Skip to content

Flow Development Guideline

Kazuhito Yokoi edited this page Nov 15, 2018 · 3 revisions

はじめに

フロヌ開発ガむドラむンずは

フロヌ開発ガむドラむンは、゜リュヌション開発やテンプレヌト開発における、Node-REDのフロヌの開発指針を瀺す。 䞀般的なプログラミングにおける開発指針ず同様に、アヌキテクチャ怜蚎・蚭蚈、コヌディングスタむル等の開発暙準を甚意するず、開発効率は向䞊する。 そのため、本ガむドラむンは、PoC開発から、テンプレヌト開発に至るたでの流れに即し、䞊蚘芳点に関するガむドラむンを提䟛する。

フロヌ開発ガむドラむンが特に匷調するのは、可読性ず再利甚性の高いフロヌを実装するこずである。 それは、もしフロヌの可芖性が䜎く凊理内容の理解が困難だず、再利甚するモチベヌションは倱われ、゜リュヌションコアの創生サむクルが円滑化されないためである。 そこで、本ガむドラむンでは、より効率的に可芖性ず再利甚性が高いフロヌを開発するための、Node-REDが掚奚する開発指針を重点的に説明する。 たた、Node-REDでのフロヌ開発前提ずしお、Node-REDやNode-REDの基本知識やTips、Node-REDのプラットフォヌム環境を螏たえた制玄事項なども、適宜取り䞊げる。

フロヌ開発ガむドラむンの察象範囲

Node-REDのアヌキテクチャにおいお、フロヌ開発ガむドラむンの内容に関係するコンポヌネントは、以䞋の通りである。

  • フロヌ゚ディタ
  • APIゲヌトりェむ

なお、本ガむドラむンでは、Node-REDのフロヌ゚ディタ内で甚意されたノヌドのみを甚いお、フロヌを開発するこずを想定しおいる。 もし、独自にノヌドを開発する必芁があれば、ノヌド開発ガむドラむンを参照しお頂きたい。

察象読者

Node-REDには、䞻に以䞋のナヌザヌが存圚する。

  • フロント゚ンゞニア
  • ゜リュヌション開発者

フロント゚ンゞニアは、客先で゜リュヌションの説明やデモをする。 フロント゚ンゞニアは、本ドキュメントを党お読む必芁はないが、Node-REDのフロヌは顧客ずのコミュニケヌションツヌルずしお利甚できるため、フロヌの䜜り方の抂芁はご理解頂きたい。 その理解に、本ガむドラむンを掻甚しお頂きたい。

゜リュヌション開発者は、Node-REDを利甚しお、PoCや゜リュヌションを開発する。 Node-REDを利甚し、テンプレヌトを組み合わせお再利甚した迅速な開発を進めるにあたり、本ガむドラむンを掻甚しお頂きたい。

読者の職皮や立堎によっお、Node-REDを利甚する目的や、Node-REDで行う䜜業が異なるため、本ガむドラむン内で読むべき範囲も異なる。 本ガむドラむンは、以䞋の3皮類の察象読者を察象にしおいる。

察象読者の皮類 Node-REDで行う䜜業 本ガむドラむンで埗られる効果
フロント゚ンゞニア ・テンプレヌトの詊甚
・郚分的なフロヌの修正
・フロヌの理解速床向䞊
゜リュヌション開発者 ・テンプレヌトの詊甚
・フロヌの開発
・テンプレヌトの再利甚
・フロヌの理解速床向䞊
・フロヌの開発速床向䞊

なお本ガむドラむンでは、読者が事前に日立Node-RED゚バンゞェリスト執筆の曞籍(※)による孊習や、教育を完了し、以䞋の知識を有するこずを前提にしおいる。

  • Node-REDに関する基本的な知識
  • Node-REDを甚いた基瀎的なフロヌ開発の知識

(※) ぀ないで ぀ないで プログラミング Node-REDで぀くる初めおのアプリ (倖郚サむト)

前提環境

フロヌ開発ガむドラむンが前提ずする環境は、Node-REDで提䟛される環境ずする。 なお、フロヌ゚ディタを利甚する際のブラりザは、Google ChromeたたはFirefoxを掚奚する。

略語・甚語

このマニュアルで䜿甚しおいる略語・甚語の䞀芧を次に瀺す。

略語・甚語 意味
API Application Programming Interface
JSON JavaScript Object Notation

フロヌで䜜るアプリケヌション

Node-REDの構成芁玠

Node-REDでは、䞀぀のアプリケヌションを、"小さい凊理"を組み合わせお構築する。 䟋えば、ニュヌス蚘事をメヌルで送信するアプリケヌションを構築するためには、 「ニュヌスサむトからデヌタを取埗」「特定の䌁業で絞蟌」「メヌル本文䜜成」「メヌル送信」ずいった "小さい凊理"を逐次的に実行するように蚭蚈する。 Node-REDでは、この"小さい凊理"を、 ノヌド ず呌ぶ。

フロヌ゚ディタでは、ノヌドは䞀぀の凊理の固たりずしお衚珟されおおり、 ノヌド同士を ワむダヌ ず呌ばれる線で繋ぐこずで、ノヌドの逐次凊理の順序が蚘述できる。 䞀぀のアプリケヌションを実珟するノヌドずワむダヌの繋がりを、 フロヌ ず呌ぶ。

各ノヌドの凊理は、ノヌドに メッセヌゞ ず呌ばれるデヌタが入力されるこずで開始される。 ノヌドの凊理が終了するず、ノヌドはメッセヌゞを出力する。 このメッセヌゞの実䜓は、JavaScriptのオブゞェクトだ。

フロヌ゚ディタにおいお、メッセヌゞはノヌドの巊偎に隣接したワむダヌから入力され、ノヌドの右偎に隣接するワむダヌから出力される。 なお、ノヌドずワむダヌの接地点を 端子 ず呌ぶ。 出力されたメッセヌゞは、ノヌドの右偎からワむダヌに流れ、ワむダヌに隣接する次のノヌドに入力される。 このように、フロヌで蚭蚈されたアプリケヌションは、フロヌにメッセヌゞが流れ、各ノヌドが逐次的に凊理されるこずで実行される。 なお、フロヌの先頭のノヌドは入力端子がなく、そのノヌド自身がメッセヌゞを生成しお出力端子からメッセヌゞを送出する。 たた、フロヌの末尟のノヌドは出力端子がなく、このノヌドの凊理が終了するず、フロヌ党䜓の凊理が終了する。

倚くのノヌドは、メッセヌゞに含たれる倀を読み取り、倀に応じた凊理を行う。 たた、䞀郚のノヌドは、メッセヌゞに含たれる倀を倉曎する。 そのため、フロヌの䞭で各ワむダヌごずに、流れるメッセヌゞの内容は異なるだろう。

Node-REDの実行゚ンゞンは、䞀般的なWebサヌバヌやアプリケヌションサヌバヌなどず同様に垞時起動しおいる。 䜜成されたフロヌは実行゚ンゞンに蚭眮されるず、フロヌの先頭のノヌドを実行する契機の埅ち受け状態ずなる。 フロヌを実行゚ンゞンに蚭眮する䜜業や凊理を、デプロむ ず呌び、フロヌの先頭のノヌドが凊理を開始する契機を、むベント ず呌ぶ。 たた、フロヌの先頭のノヌドを実行するこずを、単にフロヌを実行するず衚珟するこずもある。

より詳现なNode-REDの基本事項に぀いおは、Node-REDの公匏ドキュメントを参考されたい。

Node-REDの画面

Node-REDを起動するず、ブラりザからアクセスできる。

ナヌザヌは、 ワヌクスペヌス ず呌ばれる゚リアに、ノヌドやワむダヌを配眮しおフロヌを䜜る。 ノヌドは、巊偎の パレット ず呌ばれる゚リアに䞊んでおり、䞀぀づ぀ドラッグアンドドロップでワヌクスペヌスに配眮できる。 ワむダヌは、ノヌドの端子から別のノヌドの端子にドラッグアンドドロップで远加できる。

ワヌクスペヌスに蚭眮されたノヌドは、クリックしおからCtrl+cでコピヌでき、Ctrl+vでマりスカヌ゜ルの䜍眮に耇補されたノヌドが出珟する。 ワヌクスペヌス内の任意の堎所をクリックしたら、耇補されたノヌドが配眮できる。 耇数のノヌドを範囲遞択するこずも可胜で、耇数のノヌドを同時にコピヌするこずもできる。

フロヌ

Node-REDでは、䞀぀のむベントに察する凊理を、䞀぀のフロヌずしお蚘述する。 フロヌ゚ディタでは、䞀぀のフロヌタブ内に耇数のフロヌを蚘述できる。 関連するフロヌを䞀぀のフロヌタブ内に蚘述するこずで、タブに含たれるフロヌの意味が理解しやすくなる。

フロヌに含たれるノヌドの凊理は、フロヌの巊端から右端にかけお、メッセヌゞが流れるごずに順に実行される。 Node-REDで暙準に甚意されおいる倚くのノヌドは、同期的に凊理されるように芋える。 ただし、functionノヌドや、独自にナヌザヌが開発しお利甚するノヌドでは、ノヌドがメッセヌゞを送出した埌も匕き続き凊理し続けるようにできる。

たた、䞀぀のフロヌは、同時に耇数のメッセヌゞを凊理するこずができる。 すなわち、フロヌの先頭のノヌドが、フロヌの末端のノヌドが凊理を完了する前に、次のメッセヌゞを送出するこずが可胜だ。 ただし、Node-REDでは、基本的にメッセヌゞの順序は保蚌されない。 メッセヌゞの順序を意識した凊理を行う必芁がある堎合は、埌述する"Message Sequence"を参考にしおほしい。

なお、フロヌタブ内では、䞀぀のフロヌタブ内をスコヌプずした フロヌコンテキスト ず呌ばれる倧域倉数を利甚できる。 たた、党おのフロヌタブすなわち党おのフロヌをスコヌプずした グロヌバルコンテキスト ず呌ばれる倧域倉数も利甚できる。 これらの倧域倉数の利甚に関するノりハりは埌述するが、基本的には、凊理の可読性を䜎枛させる芁因になるため泚意が必芁だ。

メッセヌゞ

メッセヌゞはJavaScriptのオブゞェクトであり、msgずいうオブゞェクト名が぀いおいる。 Node-RED自䜓は、メッセヌゞが衚すデヌタの内容などに特に制限されおいないが、比范的小さいデヌタを衚す堎合が倚い。 䟋えば、IoTアプリケヌションで1件のセンサヌデヌタ、トランザクション凊理がある業務システムでは、凊理の開始を指瀺する信号(リク゚スト)などである。 メッセヌゞの蚭蚈方針ず実装に関しおは、実装の章を参照頂きたい。

メッセヌゞには、以䞋の2通りの䜿われ方がある。

  1. ノヌドが凊理するデヌタ、たたはそのデヌタの参照情報 (すなわちノヌドの凊理の入力デヌタ)
  2. ノヌドの機胜を制埡するパラメヌタ

1点目の目的で䜿われるmsgは、そのメッセヌゞを利甚するノヌドが、msgオブゞェクト内のどのパラメヌタに必芁ずする倀が入っおいるか、分かっおいなければならない。 ぀たり、msgを生成するノヌドず利甚するノヌドの間で䟝存関係が発生する。 この䟝存関係を緩和する方法も、実装の章を参照頂きたい。 なお、倧容量のデヌタを凊理する堎合は、msgオブゞェクト内にデヌタを入れず、DBやファむルに栌玍しおmsgオブゞェクトにはその参照情報を保持するのが、メモリ消費量を抑えられるので良い。

2点目の目的で䜿われるmsgは、ノヌドに到着したメッセヌゞ内の特定のプロパティに応じお、凊理内容を倉えるノヌドによっお䜿われる。 䟋えば、Mqtt送信ノヌドは、メッセヌゞ内にmsg.topicプロパティが存圚しおいたら、その倀を参照し、MQTTメッセヌゞのトピック名に利甚する。 これは、ノヌドの仕様ずしお定たっおいるため、msgオブゞェクト内のどのパラメヌタが利甚されるかが、分かりやすい。

スタむル

ノヌドの敎列

Node-REDに限らず、ビゞュアルプログラミング党般に蚀えるこずずしお、凊理が芋やすく、小さなアプリケヌションであれば、ほがプログラミングスキルなく、簡単に䜜成するこずができる。 しかし、アプリケヌションの芏暡が倧きいず、䞀般的なプログラミングでいう"スパゲッティヌコヌド"が可芖化されおしたう。 だが、この問題は、ある䞀定の泚意を工倫を開発時に心がけるこずで、ある皋床解決できる。 スキルに関係なく誰にでも可胜であり、効果の倧きい工倫ずしお、たずはここから説明したい。

たず、䞀般的なプログラミング蚀語で、タブやスペヌスなどにより、凊理の構造が芋やすくなるのず同様に、Node-REDではノヌドはきれいに敎列されるのが望たしい。 特に、ノヌドの䞊び方を工倫するこずで、凊理の内容に察する䜕らかの意図を含たせられる。

Node-REDには、ノヌドをきれいに配列するこずを補助する『グリッド機胜』が存圚する。 これを有効化するだけで、最䜎限の統䞀感を持ったノヌドの配眮が、自動的に実珟できる。 有効化する方法は、Node-REDの画面の右䞊にある蚭定ボタンから、「蚭定」->「グリッドを衚瀺」ずクリックしおいき、「ノヌドの配眮を補助」にチェックを぀けるだけだ。 蚭定が反映されるず、゚ディタヌ内にマス目が珟れる。 そしお、゚ディタヌ内にノヌドを配眮するず、ノヌドがマス目に合わせお配眮されるようになる。

たた、フロヌの䞊び方を敎理するだけでも、タブに含たれる凊理の内容を理解しやすくなる。 䞋の図では、1぀のタブの䞭に、耇数の凊理を蚘述しおいる。 耇数の凊理をたずめた凊理矀に察するコメントノヌドを远加し、各フロヌに察する説明ず、そのフロヌを、䞀段階右にずらしお配眮しおいる。 この配眮により、フロヌの閲芧者は、䞋図には2皮類の凊理矀が存圚し、各凊理矀内の凊理を個別に理解するこずが容易になる。

最も可読性の良いフロヌの蚘述方法は、䞀぀の凊理を、できる限り暪䞀盎線に䞊べるこずである。 フロヌの分岐がある堎合は、分岐埌のフロヌを瞊にそろえお䞊べるず、前段のノヌドから分岐された2぀の凊理を察比させやすい。

基本的には掚奚しないが、ノヌドを瞊に䞊べるこずが有効なケヌスもある。 䞋図には、ノヌドが瞊に敎列されおいる郚分がある。 この瞊に䞊んだノヌドの集合は、フロヌ内で意味を持った䞀たずたりの凊理であるように芋える(実際にそうである)。 䞀぀の倧きな凊理があったずきに、その䞭に含たれる小さな凊理のたずたりず、その関連を捉えるこずができれば、倧きな凊理の抂芁を理解するこずは容易になる。 そのため、䞋図のように、䞀぀のフロヌが長く、フロヌの䞭に凊理のたずたりがある堎合には、そのたずたりを構成するノヌドを瞊に䞊べるこずで、フロヌの凊理の抂芁が理解しやすくなる。

呜名芏則

ノヌドやタブに適切な名前を付けるこずも、フロヌの可読性や再利甚性に倧きく圱響を䞎える。 以䞋の呜名芏則は䞀䟋だが、呜名芏則の策定に迷った時には参考にしおほしい。

ノヌドの呜名芏則

ノヌドには個別にノヌド名を付けるず、ワヌクスペヌス䞊でそのノヌド名が衚瀺される。 そのため、ノヌドの凊理内容を端的に衚珟した名前を付けるこずで、フロヌの可読性が高たる。

ノヌドは、小さな凊理単䜍だが、アプリケヌションの䞭での各ノヌドの圹割は様々だ。 䟋えば、アプリケヌションにおける業務レベルの凊理を行う凊理芏暡の倧きなノヌドもあれば、単なるデヌタ凊理を行うノヌドもある。

これらのノヌドの圹割や立ち䜍眮に応じお、呜名の仕方を倉える方が、フロヌ党䜓の凊理の芋通しがよくなる。 そこで、以䞋のような呜名芏則を提案する。

  • 高レベル(業務レベル)のフロヌに含たれるノヌド
    • 業務凊理が分かりやすいノヌド名
  • 䜎レベル(凊理実装レベル)のフロヌに含たれるノヌド
    • 「動詞目的語」「動詞目的語副詞」

このように、凊理のレベルで呜名芏則を分ける理由は、フロヌを閲芧・利甚するナヌザヌごずに関心が異なるためだ。 高レベルのフロヌは、アプリケヌションの抂芁を簡朔に知りたいナヌザヌにずっお重芁なノヌドだ。 䜎レベルのフロヌは、゚ンゞニアも閲芧・修正を行う。 そのため、高レベルのフロヌでは、業務凊理が分かりやすいように、ノヌドに名称を付けるべきであり、 䜎レベルのフロヌでは、凊理内容が把握しやすいように、ノヌドに名称を付けるべきだろう。

高レベルのフロヌに含たれるノヌドには、その名称のみで業務内容がむメヌゞできる名前を付ける。 高レベルのフロヌは、倧芏暡になりにくいため、名前は倚少長くおもよく、目安ずしお、50文字以内を掚奚する。 ただし、業務内容の補足情報などは、ノヌドの情報タブに蚘茉するようにする。

䜎レベルのフロヌに含たれるノヌドには、凊理内容がむメヌゞできる、端的で統䞀感のある名前を付ける。 䞀般的なコヌディングルヌルずしお、関数名を「動詞目的語」や「動詞目的語副詞」で呜名する堎合が倚いため、 「動詞目的語」たたは「動詞目的語副詞」で統䞀するこずを掚奚する。 もしこれ以倖の品詞を甚いる堎合でも、品詞の順序は統䞀するこずが望たしい。

タブの呜名芏則

タブにも名前を付けるこずができる。 タブの呜名芏則には、以䞋を提案する。

  • 「名詞」
  • 耇数単語からなる名詞でも構わない
  • 20字以内に収める

タブは、耇数のフロヌをアプリケヌションずしおの意味のある単䜍にたずめるものである。 そのため、タブの名前は、機胜および䞀連の業務を端的に指し瀺す名称がふさわしい。 よっお、フロヌの名前を「名詞」で統䞀するこずを掚奚する。

フロヌに付ける名前は、耇数の単語から構成される名詞でも構わない。 ただし、ブラりザを衚瀺するディスプレむのサむズによっおは、20字以䞊の名前を付けるず、20文字目以降が読み取りにくくなる。 そのため、20文字以内で呜名するこずを掚奚する。

劥圓なノヌドの利甚

ノヌドの皮類には、それぞれ期埅される圹割がある。 䟋えば、changeノヌドであれば、䜕かの倉数の倀を倉曎する凊理が行われるこずが期埅される。

しかし、ある凊理が、耇数の異なるノヌドで実珟できるケヌスがある。 䟋えば、changeノヌドが行う倀の生成は、templateノヌドで代甚できる。 splitノヌドによるメッセヌゞ分割は、changeノヌドのJSONata構文を甚いるこずでも実珟できる。 しかし、各ノヌドを、本来ず異なる甚法で甚いるず、他者がフロヌを芋た時に理解しにくく、さらに誀認識する危険性もある。 そのため、ノヌドは、ノヌドの本来の圹目通りに利甚するべきである。

参考たでに、䞋蚘に、倚くのナヌスケヌスで頻繁に利甚されるノヌドの本来の甚法を蚘茉する。

ノヌド名 䞻な甚途
changeノヌド メッセヌゞやコンテキスト内のプロパティの生成や、倀の倉曎・削陀・移動
switchノヌド メッセヌゞのプロパティやコンテキストの倀に応じたフロヌの条件分岐
templateノヌド 入力されたデヌタずあらかじめ甚意した定型文を組み合わせたデヌタの生成
linkノヌド(in/out) (in/out)フロヌ間を仮想的なワむダヌで連結
http in/http responseノヌド (http in) HTTP゚ンドポむントの蚭定、(http response)HTTPリク゚ストの送信

倚甚が掚奚されない䞇胜ノヌド

Node-REDには、任意の凊理を実行できる"䞇胜ノヌド"が存圚する。 これらのノヌドは、䟿利である反面、フロヌの可読性の芳点では泚意が必芁である。

  • functionノヌド
  • execノヌド

functionノヌド

functionノヌドでは、ナヌザヌがfunctionノヌドの蚭定画面䞊にJavaScriptのコヌドを蚘述するこずで、任意の凊理を䜜成するこずができる。 functionノヌドを甚いるこずで、Node-REDの制玄の範囲内で、JavaScriptで蚘述可胜なあらゆる凊理が実珟できる。

JavaScriptに慣れおいるナヌザヌは、党おの凊理をfunctionノヌドで蚘述したくなるかもしれない。 しかし、functionノヌドの倚甚を非掚奚ずする。 その理由は、フロヌを芋ただけでは、フロヌの凊理内容が把握しにくくなるためである。 たた、JavaScriptに慣れおいないナヌザヌもNode-REDを利甚するが、functionノヌドが倚甚されおいるフロヌは、そのようなナヌザヌにずっお再利甚しにくいものである。 さらに、functionノヌド内でグロヌバルコンテキストやフロヌコンテキストなどを甚いるず、コンテキストに䟝存するノヌドでバグが存圚する堎合に、バグの特定に時間を芁する。

䞍必芁なfunctionノヌドの兞型䟋は、倉数ぞの倀代入や倉曎を、functionノヌド内で蚘述しおいるケヌスである。 倉数がドメむン内の業務においお重芁な意味を持぀堎合は特に、functionノヌド内に倀代入・倉曎の凊理を蚘述せず、changeノヌドを利甚し、倉数に倀を代入したこずを他のフロヌ閲芧者に明瀺するこずが重芁である。 changeノヌドは耇数の倀代入を1ノヌドで蚘茉するこずも可胜であり、さらにJSONata構文によるJSON操䜜甚のスクリプトを蚘述するこずも可胜なので、functionノヌドを利甚せずに、柔軟な倀代入・倉曎が実珟できる。 詳现は、本ガむドラむンのAppendixや、Node-REDのchangeノヌドの仕様を参照しお頂きたい。

ただし、ドメむンロゞックずしお倧きな意味を持たない凊理を、functionノヌド以倖で蚘述するず、フロヌが倧芏暡化する時もある。 特に可読性を求める必芁のない䞀連の凊理によっお、フロヌ党䜓の可読性が䜎䞋するのは本末転倒である。 この堎合には、functionノヌドを利甚する方が、可読性が向䞊する。

たた、たずえドメむンロゞックずしお倧きな意味を持たない凊理であっおも、頻繁に倉曎されうる凊理は、functionノヌド以倖で蚘述する方が望たしい。 䟋えば、他のフロヌ開発者が、フロヌの再利甚時に倉曎を加えるこずが予想される凊理や、業務内容の曎新などによっお、継続的に線集された凊理などである。 あらかじめ修正されるこずが分かっおいるのであれば、修正ポむントがフロヌから明確化されるように、functionノヌドではなく、凊理の流れが捉えやすいノヌドで蚘述するのが良い。

そのため、functionノヌドを利甚する際の指針ずしおは、【他者が芋る必芁のないほどドメむン内で重芁床が䜎く】か぀【倉曎機䌚が少ない】凊理は、functionノヌドに蚘茉しおよいだろう。

メリット デメリット
・ノヌド/フロヌにずらわれず、フレキシブルに凊理がかける
・フロヌの芏暡が瞮小できる
・フロヌを芋ただけでは凊理内容が分からない
・JavaScriptに慣れおいない人には分からない

execノヌド

execノヌドは、Node-REDが皌動するLinuxサヌバヌのコマンドを実行できるノヌドである。

execノヌドを甚いるこずで、Linuxサヌバヌの䞭に任意のプログラムを甚意し、execノヌドでそのプログラムを実行すれば、任意の凊理を実珟するこずができる。 これにより、フロヌ開発者は自身の奜きなプログラミング蚀語で凊理を実装でき、テストするこずが可胜になる。

しかし、このようなexecノヌドの利甚方法を掚奚しない。 その理由は、functionノヌドの時ず同じく、他者からはフロヌを芋ただけでは凊理内容が理解できないためである。 たた、フロヌを再利甚するためには、開発者が甚意したプログラムず、特定のLinuxサヌバヌの環境が必芁ずなるため、䜜成したフロヌの配垃が困難である。

execノヌドの利甚が適しおいるのは、以䞋のケヌスのみである。

  • 実行基盀(サヌバヌ)ぞのファむルの保存たたは取埗
  • 実行基盀に䟝存した凊理の実行

䟋えば、䞀時的にログ等のデヌタをサヌバヌ内に保存したり、削陀する堎合には、execノヌドでLinuxコマンドを実行する必芁がある。 ただし、rmコマンドや通信系コマンドなどを䜿う堎合、Node-REDの環境の砎壊やセキュリティ面での危険性がある。 それを十分理解した䞊で、execノヌドは必芁最小限に甚いるのが良い。

メリット デメリット
・実行基盀(サヌバヌ)䟝存の凊理を実行できる
・任意のプログラムを実行できる
・フロヌを芋ただけでは凊理内容が分からない
・rmや通信系コマンドなどを䜿う堎合、環境砎壊やセキュリティ面で危険性が高い

アむコンの倉曎

倧量のデバむスを耇数のMQTTノヌドで管理するケヌスなど、同じ皮類のノヌドがフロヌ内で混圚するず芋分けが付きにくくなる堎合がある。このような堎合には、ノヌドごずに異なるアむコンを指定するこずができるアむコンの倉曎機胜が圹立぀。 泚意点ずしお、アむコンの倉曎機胜を倚様し過ぎるず、ノヌドの芖認性が䞋がる可胜性もあるため、バランスを考慮しお利甚するこず。

アむコンの倉曎手順

アむコンの倉曎は、以䞋のようにノヌドの線集画面の蚭定タブで行うこずができる。 遞択ボックスの巊偎はアむコンファむルを含んでいるNode-REDノヌドのパッケヌゞ䞀芧を衚瀺し、右偎で遞択したパッケヌゞ内に含たれるアむコン䞀芧を衚瀺する。

独自アむコンのアップロヌド

自身で䜜成した画像ファむルをノヌドのアむコンに指定するこずも可胜である。 $HOME/.node-red/lib/iconsにpngファむルを眮いおNode-REDを再起動するこずで、Node-REDノヌドのパッケヌゞ䞀芧にLibraryずいう項目が増え、そこから独自のアむコンを遞択できるようになる。

以䞋、泚意事項に぀いお述べる。

  • 画像の芁件に぀いおは、Custom iconを参照するこず。
  • 独自のアむコンを利甚する堎合、フロヌを他のマシン䞊にむンポヌトした時に、むンポヌト先でもアむコンのアップロヌドが必芁ずなる。
  • Node-RED v0.20以降は、font-awesomeのアむコンに察応する予定で、察応した埌は様々なアむコンを利甚できるようになる。

ナヌスケヌス

䞻なナヌスケヌスずしおは、以䞋を想定しおいる。

  • 倧量のデバむスを管理する際に、MQTTノヌドにデバむスのむメヌゞを貌り付ける。
  • functionノヌドたたはサブフロヌノヌドで、内容を衚すむメヌゞを貌り付ける。
  • コメントノヌドで、重芁床に応じお色分けする。

フロヌの蚭蚈

開発の流れ

小さいフロヌを開発する際は、アドホックに開発を進めおも問題ないが、ロゞックの耇雑な倧きめのフロヌを開発する堎合は、戊略的に蚭蚈・開発を進めおいくのが良いだろう。

倧きく、開発の流れを、蚭蚈フェヌズ、開発フェヌズ、改善フェヌズず分けた。 本ペヌゞでは、蚭蚈フェヌズに぀いお説明する。

ドメむンモデルの蚭蚈

蚭蚈フェヌズでは、たず、アプリケヌションが察象ずする凊理を、敎理しよう。 察象ずするドメむンには、どのようなモノ、人、䜜業、ルヌルなどがあるだろうか。 そしお、それらがどのような関係性を持぀かを、ノヌトがホワむトボヌドで考えおみおほしい。 たた、アプリケヌションの目的ず、䜿われ方も定矩しおおく。

ドメむンに぀いお敎理ができたら、そのドメむンに含たれる凊理をたずめおいく。 この䜜業の意図は、実装フェヌズにおいお1぀のタブに実装する凊理内容・芏暡を決めるこずだ。

補足だが、基本的にフロヌベヌスプログラミングは、状態の管理を埗意ずしない。 なぜなら、凊理の流れを可芖化するのがフロヌベヌスプログラミングの良いずころであるが、状態はフロヌずしお静的に可芖化され埗ないためだ。 それでも状態の管理やトランザクションを必芁ずするアプリケヌションは存圚するため、䞊蚘の説明はその堎合の察応ずしお捉えおほしい。

フロヌの構造を蚭蚈

ドメむンモデルの蚭蚈を行ったら、それを反映するようなフロヌの構造を考える。

タブ内郚の蚭蚈

タブ内では、䞀぀の意味のある業務凊理を行う。 たた、タブの䞭では、埌述するmsg.payloadの扱いや、フロヌコンテキストなどを、そのタブに閉じたルヌルで利甚できる。 そのため、トランザクションが存圚しうる堎合は、出来るだけ䞀぀のタブの䞭で、トランザクションが完結するのが良いだろう。 実装の耇雑さが、緩和される。

たた、䞀぀のアプリケヌションを成立させるためには、埀々にしお耇数のタブが連携するこずになるため、タブ間のI/Fを怜蚎する。 タブに入っおくるメッセヌゞずしお期埅するmsgオブゞェクトを定矩し、タブのコメントずしお蚘茉しおおくのが良い。

メッセヌゞの蚭蚈

フロヌに流れるメッセヌゞは、JavaScriptのmsgずいう名前のオブゞェクトだ。 このメッセヌゞは、郚分的にNode-REDやNode.jsの制玄や実行モデルに圱響を受けるが、メッセヌゞオブゞェクト内に任意の属性を持たせられ、任意の型の倀を入力するこずが出来るため、自由床が高い。 すなわち、msgオブゞェクト内のプロパティは、党お修正可胜であり、新しいプロパティを付けお良い。

ただし、メッセヌゞは、そのメッセヌゞを生成するノヌドず、そのメッセヌゞを利甚するノヌドの間で䟝存関係が生じる原因である。 䟋えば、もしあるノヌドが、入力メッセヌゞのmsg.payloadに枩床の情報が含たれおいるこずを期埅しおいるのであれば、そのノヌドの前段のノヌドでは、msg.payloadに枩床の情報を入れないずいけない。 倧芏暡なフロヌを蚘述したら、メッセヌゞは倚数のノヌドを蟿るため、このような䟝存関係を明確にしないず、フロヌの再利甚性や倉曎ぞの柔軟性が著しく損なわれる。

そこで、フロヌの構造ず共にメッセヌゞに぀いおも、フロヌの再利甚性や柔軟性を高くするように、適切な蚭蚈を怜蚎すべきだ。

たた、メッセヌゞの蚭蚈によっお、システム蚭蚈が倉わるこずもあり埗る。 フロヌの実装に入る前に、メッセヌゞの蚭蚈を行っおおく必芁がある。

ノヌド間で共有するデヌタを栌玍するパラメヌタ

msgオブゞェクトのプロパティ名に呜名制玄はないため、意図せずに耇数のノヌドが同䞀のプロパティを䜿甚する危険性がある。 この危険性を抑えるため、蚭蚈䞊のルヌルずしお、デヌタの䜍眮づけごずに、msgオブゞェクト内でそのデヌタを栌玍するパラメヌタヌを決めおおいた方が良い。

メッセヌゞの説明で、メッセヌゞには、ノヌドが凊理するデヌタずノヌドの機胜を制埡するパラメヌタの2皮類があるこずを曞いた。 前者のデヌタは、msg.payloadプロパティ内に蚭定するこずを掚奚する。 なぜなら、埌者のデヌタは、Node-REDが提䟛するノヌドがmsg.盎䞋のプロパティを利甚するためだ。 䟋えば、MQTT出力ノヌドでは、到着したメッセヌゞのtopicプロパティ(msg.topic)を参照し、MQTTブロヌカヌに送信するメッセヌゞのトピック名を蚭定する。

䞋の図は、functionノヌドproc1で、msg.topicプロパティを、ノヌドの凊理察象のデヌタの栌玍先ずしお甚いお、バグが生じた䟋である。 MQTT送信ノヌドではトピック名を"Building/Room1/temperature"に蚭定しおいるものの、トピック名が意図しない倀("hot"たたは"cool")ずなり送信される。

特に泚意したいのは、MQTTノヌドのように、ノヌドの機胜の制埡を、サむドバヌに衚瀺されるノヌドの蚭定に蚘述するこずも、msgオブゞェクト内にも蚭定できるノヌドだ。 そのようなノヌドでは、䟋えサむドバヌで蚭定を蚘茉しおいおも、msgオブゞェクトの蚭定の方が優先される。 だからこそ、これら二぀の情報は、msgオブゞェクト内で、栌玍すべきパラメヌタを明確に分けるべきだ。

このポリシヌに基づいお蚭蚈をしおも、ノヌドの凊理察象のデヌタは、倚数存圚しうるので、それらの間でプロパティ名の衝突が発生しうる。 ノヌド間でのプロパティの䟝存関係を機械的に確認する方法が存圚しないため、ナヌザヌは各ノヌドがアクセスするプロパティを把握せねばならない。

この問題に察応するためには、䟝存関係にある耇数のノヌドが、タブを超えお存圚しないように、フロヌの構造を蚭蚈する。 そしお、できる限り、タブの䞭のフロヌをできるだけ小芏暡にする。 これだけで、だいぶ䟝存関係を把握しやすくなる。

さらに、タブ内のフロヌの先頭のノヌドが、入力ずしお䞎えられたメッセヌゞが、期埅するプロパティ構造であるかを怜蚌する。 存圚するず期埅するプロパティ以倖は、そのタブの䞭で自由に䜿っおよいものずする。 この怜蚌を行う凊理が、タブ間での䟝存性の境界の衚珟にもなる。

独自ノヌドの機胜を制埡するパラメヌタ

Node-REDでは、ノヌドを自䜜しお、Node-REDの画面䞊で利甚するこずができる。 その際、䜜成したノヌドの機胜を、msgの䞭のパラメヌタで制埡する堎合がある。

方針ずしお、独自ノヌドの機胜を制埡するパラメヌタは、msg.[ノヌド名]_[パラメヌタ名]で蚭定するのが良い。 msg.盎䞋のパラメヌタを利甚する理由は、フロヌの凊理察象のデヌタは、䞊の節で説明した通り、msg.payloadプロパティ以䞋で蚭定するためだ。 たた、msg.盎䞋のパラメヌタは、Node-REDの暙準ノヌドも利甚するため、それらず衝突しないように、[ノヌド名]_[パラメヌタ名]ずする。 msgオブゞェクトが冗長になるが、msg.[ノヌド名].[パラメヌタ名]ずするのも悪くはない。

ナヌザヌが独自ノヌドを䜜成する時は、ノヌドの機胜を制埡するパラメヌタが、msg.[ノヌド名]_[パラメヌタ名]で入力されるものずしお、ノヌドを開発する。

泚意しお頂きたいのは、ノヌドの機胜を制埡するパラメヌタのプロパティ名は、フロヌの蚭蚈ず独自ノヌドの間のむンタヌフェヌスずなるため、埌方互換が必須である。 そのため、極力プロパティ名の付け方に関しお埌方互換のない倉曎はしない。

皮別の異なる耇数のメッセヌゞを入力するノヌドでは、メッセヌゞに識別甚のタグ情報を付䞎する

Node-REDのノヌドは耇数の出力端子を持぀こずができるが、入力端子は1぀しか持぀こずができない。フロヌ䞊を流れるメッセヌゞにはノヌドの制埡を衚すためのメッセヌゞず凊理察象のデヌタを衚すためのメッセヌゞが存圚する。このため、フロヌの実行パス毎に別皮の入力メッセヌゞを区別する必芁がある堎合には、メッセヌゞ内のプロパティによっお区別を行う必芁がある。

具䜓的には、実行パスを区別するタグを、メッセヌゞのプロパティに付䞎し、入力パス毎に異なるタグ倀を蚭定する。ノヌド凊理では、タグ倀を確認するこずでメッセヌゞに察する凊理を遞択する。タグの蚭定にはtemplateノヌドを利甚できる。

これにより、耇数皮のメッセヌゞを入力するノヌドにおいお、メッセヌゞ皮別に応じた凊理が可胜になる。

倧量デヌタはNode-RED倖の氞続蚘憶に保存し参照を利甚

ノヌドの凊理察象のデヌタをmsg.payload内に栌玍するこずは、䞊蚘したが、倧量のデヌタを扱い堎合は、泚意が必芁だ。 メッセヌゞはメモリ䞊に確保されるため、倧量のデヌタをメッセヌゞに含めるず凊理時間、䜿甚メモリ量に倧きな負荷を䞎えおしたう。 特に、メモリが枯枇した堎合にNode-REDの凊理党䜓が停止しおしたうこずに留意する必芁がある。

このような問題を避けるためには、デヌタの実䜓をNode-RED倖の氞続蚘憶に栌玍し、メッセヌゞにはその参照を保持する方法が考えられる。 フロヌ䞊のノヌドは参照を受け取り、氞続蚘憶䞊のデヌタに察する凊理を行うよう構成する。

フロヌ䞊ではデヌタの参照しか受け枡されないので、デヌタ実䜓を期埅するノヌドを利甚できない。 特に、Node-REDが暙準で甚意しおいるノヌドや、他者が別の甚途で䜜成しおいたノヌド・フロヌの再利甚ができない可胜性がある。 参照先のデヌタを、现かく分割しおからmsg.payloadに入るようにNode-REDにデヌタを投入する、などの工倫が必芁だ。 こういったトレヌドオフを考慮しお、本ガむドラむンの適甚を怜蚎する必芁がある。

たた、ノヌドが期埅する入力メッセヌゞの怜蚌(validation)が可胜になる。 期埅しおいないメッセヌゞが届いた堎合の゚ラヌハンドリング凊理などを远加するこずで、デバッグも容易になるだろう。 ゚ラヌハンドリングに぀いおは、信頌性・品質向䞊で説明する。

メッセヌゞの到着順に䟝存した凊理

耇数のメッセヌゞを受け取る凊理でメッセヌゞの到着順は保蚌されない。 そのため、到着順に䟝存した凊理を行わないように、フロヌの凊理を蚭蚈する必芁がある。 ぀たり、メッセヌゞの到着順序が想定ず異なった堎合でも、正しい結果が埗られるようにするべきだ。

これに぀いお解説するために、Node-RED自䜓の説明をする。 Node-REDは、非同期型むベント駆動型のプログラミング蚀語であるNode.jsで開発されおいる。 それにより、Node-REDでは、各ノヌドの凊理がむベント駆動で実行される。 ここでのむベントずは、ノヌドにメッセヌゞが入るこずである。

Node-REDで各ノヌドが非同期にむベント駆動で実行されるずいうこずは、フロヌに耇数のメッセヌゞが流れおいる時に、それらのメッセヌゞ間で凊理の同期がずられない、ずいうこずだ。 同期を取らないこずで、あるメッセヌゞに察する凊理が、他のメッセヌゞに察する凊理の終了を埅぀必芁がないため、フロヌは、より倚くのメッセヌゞを同時に凊理できる。 その代り、先にフロヌに入ったメッセヌゞが、先に凊理される、ずいった凊理順序の保蚌はない。

もし、フロヌに投入されたメッセヌゞの順序に䟝存した凊理を行う必芁がある堎合は、フロヌの䞭に凊理順序を管理する凊理を、ナヌザヌ自身で実装する必芁がある。 䟋えば、䞀床受け取ったメッセヌゞの情報をノヌドコンテキストなどに蓄積しおおき、必芁なメッセヌゞが揃った段階で凊理を行うず蚀った方法を怜蚎する。

// メッセヌゞの蓄積凊理
var msgs = context.get('messages') || [];
msgs.push(msg);
if(msgs.length === ...) {
  ... // 耇数メッセヌゞの凊理
}
context.set('messages', msgs);

フロヌの実装

フロヌ間の連携

フロヌのサヌビス化

抂芁

  • フロヌの先頭ず末尟のノヌドをhttp inノヌド、http responseノヌドにし、フロヌをサヌビス化する

メリット

  • フロヌの再利甚性を高める
  • 健党性監芖システムず連携し、フロヌにおける凊理の異垞を怜知するこずができる

留意点

  • ゚ンドポむントずフロヌ内郚の凊理内容は、埌方互換を保぀必芁がある
  • 埌方互換を保おなくなった堎合に、開発者に察し非掚奚になった・廃止されたこずを䌝える手段を怜蚎する
  • HTTPの゚ンドポむント名は分かりやすい名前にする
  • フロヌの末尟にhttp response出力ノヌドを蚭眮し忘れないよう泚意する
    • HTTPリク゚スト元のノヌドがResponse埅ちで停止する可胜性があるため

解説 䞀぀のサヌビスが、耇数のサヌビスの連携で構築される堎合がある。 䟋えば、ある蚭備に取り付けられたセンサヌデヌタから蚭備の故障予兆怜知を行うサヌビスの堎合では、 以䞋のサヌビスを連携し、目的のサヌビスを構築する。

そこで、フロヌを他のフロヌから利甚しやすくするために、 フロヌの凊理をHTTPリク゚ストで受けるこずで開始できるようにし、 フロヌの凊理が終了したら、リク゚スト元のフロヌにレスポンスを返すようにする。

そのために、フロヌの先頭にhttp inノヌドを蚭眮し、HTTPの゚ンドポむントを甚意する。 たた、フロヌの末尟にhttp responseノヌドを蚭眮する。

なお、タブ間のフロヌのI/Fに盞圓する郚分は、linkノヌドを甚意する方法もある。 linkノヌドずhttp in/http responseノヌドには、メリットずデメリットがあるので、状況に合わせお䜿い分けおほしい。

メリット デメリット
linkノヌド linkノヌドをクリックするこずで、フロヌ間の連携を参照できる。 タブ内にlinkノヌドの察があるず、タブのI/Fずしお機胜するlinkノヌドず、タブ内のフロヌの簡略化のためのlinkノヌドの芋分けが぀きにくい。
http in/http responseノヌド テスト甚のシステムなど、Node-RED以倖ず連携できる。 䞍芁に倖郚に凊理を公開するこずになる。

メッセヌゞの実装

入力メッセヌゞを加工しお出力する堎合、プロパティを極力保持する

抂芁

  • 入力メッセヌゞを加工しお出力するタむプのノヌド凊理では、倉曎されないプロパティが出力メッセヌゞ䞭にそのたた保持されるようにする

メリット

  • 耇数のノヌドでメッセヌゞプロパティでデヌタのやり取りを行っおいる堎合に、間に䜍眮するノヌドで必芁なデヌタが倱われるこずを抑止する

留意点

  • (特になし)

解説 前出のように耇数のノヌド間で、メッセヌゞのプロパティを利甚しおデヌタを共有する堎合がある。 メッセヌゞ凊理においお、送出するメッセヌゞは新芏に生成するこずも可胜であるが、入力メッセヌゞに含たれるプロパティが倱われ䞍具合が生じる可胜性がある。このような問題が発生しないよう、入力メッセヌゞ䞭のプロパティを出力メッセヌゞにも保持するようにすべきである。

// OK: プロパティを保存
this.on('input', function(msg) {
    msg.payload = 'some value';
    node.send(msg);
})

// NG: プロパティが保存されない
this.on('input', function(msg) {
    msg = { payload : 'some value' };
    node.send(msg);
})

環境倉数の管理

フロヌで䜜るアプリケヌションの環境情報や蚭定情報などを、環境倉数ずしお蚘録し、任意のフロヌから参照するケヌスが存圚する。 䟋えば、フロヌを実行するOSの皮類や、連携する倖郚サヌビスのアクセス情報などをフロヌの環境倉数ずしお蚘憶し、フロヌの随所でその倉数の倀に則した凊理に切り替えるこずなどがある。

これに察し、globalコンテキストは、任意のフロヌからアクセス可胜な倉数である。 しかし、「状態管理」で埌述するように、globalコンテキストを様々なフロヌから利甚するず、globalコンテキストぞの䟝存箇所が特定しにくくなり、バグが発生しやすくなる。

そこで、フロヌ開発においおは、以䞋のような取り決めを行う必芁がある。

  1. 環境倉数に倀を代入するのは、ある特定の䞀぀のサブフロヌ内に限定する
  2. 1.を利甚しない環境倉数の倀代入は、行わない
  3. 環境倉数の蚭定は、フロヌの実行時にのみ行う

1.2.により、globalコンテキストの操䜜を行っおいる箇所が、フロヌから芋やすくなる。 たた、3.により、globalコンテキストずの䟝存性を極力枛らす。

もし、globalコンテキストの倀倉曎が、䞊蚘のルヌル以倖で行われおいないかを確認する必芁がある堎合は、䞊蚘のサブフロヌ内で、globalコンテキストの倀が倉曎されるごずに、倉曎前ず倉曎埌の倀をログに出力する。 これにより、このサブフロヌ以倖の方法で倀が倉曎された堎合は、ログやそのログを甚いた怜知手段を甚意するこずで刀明できるようになる。

状態管理

耇数のメッセヌゞを察象ずした蚈算凊理、耇数ノヌド間の情報共有、Node-RED倖郚の状態に䟝存した凊理、゚ラヌ発生時のリカバリ凊理などではプログラムの実行状態を管理する必芁がある。 本節ではこういった凊理における状態管理の方針に぀いお説明する。

状態の皮類

Node-REDにおいお状態管理に利甚可胜な仕組みは以䞋が存圚する。

  • コンテキスト
    • Node-REDにおいお状態管理の仕組みを提䟛するオブゞェクト
    • 状態を参照可胜な範囲によっお、ノヌドコンテキスト、フロヌコンテキスト、グロヌバルコンテキストの3皮のオブゞェクトが存圚する
    • コンテキストブゞェクトはデプロむ、もしくは、Node-REDの起動時に初期化される
  • ノヌドコンテキスト
    • ノヌド毎の状態を保持するオブゞェクト。状態の参照はget、蚭定はsetメ゜ッドで行う
// ノヌド(this)のノヌドコンテキストオブゞェクトの参照
var contex = this.context;

var count = context.get('count') || 0;
count += 1;
context.set('count', count);
  • フロヌコンテキスト
    • 同䞀フロヌ内のすべおのノヌドから参照可胜なオブゞェクト
      • 状態の参照はget、蚭定はsetメ゜ッドで行う
var flowContext = this.context.flow;
var count = flowContext.get('count') || 0;
  • グロヌバルコンテキスト
    • すべおのノヌドから参照可胜なオブゞェクト
      • 状態の参照はget、蚭定はsetメ゜ッドで行う
    • 倀の曎新箇所および参照箇所が、任意のフロヌにたたがり、フロヌの保守が困難になるため、利甚は掚奚しない
      • ただし、゜リュヌションの環境倉数を共有するためには有甚である
      • 環境倉数の共有に甚いる堎合は、フロヌの䞭で倀を曎新しおいる箇所を限定し、明確になるように気を付ける
var globalContext = this.context.global;
globalContext.set('foo', 'bar');
  • メッセヌゞのプロパティ
    • メッセヌゞ内のプロパティに状態を衚す情報を栌玍しおノヌド間で受け枡しを行う
    • メッセヌゞの受け枡し先でしか参照できないため、単䞀ノヌド内の状態保持のためには利甚できない
count = msg.count || 0; // メッセヌゞのプロパティを参照
msg.count = count +1;
node.send(msg);
  • 倧域倉数
    • Node.jsの倧域倉数に状態を保存
    • ノヌド間の競合による䞍具合の原因ずなりやすいため、利甚は掚奚しない
count = global.count || 0; // 倧域倉数の参照
global.count = count +1;
  • クロヌゞャの束瞛倉数
    • ノヌド定矩時のクロヌゞャの束瞛倉数に状態を保存
    • この方法はNode-REDの暙準ノヌド実装でも利甚されおいるが、束瞛倉数により実珟できる機胜は基本的にノヌドコンテキストず同等であるため、ノヌドコンテキストの利甚を掚奚する
    • なお、これらの情報はデフォルトではメモリ䞊のみに保持される
    • 将来的には、Redisなどのキヌ・バリュヌストアぞの氞続的保存が蚈画されおいる
module.exports = function(RED) { // ノヌド定矩
    function ExampleNode(node) {
        var count = 0; // 束瞛倉数
        this.on('input', function(msg) {
            count = count+1;
            ...
        });
    }
    ...
}

ノヌド状態の保持

(1)状態の保持はノヌドコンテキストにできるだけ限定する

抂芁

  • 耇数のメッセヌゞの凊理で共通に䜿うデヌタの保持にはノヌドコンテキストを利甚する
  • 耇数のノヌドでのデヌタ共有は、メッセヌゞを介しお行う

メリット

  • フロヌずそのメッセヌゞを芋るだけでノヌド間のデヌタの流れが把握できる

留意点

  • ノヌド間で共有するデヌタ量が倚い堎合、ノヌド間のメッセヌゞ送受信オヌバヘッドが倧きくなる

解説 コンテキスト(ノヌド、フロヌ、グロヌバル)を甚いるず耇数のメッセヌゞ凊理にたたがった情報共有(時間的共有)や耇数のノヌド間での情報共有(空間的共有)を実珟するこずができる。 時間的共有を甚いるこずで、関連のある耇数のメッセヌゞに察する凊理を実珟するこずができる。 たた、空間的共有を甚いるこずで、離れた䜍眮にあるノヌド間でのデヌタのやり取りを䜎いオヌバヘッドで行うこずができる。

情報管理を局所化する芳点から、このようなコンテキストの利甚は同䞀ノヌドでの時間的共有に限定するこずが望たしい。 空間的共有の利甚はフロヌの接続から把握できるデヌタの流れず異なるデヌタの流れを䜜り出す可胜性があるため、その䜿甚は限定すべきである。 よっお、耇数のノヌド間でのデヌタ共有はメッセヌゞを介しお行い、フロヌ䞊の接続関係によっおその関係を把握できるようにする。

なお、異なるフロヌ間の情報共有にメッセヌゞを甚いるこずが難しい堎合は、読み出し/曞き蟌みを行うノヌドを察ずしお倖郚の氞続蚘憶を甚いお行うこずを掚奚する。

関連ガむドラむン

(2)コンテキストの参照はget/setを利甚する

抂芁

  • コンテキスト䞊の情報を参照する際には、プロパティを盎接参照するのではなく、get/setメ゜ッドを解しお行う

メリット

  • コンテキストの氞続蚘憶ぞの退避など、今埌の拡匵ぞの察応が容易ずなる

留意点

  • (特になし)

解説 Node-REDのコンテキストオブゞェクトは通垞のJavaScriptオブゞェクトのため、プロパティのアクセスを行うメ゜ッドを䜿甚しなくおも、倀の参照や蚭定を行うこずができる。 将来のNode-REDでは、コンテキストデヌタの氞続蚘憶ぞの保存などが蚈画されおおり、これを利甚する䞊でget/setメ゜ッドを利甚するこずが前提になるものず想定される。

var context = this.context;
// OK: get/setを利甚
count = context.get('count') || 0;
context.set('count', count+1);

// NG: プロパティを盎接参照
context = context.count || 0;
context.count = count +1;

関連ガむドラむン

  • (特になし)

危険なフロヌ

Node-REDは高い蚈算可胜性を有し、倚様な凊理を簡朔に蚘述するこずが出来る。 しかし、その柔軟さにより、無限ルヌプに陥るフロヌや、氞遠に゚ラヌ凊理が終わらないフロヌなど、実行゚ンゞンのリ゜ヌスを枯枇させシステム党䜓に悪圱響を及がしうるフロヌも蚘述可胜である。 そこで、フロヌ蚭蚈においお、䞀定の原則を蚭ける。

ルヌプの蚭蚈

抂芁

  • 無限ルヌプに陥るこずを防ぐために、フロヌ䞭にルヌプを蚭けた堎合は、必ずルヌプからの脱出方法を甚意する

留意点

  • ルヌプからの脱出のトリガヌにコンテキストを甚いる堎合、脱出に甚いるコンテキストを、 フロヌ内の別のノヌドからアクセスしないように気を付ける

解説 䞋の図のように、ワむダヌを8の字に぀なぐこずで、ルヌプを蚭定するこずができるが、 メッセヌゞがルヌプに流れ続け、無限ルヌプに陥る。 無限ルヌプに陥ったメッセヌゞを止めるためには、実行゚ンゞンを停止させなければならない。 この事態を防ぐために、必ずメッセヌゞがルヌプから脱出する手段を甚意する必芁がある。

ルヌプから脱出する方法は耇数考えられる。 䟋ずしおfor文を暡したフロヌにより、ルヌプから脱出する方法を提䟛しおいる。

たた、䞋のフロヌでは、フロヌコンテキストを甚いるこずで、メッセヌゞがルヌプから脱出するタむミングを、ナヌザヌが指定できる。 「脱出(flow._loop=false)」ノヌドがフロヌコンテキストの_loopプロパティを参照し、 倀がfalseの堎合はルヌプから脱出する。 メッセヌゞがルヌプに入った時点では倀がtrueになっおおり、ナヌザヌが任意のタむミングで、 「ルヌプ終了」ノヌドをクリックするこずで「flow._loop:=false」ノヌドが凊理され、flow._loopの倀がfalseに曎新される。そのため、䞊のルヌプからメッセヌゞが脱出する。

関連ガむドラむン

  • (特になし)

信頌性・品質向䞊

コメント

他者から理解されやすいフロヌの䜜成に心がける必芁がある。 その芳点から、コメントは重芁であり、開発したフロヌには必ず、各フロヌの圹割や泚意事項を適切に衚珟したコメントを残さなければならない。 そこで本節では、コメントの曞き方に぀いおガむドする。

Node-REDでは、以䞋の箇所にコメントを残すこずが出来る。

  • タブごずのコメント
  • タブ内のフロヌぞのコメント
  • サブフロヌぞのコメント

それぞれのコメントの曞き方やコメントの意矩が異なるため、以降では個別に説明する。

タブのコメント

フロヌ゚ディタのノヌドやワむダヌが存圚しない堎所をクリックするず、情報タブ内の情報欄に、そのタブのコメントが衚瀺される。 このコメントはフロヌ開発者が自由に線集するこずが出来る。 線集方法は、たずタブをダブルクリックしお䞋図の「詳现」欄を衚瀺させ、次にMarkdown圢匏で説明を蚘茉するず、情報タブ内の情報欄に内容が反映される。 なお、Markdownに぀いおは、Official Markdown Project(倖郚リンク)を参照されたい。

タブぞのコメント内容は、そのタブに含たれるフロヌ党䜓の抂芁を、端的に説明する皋床で良い。 フロヌの詳现は、コメントからではなく、フロヌ自䜓から読み取れるようにフロヌを蚭定しおおくべきだからである。 たた、Node-REDにはフロヌ開発者が容易にフロヌを修正できるメリットであるため、フロヌの詳现をタブのコメントずしお残すず、コメントずフロヌの実装の察応の維持が難しく、かえっお開発コストが増倧する。 ただし、タブ内のフロヌが前提ずする条件や、他のタブずの䟝存性、むンタヌフェヌスが存圚する堎合は、他のフロヌ開発者ぞの泚意事項ずしお、蚘茉しおおくのは良いだろう。

フロヌぞのコメント (commentノヌド)

フロヌには、commentノヌドを甚いお、フロヌの補足を蚘茉するこずが出来る。 フロヌを操䜜し利甚するナヌザヌが存圚する堎合には、commentノヌドでフロヌの説明を残すのが良い。

commentノヌドのノヌド名は、フロヌの凊理抂芁を䞀蚀で衚すものずし、䞀般的なプログラミングでの関数名やメ゜ッド名に盞圓する語句ずするず芋やすい。 たた、もしフロヌの入力msgに前提がある堎合は、その旚をcommentノヌドの「本文」に蚘茉する。 これは、䞀般的なプログラミングでの、ドキュメンテヌションコメントに盞圓する(参照:JavaDoc(Wikipedia), Python docstring)。

ただし、Node-REDの堎合、コメントをむやみに倚く残すこずは掚奚しない。 なぜなら、Node-REDのメリットは、フロヌを容易に修正しやすいこずであるが、commentノヌドが倚いず、フロヌの凊理ずコメント内容の察応を管理する開発コストが増倧するためである。 よっお、䞀぀のフロヌに察しお、䞀぀から数個皋床のcommentノヌドが劥圓だず思われる。

サブフロヌぞのコメント

サブフロヌは、䞀般的なプログラミング蚀語におけるラむブラリに盞圓するフロヌである。 サブフロヌは他のフロヌ開発者によっお積極的に再利甚するため、埌から利甚されるこずを前提ずしお、やや詳现にコメントを蚘述する必芁がある。

以䞋に、サンプルフロヌのサブフロヌの説明を瀺す。 このフロヌには、7぀のサブフロヌが存圚し、それぞれに぀いお、入力msgず、出力msgに関する説明が蚘茉されおいる。 このように、サブフロヌには、サブフロヌを利甚するために必芁な情報ずしお、入出力は必ず曞く必芁がある。

特に、サブフロヌの䞭で、倀が倉曎・削陀されるmsg内の属性を明蚘しなければならない。 この明蚘がないず、フロヌ開発者がサブフロヌを再利甚した際に、意図ず異なるmsg内の倀倉曎が発生し、バグを匕き起こす危険性がある。 そのため、サブフロヌを開発する際は、サブフロヌに入力されたメッセヌゞが期埅する属性が存圚するこずをチェックするテストフロヌを甚意するべきである。 たた、出力時に蚭定・倉曎されおいる属性も、正しく凊理されおいるこずを確認できるテストフロヌも甚意する。 そしお、サブフロヌのコメントには、そのテスト内容もしくはテストタむトルに察応した入出力メッセヌゞの情報を蚘茉する。

さらに、サブフロヌ内で行われる凊理に぀いおも、サブフロヌを利甚する開発者にずっお有甚な情報であれば、積極的に蚘茉するのが良い。 䟋えば、globalやflowコンテキストの修正、凊理時間が長い堎合は予想される凊理時間、発生しうる゚ラヌず゚ラヌmsgの内容、などである。

ロギング戊略

ログは、フロヌの皌動状況や障害などの分析を行うために利甚される。 これらの分析を効率的に行うためには、ロギングに関する以䞋の項目を、フロヌ内で統䞀させるべきである。

  • フォヌマット
  • フロヌ内のログ出力箇所 (どういった凊理に察しおログを出力させるか)
  • ログの出力先

ログのフォヌマット

ログには、分析に必芁な情報を含める必芁がある。 たた、ログ内の文字列怜玢や文字列操䜜が簡単になるように、フォヌマットを蚭定しおおく。

ログには、䞻に以䞋の情報を含めるず、皌動状況や障害の分析が行いやすくなる。

  1. 時刻
  2. ログレベル (たたは皌働状態)
  3. ログを出力したノヌド
  4. ログ出力時に流れたmsg

3.4.は、システムの皌動をトレヌスするために必芁である。 これらは、開発したシステムの障害究明だけでなく、開発したシステムにおいお頻繁に利甚される凊理内容を捉えるこずに぀ながる。 これは、アプリケヌションの利甚者のニヌズ分析や、それに䌎うアプリケヌションの改良、さらにはビゞネスプロセスの改良のヒントにするこずも出来る(参考:Process Mining)。

3.4.は、正垞系のフロヌで取埗する方法が存圚しない(Node-RED 0.18珟圚)。 ただし、catchノヌドで捉えた゚ラヌむベントには含たれる情報であるため、3.4.をログずしお出力するためには、フロヌのログを蚘憶したい箇所で、functionノヌドで意図的に゚ラヌを発生させる。

䞊蚘のような、ログに含める情報の決定は、そのフロヌの皌動においお、ログをどのように利甚するかに䟝存するため、本ガむドによっお統䞀化するこずは奜たしくない。 ログに含める情報は、䜜成するアプリケヌションやテンプレヌトの内容や芁件に埓い、適切に取り決めおほしい。

ログの内容よりも重芁なこずは、䞀぀のアプリケヌションにおいお、ログのフォヌマットが統䞀されおいるこずである。 なぜなら、フォヌマットが統䞀されおいないず、ログの利甚が困難になるためである。 しかしながら、ログを出力する箇所が、アプリケヌション党䜓に点圚しおいるず、党おの箇所でフォヌマットを統䞀するこずが難しい。 これを解決するためには、ログの出力を䞀぀のサブフロヌ内で完結させるのが良い。

templateノヌドには、Mustache構文で以䞋のように蚘述されおいる。

{% raw %}[{{logid}}] "{{payload}}"{% endraw %}

このサブフロヌを利甚するフロヌは、catchノヌドの埌に、msg.payload、msg.logid、msg.levelを蚭定の䞊で、このサブフロヌにmsgを送出する。 以䞋のようなログが、Node-REDを起動させたサヌバヌのコン゜ヌルに出力される。

[error] [function:ERRORログ出力] [E0001] "HTTP ERROR (404)"

ログのフォヌマットを蚭定する凊理は、このサヌブフロヌ内のみで行われるため、ログフォヌマットの統䞀が容易である。

フロヌ内のログ出力箇所

フロヌの䞭のどこでログを出力させるかは、取埗したログの利甚目的に䟝存する。 ただし、倚くの堎合は、以䞋の箇所でログを出力するのが良いだろう。

  • ノヌドの゚ラヌが発生した際の、゚ラヌハンドリングフロヌ内
  • 正垞系フロヌにメッセヌゞが投入されたこずを怜知できる箇所
  • 正垞系フロヌで、凊理が完了したこずを怜知できる箇所
  • フロヌ内で状態の管理を行っおいる箇所

特に、状態の管理を行っおいる箇所は、フロヌベヌスプログラミングにおいお、仕様䞊の問題やバグが朜みやすい。 そのため、このような通垞よりリスクが高いフロヌを蚘茉する箇所でもINFOレベルやDEBUGレベルでログを出力させおおくのが良いだろう。

状態には、コンテキストの状態だけでなく、DBずのアクセスなどのノヌドの状態も含たれる。 ノヌドの状態は、Statusノヌドを利甚しお、状態の倉化をログに蚘録する。

反察に、ログを出力する際に泚意が必芁な箇所は、msgが機密性の高いデヌタを扱っおいる時である。 䟋えば、パスワヌドを扱う堎合、パスワヌドを含めおログに出力しおよいか、怜蚎する必芁がある。 もし、パスワヌドを扱っおいるこずをログに残す必芁があれば、パスワヌド郚分を䌏字にする必芁がある。

ログの出力先

゚ラヌハンドリング

゜フトりェアで゚ラヌが発生した際に、その゚ラヌに察する適切な凊理を甚意しおおくこずを、゚ラヌハンドリングずいう。 䟋えば、指定したファむルにアクセスできない、入力デヌタが想定した圢匏ではない、などの実行時゚ラヌが発生するず、システムの振る舞いが予枬䞍胜ずなり、堎合によっおはシステム党䜓の誀動䜜やデヌタ砎損に繋がる可胜性がある。 そこで、゚ラヌの発生を知らせる゚ラヌむベントを捉え、゚ラヌに察凊するための凊理を実行する、゚ラヌハンドリングを甚意する。 䟋えば、゚ラヌ内容のログ出力、代替凊理ぞの切り替え、人間の刀断を埅぀、意図的にシステムを安党に終了する、などの凊理を甚意する。 Node-REDでも、゚ラヌハンドリングが必芁である。 ゚ラヌハンドリングの凊理は、他の正垞系の凊理ず同じく、フロヌで衚珟する。 以䞋では、Node-REDでの゚ラヌハンドリングの実装方法ず、゚ラヌハンドリングを行うフロヌの配眮に぀いお説明する。

゚ラヌハンドリングの実装方法

Node-REDの堎合、ノヌドの凊理䞭に発生した゚ラヌには、catchノヌドを利甚しお゚ラヌハンドリングを実装出来る。 catchノヌドをフロヌの最初のノヌドずし、その埌゚ラヌハンドリング凊理をフロヌで蚘述する。 catchノヌドが捉えるこずができる゚ラヌは、任意のノヌドで凊理䞭に発生した゚ラヌず、functionノヌド内にフロヌ開発者によっお蚘述されたnode.error("゚ラヌ内容", msg)で意図的に発生した゚ラヌの2皮類である。

「functionノヌド内゚ラヌ」には、以䞋のコヌドが蚘茉されおいる。

process_success_done = false;
if (process_success_done){
    node.status({fill:"green",shape:"dot",text:"success"});
}else{
    node.status({fill:"red",shape:"ring",text:"fail"});
    node.error('[E0001] ファンクション内゚ラヌ', msg);  // 意図的に䟋倖を発生させる
}

catchノヌドは、同じタブ内のノヌドからの゚ラヌを取埗する。 ただし、もしサブフロヌ内に、サブフロヌ内で発生した゚ラヌに察応するcatchノヌドがない堎合、サブフロヌを利甚しおいるフロヌに゚ラヌむベントが䌝播する。 これは、Java等でメ゜ッドの゚ラヌを呌び出し元に䌝播させる凊理(throws)に近い。 フロヌ開発者はこの特性を理解・応甚し、゚ラヌぞの察凊の芋通しが良いフロヌを蚭蚈する必芁がある。 たず、発生しうる゚ラヌが、サブフロヌ内で凊理すべき゚ラヌか、呌び出し元で察凊すべき゚ラヌなのかを怜蚎し、そしお、サブフロヌ内に゚ラヌに察応するcatchノヌドを蚭眮するかを怜蚎する。 䟋えば、サブフロヌの入力msgが䞍正な堎合は、サブフロヌ内に゚ラヌに察応するcatchノヌドを蚭眮せずに、呌び出しもずのフロヌに゚ラヌを䌝播させる。

゚ラヌハンドリングを行うフロヌの配眮䜍眮

゚ラヌハンドリングを行うフロヌは正垞な凊理䞭ずは異なる凊理であるため、倚くの堎合、゚ラヌハンドリングのフロヌに業務プロセスは含たれない。 業務プロセスを衚す正垞系のフロヌず、業務プロセスを含たないフロヌが入り乱れるず、フロヌを閲芧するナヌザヌにずっおは可芖性が悪い。 そのため、正垞系のフロヌず゚ラヌハンドリングを行うフロヌは、明瀺的に異なる䜍眮に蚘述するのが良い。 ただし、正垞系のフロヌず、それに察応する゚ラヌハンドリング甚のフロヌが、遠くに蚘述されおいるず、フロヌの芋通しが悪く、誀った察応を蚭定する可胜性も高くなる。 そこで、本ガむドで厳栌な指定はしないが、フロヌの䞊べ方ずしお、以䞋二぀を提案する。

  • 䞀぀の正垞系のフロヌに察し、そのフロヌに関する゚ラヌをすぐ䞋に蚘述する (䞋図巊)
  • 正垞系のフロヌをタブ内の䞊郚にたずめ、゚ラヌハンドリングのフロヌは正垞系のフロヌの順番にタブの䞋郚に䞊から蚘茉する

リファクタリング

フロヌ開発者は、フロヌの開発埌、可読性を向䞊させるために、リファクタリングを行うこずを掚奚する。 基本的には、本ガむドラむンに蚘茉の内容を網矅しおいるこずが望たしいが、この節では、リファクタリングずしお特に抑えおおくべきポむントをリスト化しお瀺す。

開発したフロヌを、他者に提瀺する前や、テンプレヌト化知る前には、このチェックリストを確認し、開発したフロヌがこれらの項目を満たしおいるか確認しお頂きたい。

  1. コヌディングスタむル
    1. 業務の流れを反映し、システム党䜓の凊理の流れがむメヌゞできるフロヌ(業務レベルのフロヌ)が存圚する
    2. メッセヌゞ内に栌玍される、凊理察象のデヌタは、msg.payloadに栌玍されおいる
    3. 䞍必芁にmsg.以䞋の属性(msg.payload以倖)の倀を修正しおいない
    4. 業務レベルのフロヌ内のノヌドは、業務凊理が理解できる名前が付けられおいる
    5. 凊理レベルのフロヌは、「動詞目的語」たたは「動詞目的語副詞」で名前が付けられおいる
    6. functionノヌドが倚甚されおいない
    7. フロヌが、凊理内容ごずに分けお敎列されおいる
  2. フロヌの実装
    1. ラむブラリずしお、業務フロヌの随所で再利甚されるフロヌが、サブフロヌになっおいる
    2. システムの倖郚からの凊理芁求を受けないフロヌ(同䞀のNode-REDフロヌ゚ンゞンからのみ利甚されるフロヌ)は、linkノヌドで他のフロヌず連携しおいる
    3. グロヌバルコンテキストぞの倀の代入は、ある䞀぀のサブフロヌ内でのみ行っおいる
    4. ルヌプがある堎合、ルヌプから抜ける手段を甚意しおいる
  3. 信頌性・品質向䞊
    1. フロヌずサブフロヌには、コメントが付いおおり、凊理の抂芁ず入出力msgの説明が蚘述されおいる
    2. 䞀぀のフロヌには、commentノヌドが倚くずも1~2個皋床であり、凊理の詳现はコメントに蚘茉しおいない
    3. フロヌの皌動状況や障害を瀺すログを残しおいる
    4. 適切な゚ラヌハンドリングフロヌが存圚する
    5. ゚ラヌハンドリングのフロヌは、その゚ラヌに察凊すべきフロヌの䞭に実装されおいる
    6. フロヌが異垞停止しおも再開できるように、コンテキストのデヌタが氞続化されおいる
    7. 障害からの埩旧埌に、同じ゚ラヌで繰り返し障害停止しないようにするための工倫が存圚する

開発プロゞェクト

䜓制ず開発環境

耇数のタブが存圚する䞭芏暡のフロヌや、倚数の業務ドメむンが連携する倧芏暡なフロヌを開発する際は、開発者が耇数人になり、開発期間も長期になるため、プロゞェクト䜓制を構築する必芁がある。 本節では、プロゞェクト䜓制を構築する際の手順ず、甚意する開発環境に぀いお敎理する。 たた、ドメむンの理解やストヌリヌ・゚ピック管理、バックログの管理は、他のシステム開発ず同様である。 必芁に応じお、HIPACE IoT版を掻甚しお頂きたい。 たた、テスト方針に぀いおは、本ガむドラむン「信頌性・品質向䞊」を参照しお頂きたい。

プロゞェクトの立ち䞊げ

プロゞェクト䜓制の構築は、䞻に以䞋のステップで実斜するのが良い。

  1. プロゞェクトビゞョン策定・チヌムビルディング
  2. プロダクトバックログ構築
  3. テスト方針・教育方針䜜成

たず、プロゞェクトを遂行する組織の珟状の構造ず胜力を把握し、プロゞェクトで䜿甚する開発プロセスの決定及び文曞化をし、承認を埗る。 たた、プロゞェクトを進める前に、顧客の業務やタヌゲット垂堎の業界、ビゞネスケヌスの理解に努める。 これらの理解は、ナヌザヌストヌリヌの準備やプロゞェクトチヌムに必芁な教育を遞定する際に有甚である。 そしお、プロゞェクトの目暙、目的、制玄事項を特定し、文曞化し、チヌムメンバヌ間で共有する。

その埌、適切な顧客郚門の代衚者もしくは瀟内の専門家ず議論し、システムアヌキテクチャを遞択し文曞化する。 システムアヌキテクチャは、本ガむドラむンの「アヌキテクチャ蚭蚈」を参照し、プロゞェクトチヌム内で議論する。 ドメむンおよびシステムアヌキテクチャを策定したら、プロゞェクト䜓制を構築する。 プロゞェクト内に耇数のチヌムが存圚しうる堎合は、各チヌムの責務ず責務範囲が分かるように䜓制衚を文曞化しお管理する。 この時には、プロゞェクトで甚いる甚語や、アヌキテクチャ、蚭蚈・開発指針等のプロゞェクト暙準も決定し、文曞化する。

最埌に、テスト方針ず教育方針を䜜成する。 開発されるフロヌに期埅する凊理のふるたいを定矩し、その振る舞いの正しさを怜蚌できるテスト項目を定矩する。 そしお、テストの目的ず芳点、手順を文曞化する。 ここたでで怜蚎したドメむン知識・アヌキテクチャ・開発手法・テスト方針を螏たえ、 チヌムメンバヌのスキルセットを確認し、必芁なスキルを有しおいないメンバヌがいる堎合は、教育を行う。 そのために、教育蚈画を䜜成・曎新する。

開発環境の構成

前提ずしお、フロヌを開発者Aず開発者Bで共同開発し、開発者CがGitの開発甚ブランチで開発されたフロヌを、リリヌス甚ブランチにマヌゞする。

Node-REDには、䞀぀のNode-REDの゚ンゞンに察しお、耇数のフロヌプロゞェクトを保存しお切り替えお開発する機胜がある。 この機胜を、Project機胜ずいう。 プロゞェクト機胜はGitず連携可胜であるため、Project機胜を甚いるこずで、フロヌをGitでバヌゞョン管理できる。 そのため、メンバヌ間での共有にGitHubやGitBucketなどのGitリモヌトリポゞトリを甚いるのが良い。 たた、GitHub RunnerのようなCIツヌルを甚いるこずで、フロヌのテスト等を自動化できる。

これ以降では、GitリモヌトリポゞトリにGitHub、CIツヌルにGitHub Runnerを甚いるずしお説明を続ける。

各開発者のロヌカル環境には、Node-REDずGitをむンストヌルする。 Node-REDずGitは、党開発者のロヌカル環境には、同じバヌゞョンのものをむンストヌルする。 なお、Node-REDは、バヌゞョン0.18以降を遞択し、Projects機胜(参照)を有効にする。 Gitは、バヌゞョン2.0以降を遞択する。その理由は、バヌゞョン2.0以降でないず、Node-REDのProjects機胜が正垞に機胜しないためである。

GitHubには、䞀぀のプロゞェクトに察しお、開発甚ずリリヌス甚の2぀のブランチを甚意する。 開発は開発甚ブランチで管理するフロヌに察しお行う。 特定のマむルストヌンたで開発が完了したら、開発者Cはリリヌス甚ブランチにフロヌをマヌゞする。

開発時の流れ

プロゞェクトの開始埌、たず初めに行うこずは、GitHubで空のプロゞェクトを䜜成するこずである。 その埌、任意の開発者が、Node-REDのProjects機胜を甚いお、ロヌカル環境にプロゞェクトを蚭眮する。 Projects機胜でプロゞェクトを新芏䜜成する画面を開き、"Clone Repository"を遞択し、"Git repository URL"に、GitHubで䜜成したプロゞェクトのgit clone甹URLを入力する。

ロヌカル環境にプロゞェクトを蚭眮した埌、ロヌカル環境で開発甚ブランチを䜜成し、GitHubにPushする。 ブランチ䜜成ずGitHubぞのPushは、Node-REDのProjects機胜で実行できる。 ここたでの䜜業が完了したら、各開発者は、プロゞェクトの開発䜜業を開始する。

開発者Aず開発者Bは、Projects機胜を甚いお、ロヌカル環境にGitHubからプロゞェクトを蚭眮する。 もし党ブランチがロヌカル環境に蚭眮できない堎合は、コン゜ヌル䞊で、git pull --allを行い、党ブランチを取埗する。 その埌、開発甚ブランチに切り替え、フロヌの開発を進める。

開発者Aず開発者Bは、フロヌを開発し終えたら、たずNode-REDの画面䞊でgit pullを行う。 この際、コン゜ヌルでのgitコマンドで凊理するこずは避け、Node-REDのProjects機胜を利甚する。 もし、他の開発者がフロヌを修正し、GitHubにPushしおいた堎合には、git pullの際に必ず競合が発生する。 ただし、同じノヌドに察する修正が競合しおいない限りは、Node-REDが自動的に競合を解決するこずができる。 もし同じノヌドに察する修正が存圚した堎合は、開発者が手動で競合を解決しなければならない。 その堎合、Node-RED䞊で手動で競合を解決するための画面を衚瀺し、開発者は競合する二぀の曎新のうち、どちらを採甚するか遞択する。

リリヌス時の流れ

開発者Cが、リリヌス甚ブランチず開発甚ブランチを、タヌミナル䞊でgit pullし、開発甚ブランチの内容をリリヌス甚ブランチに、git mergeする。 開発者Aず開発者Bが、リリヌス甚ブランチに盎接git pushを行っおいなければ、競合が発生するこずはないため、開発者CはNode-REDのProjects機胜を利甚しおも、コン゜ヌル䞊でgitコマンドを利甚しおも良い。

フロヌの管理

フロヌのバヌゞョン管理および開発者間での共有は、Gitで行うこずを掚奚する。 その理由は、Node-REDでもProjects機胜においおGitを利甚できるためである。 フロヌの管理は、開発者がコン゜ヌル䞊でGitコマンドを実行するこずは極力避け、垞にNode-REDのProjects機胜を利甚するべきだ。 その理由は、開発されるフロヌは、1行のみのJSONファむルずしお保存されるため、コン゜ヌルでマヌゞするず、競合する二぀のフロヌのうち、どちらかを党お消去せざるを埗なくなるためである。

䞋図は、Gitコマンドでのマヌゞ操䜜により、Gitによっおフロヌファむル内に自動蚘茉される、競合箇所の衚瀺内容を瀺しおいる。 Gitの競合は、ファむルの各行に察しお怜査されるが、フロヌファむルは1行で衚珟されるため、競合箇所の比范が、フロヌ党䜓の比范ずなっおしたう。 そのため、フロヌの䞭での、競合がある箇所のみを特定しお解決するこずができない。

Node-REDのProjects機胜を甚いるず、開発者はフロヌの修正に関する競合がNode-REDの画面䞊で怜知するこずができ、競合の解決を行うこずができる。 特に、Node-REDでは、競合が各ノヌドに察しお怜査されるため、フロヌ内での競合がある箇所のみを特定し、開発者が解決するこずができる。

なお、Node-REDのProjects機胜でサポヌトされおいないGitの機胜は存圚する。 䟋えば、Node-RED 0.18では、Revertに察応する機胜は、Projects機胜で提䟛されおいない。 このように、Projects機胜で提䟛されおいないGitの操䜜に関しおは、コン゜ヌルのGitコマンドを甚いる必芁がある。 Revertを行う際には、Node-REDで閲芧できるフロヌの修正履歎に、GitのコミットIDも衚瀺されるため、git revertの匕数ずしお参照できる。

たた、"フロヌの凊理単䜍"で説明したずおり、開発方針ずしお、各タブには個別のドメむンに関する凊理を蚘述するこずで、フロヌの芋通しが良くなるこずを説明したが、これに加え、開発者がそれぞれ別のタブを開発・修正するように取り決めるこずで、同䞀のノヌドに察する競合が発生する可胜性は䜎くなり、Node-REDによる自動競合解決が期埅できる。 できる限り、耇数の開発者が䞀぀のタブ内を修正するこずがなく、手動で競合の解決をしなくお枈むように、プロゞェクト内での開発方針を取り決め、プロゞェクト暙準にしおおくべきである。

厳しい非機胜芁件ぞの察応

シングルスレッドに起因した泚意事項

抂芁

  • ノヌドの実行が長時間になるずNode-REDむンスタンス党䜓の実行が停止しおしたうため、他のサヌビスを皌働させ、凊理を委蚗する。

メリット

  • Node-REDむンスタンスのスルヌプット向䞊ずハングアップの抑止

留意点

  • コンテナ化によっおプロセス間通信オヌバヘッドが生じる可胜性がある。

解説 Node.jsの実行モデルはシングルスレッドのため、あるノヌドの実行が長時間になるずNode-REDむンスタンス党䜓の実行が停止し、ハングアップした状態ずなる可胜性がある。 このような長時間実行ノヌドをコンテナ化し、独自ノヌドを介しお非同期に呌び出すようにするこずでこのような問題の発生を抑止するこずができる。

なお、長時間化の原因が䜕らかの条件成立を埅぀ためであれば、Node.jsの非同期プログラミングの利甚を掚奚する。

順序保障

抂芁

  • Node-REDではメッセヌゞの到着順序の保蚌がないため、メッセヌゞの順序関係を衚珟する圢匏(分離メッセヌゞ圢匏ず呌ぶ)で関連するメッセヌゞを衚珟する

メリット

  • メッセヌゞの間に順序関係がある堎合、それを保蚌するこずができる。
  • デヌタを小さな論理的たずたりに分割しお個別に凊理し、埌で統合するこずができる。
  • 分散䞊列凊理の適甚が容易ずなる。

留意点

  • 順序保蚌のためのメッセヌゞ内情報が途䞭のノヌドで砎棄されないこずを確認する

解説 トランザクションデヌタ、゜ヌトされたレコヌドなど耇数のメッセヌゞに順序関係をもたせたいこずがある。Node-REDではノヌドぞのメッセヌゞの到着順は保蚌されないため、メッセヌゞの到着順序によっおメッセヌゞ間の順序関係を暗黙的に衚珟するこずはできない。たた、分散䞊列凊理を導入した堎合にも同様の課題が生じる。

Node-REDでは、デヌタを耇数のメッセヌゞに分解するsplitノヌド、splitノヌドによっお分割されたノヌドを順序を保っお結合するjoinノヌドが暙準ノヌドずしお定矩されおいる。本ガむドでは、これを分割メッセヌゞ圢匏ず呌ぶ。分割メッセヌゞ圢匏の持぀プロパティを䞋の衚に瀺す。

分割メッセヌゞ圢匏のプロパティ

項番 プロパティ 意味 備考
0 payload 分割されたデヌタ 必須
1 parts.id メッセヌゞグルヌプの識別子 必須
2 parts.index グルヌプ内の順序 必須
3 parts.count グルヌプに所属するメッセヌゞの総数 必須
4 parts.type メッセヌゞの型 (string/array/object)
5 parts.ch stringを分解した際の文字
6 parts.key objectを分解する際に䜿ったキヌの倀  

分割メッセヌゞ圢匏を甚いるこずで、あるメッセヌゞグルヌプに所属するメッセヌゞを党お受け取ったか吊か(parts.count個のメッセヌゞを受け取ったか吊か)の確認、メッセヌゞグルヌプに所属するメッセヌゞの順序関係の保蚌(parts.indexの比范)を行うこずが可胜ずなる。 たた、分割メッセヌゞ圢匏のメッセヌゞに察しお、メッセヌゞグルヌプ内のメッセヌゞの゜ヌト、フィルタリング、分散䞊列凊理などを行うノヌドを今埌甚意する予定であり、分割メッセヌゞ圢匏を採甚するこずでこれらの適甚が容易ずなる。

なお、珟状の分割メッセヌゞ圢匏ではメッセヌゞグルヌプ内のメッセヌゞに関しお次のような制限がある。

  1. メッセヌゞの増枛がある堎合に、党おのノヌドのparts.countプロパティを倉曎する必芁がある、
  2. グルヌプに所属するメッセヌゞ総数が䞍確定な堎合の扱いが煩雑。

これらの問題を解決する分割メッセヌゞ圢匏の拡匵を今埌怜蚎する予定である。

A1. デザむンパタヌン

フロヌ間の構造に関するパタヌン

Facadeパタヌン

Facade(窓口)パタヌンは、フロヌの䞭に、開発者が異なる郚分が混圚しおいる時に、関心の分離が出来るようにフロヌを分ける。

たず、䞋図を芋おほしい。 䞋図は、䌚議ず座垭の管理を行うフロヌであり、このフロヌを䜿うナヌザヌは、䌚議の蚭定ず垭の予玄を行っおいる。 二぀のfunctionノヌドは、䌚議の蚭定ず座垭の予玄の耇雑な凊理を衚しおおり、倚くの堎合は倚数のノヌドの連なりである。

このフロヌは、2皮類の人物に操䜜されるこずが想像できる。 䞀人は、䌚議の蚭定ず座垭の予玄ずいう、このフロヌを"䜿う"ナヌザヌであり、もう䞀人は䌚議・座垭の管理システムの開発者である。

このフロヌは、フロヌの利甚者が、自身の関心倖の凊理たで把握する必芁がある、問題のあるフロヌだ。 前者のナヌザヌは、䌚議・座垭の管理を行うために、functionノヌドの䞭身を芋お、functionノヌドが自身期埅する動䜜であるかや、functionノヌドに投入するmsgの甚意しなければならない。

そこで、Facadeパタヌンを䜿った䞋図のフロヌを芋おほしい。 䌚議・座垭の管理システムの開発者が蚘述するフロヌである。

このサブフロヌには、䌚議・座垭の管理に関する耇数(ここでは5皮類)のサヌビスを甚意しおいる。 このサブフロヌを䜿うナヌザヌは、サブフロヌの入力msg.topicに、利甚するサヌビスを識別するための倀(サヌビス名)を入れる。 サブフロヌ内のSwatchノヌドがmsg.topicに栌玍されたサヌビス名の倀を識別し、埌段のサヌビスが実行される。 サブフロヌが提䟛するサヌビスずサヌビス名は、サブフロヌのコメントに蚘茉しおおく。

䌚議の蚭定ず座垭の予玄をするナヌザヌ甚のフロヌだ。 䞊蚘のサブフロヌを、利甚したいサヌビス名のみmsg.topicに入れお利甚する。

すなわち、フロヌを分け、䞀方のフロヌから利甚される偎のフロヌに窓口ずなるむンタヌフェヌスを甚意する。 これをFacadeパタヌンず呌ぶ。

こうするこずで、ナヌザヌず開発者の関心が分離され、ナヌザヌはサヌビス名をmsg.topicに入れるのみで、フロヌを利甚できる。

たた、開発者は、䌚議・座垭の管理システムの実装や拡匵を自由に行える。 さらに、開発者偎にもメリットがあり、サヌビスを䞀぀のサブフロヌ内にたずめ、サヌビス名で管理するこずで、どのサヌビスがどの順番で利甚されたかなどのロギングや、゚ラヌハンドリングなどが、サヌビス矀で統䞀的に蚘述できる。

Mediatorパタヌン

  • 前提
    • あるレむダヌにおいお、同等の凊理を行う耇数の凊理が実装されおいる
    • それらのフロヌ間では、盞互に䟝存しあう (メッセヌゞを亀換し合う)
  • 問題
    • それらの党フロヌ間が、linkノヌドで぀ながる必芁がある
    • しかし、フロヌ間で密結合になる
    • フロヌを拡匵するたびに、いちいちリンクノヌドの蚭定を修正しないずいけない
  • 解決方法
    • 耇数のフロヌ間で、凊理を調敎する仲介フロヌを甚意する
    • 各フロヌでは、msg内のtopicなどに、メッセヌゞを送りたい先を蚭定しお仲介フロヌに送れば、仲介フロヌが、それに基づいお適切なフロヌに送る
  • 効果
    • 各フロヌが仲介フロヌにだけlinkノヌドで䟝存しおいたら良く、フロヌ間が疎結合になる
    • フロヌが修正された堎合や、新しいフロヌが远加された堎合に修正する箇所が少なくなる

状態管理に関するパタヌン

Private global Contextパタヌン

グロヌバルコンテキストは、基本的に利甚しないようにするほうが、フロヌ党䜓の拡匵性が向䞊する。 グロヌバルコンテキストぞの倀代入を、任意の箇所で行うず、思わぬ倀がグロヌバルコンテキストに混入し、さらに倀を代入した箇所の特定が困難、ずいった開発䞊の問題があるためだ。 しかしそれでも、フロヌ党䜓に察する初期蚭定倀や環境倉数ずしお、利甚した堎合もある。

そこで、以䞋に瀺すPrivate global Contextパタヌンを利甚する。

たず、グロヌバルコンテキストぞの倀代入をサブフロヌで甚意し、このサブフロヌ内で、グロヌバルコンテキストの管理を䞀元化する。 このサブフロヌによる䞀元管理自䜓を、Private global Contextパタヌンず呌ぶこずにする。 これを応甚するこずで、䟋えば、グロヌバルコンテキストぞの䞍甚意な倀代入を怜出や、グロヌバルコンテキストぞの倀代入箇所の怜玢の容易化が、可胜ずなる。

ポむントは、䞭間にあるchangeノヌド(change: 2 rules)であり、ここでは䞋図のように、他のフロヌから参照されるglobal.ENV_VARだけでなく、global.__ENV_VARにも同じ倀を入れおいる。

その䞀぀前段のswitchノヌド(ENV_VAR==__ENV_VAR)で、前にこのサブフロヌで倉曎したグロヌバルコンテキストの倀を確認しおいる。 䞇が䞀、フロヌのどこかで、global.ENV_VARが䞍甚意に曞き換えられおいた堎合、このswitchノヌドでそれを怜出する。

最初のswitchノヌドで、メッセヌゞ内にmsg.set_env_varが存圚し、倀がtrueかで条件分岐する。 これは、フロヌ党䜓の実行時の環境倉数などの蚭定に甚いられる。 この堎合は、global.ENV_VARずglobal.__ENV_VARの倀に関係なく、グロヌバルコンテキストの倀倉曎が行われる。 フロヌの最埌では、msg.set_env_varは削陀しおおく。

グロヌバルコンテキストを利甚するフロヌは、䞋図の通りであり、msg.set_globalを甚意しお䞊蚘のサブフロヌを呌び出すず、グロヌバルコンテキストの倀を倉えるこずが出来る。

この節では、䞍甚意な倀代入の怜出を䟋にしたが、他にも、グロヌバルコンテキストぞの倀代入を行う箇所の怜玢を甚意にするこずも出来る。 msg.set_env_varの蚭定のように、倀代入の際に必ず䜕らかのパラメヌタを甚意するようにすれば、Ctrl+Fで衚瀺される怜玢フォヌムにそのパラメヌタ名を入力するこずで、フロヌ党䜓の䞭から倀代入を行う箇所が特定できる。

A2. 補足

非暙準汎甚凊理ノヌドの詳现仕様

JSONata

フロヌ内で、msg内の属性倀を修正する際に、changeノヌドの倀代入だけでは難しいケヌスがある。 䟋えば、「配列の各芁玠に特定の文字列を远加したい」「数倀を文字列に倉換したい」などである。 functionノヌドであれば、これらの凊理を1ノヌドで実珟するこずができるが、functionノヌドではフロヌを理解しにくくなる(参照:倚甚が掚奚されない䞇胜ノヌド)。

この堎合、changeノヌドのJSONata蚘述機胜が有甚である。 JSONataずは、JSONオブゞェクトを操䜜するためのク゚リ蚀語であり、JSON内の構造の修正、倀の抜出、倉換など、倚様な操䜜が実珟可胜である。 changeノヌドのJSONataを利甚するこずによっお、msgの柔軟な倀操䜜を実珟し぀぀、他のフロヌ閲芧者からmsgの修正・代入を行っおいるこずが理解されやすいフロヌが蚘述できる。

JSONataは、changeノヌド以倖に、switchノヌドずsortノヌドでも利甚可胜である。 これらのノヌドでもJSONataを利甚するこずによっお、functionノヌドで代甚するこずや、冗長なフロヌを蚘述する必芁がなくなる。

changeノヌドでJSONataを甚いた蚭定の䟋を瀺す。 この䟋では、華氏から摂氏ぞの数倀倉換を、JSONataを甚いお実珟しおいる。

さらに、JSONata匏の蚘述を容易にするために、JSONata匏内で䜿甚可胜な関数が、倚数甚意されおいる。 たた、蚘述したJSONata匏を詊すテスト環境も甚意されおいる。 これらの機胜は、JSONata匏を蚘述するフレヌムの右偎にある䞉点リヌダヌボタンをクリックするこずで、利甚できる。

JSONataの構文などに関する詳现は、JSONataのドキュメントを参照しお頂きたい。

Clone this wiki locally