update.私がNode-REDを使い始めて4カ月が経ちました。開発をしていると、Node-REDには単にノードを横に繋いでゆくだけではなく、ノードの接続関係を活用したデザインパターンが沢山あることに気が付きました。本記事では、Node-REDを今まで以上に活用できるデザインパターン10個を、ご紹介します。Cloud上のNode-REDはもちろん、ローカルPCにインストールしたNode-REDでも動作しますので、貼り付けて遊んでみてください。Node-REDとはNode-REDは、機能毎に用意されたノードをマウスで繋ぐ操作で、簡単にアプリケーションを作成できる開発環境です。当初はIoT向けに開発されましたが、ウェブアプリケーション開発等、幅広い用途で利用できます。最近では、SiemensのMindSphereで採用されたり、自作ノードの開発を支援するツールが開発されたりしており、様々な企業がNode-REDを活用しています。デザインパターンとは一般的にデザインパターンとは、Java等のオブジェクト指向言語を使いこなしてゆくと辿り着く、開発や変更の効率が良い設計パターンを指します。学生の時、興味深いパターンが何個か学び、特にMediatorやSingletonパターンは目から鱗でした。Node-REDにおけるデザインパターンNode-REDは、複雑な処理をカプセル化したノードが沢山用意されているため、ノードを繫ぐだけで簡単に一連の処理を実現できます。ノードを一方向に繋ぐのみでは、Node-REDの利点を活用しきれていないと考えます。「処理のロジックを、ノードの接続関係で記述する」と視点を変えると、様々なデザインパターンのアイデアが沸いてきました。デザインパターンを用いると、一連の処理を理解しやすくなり、リリース後の修正も効率的に行えるようになります。Searchパターンデータの格納と検索を行うパターンです。Searchパターンは一番メジャーなパターンであると思います。Storeパターンは、IoT端末等から取得したデータをデータベースに格納します。この時、JavaScriptを記述するノードを介して、格納するデータを選択したり、データを格納する列名を指定したりできます。Searchパターンは、Storeパターンを用いて格納したデータを検索するパターンです。APIパターンブラウザ上でAPI問合せに用いる入力値を受け付け、APIを問合せた結果を表示するパターンです。UIパターンは、入力フォーム表示用処理、API問合せ結果表示用処理の2つの処理で構成されています。入力フォームのHTMLは、ブラウザ上でユーザから受け取った値をGETのパラメータとして、API問合せ結果表示用処理に引き継ぎます。API問合せ結果表示用処理は、パラメータの値を用いてウェブAPIを問合せ、その結果を表示用HTMLに組み込んで出力します。UIパターンは、ウェブAPIを問合せるUIを作成したい時に覚えておくと便利です。APIパターンは、Node-RED上で扱うデータを、ウェブAPIとして問合せできるようにするためのパターンです。処理をウェブAPIとして作成しておくと、UIパターンからの問合せはもちろん、他の開発言語で開発したウェブアプリケーションからNode-RED上の処理を呼び出すことが容易となります。JavaのUI開発フレームワークVaadinでUIを開発し、内部ロジックはNode-REDでウェブAPIとして開発するという手法は、とても開発効率が良くオススメです。Timeoutパターンノードの処理に時間がかかった場合、タイムアウトさせるパターンです。Node-REDでDBやウェブAPIに問合せた際、応答が返って来ず、処理が進まないことがあります。この現象は、ウェブアプリケーションの際に致命的です。処理が終端のHTTP応答ノードまで到達しなかった場合、ユーザのブラウザはローディング状態になってしまい、ユーザは長時間待たされてしまいます。その時は、Timeoutパターンを用いて、指定秒数でタイムアウトし、「タイムアウトしました」というエラーを返す方が、ユーザに親切です。whileパターンノードの接続のみで、while文を実現するパターンです。Java等でwhile文を用いる場合は、変数i=0で初期化、条件文でループ回数指定、i++でインクリメントという3つの手順を行います。Node-REDにおけるwhileパターンは、同様の手順を行う初期化ノード、条件文ノード、インクリメントノードの3ノードから構成されます。whileパターンを用いると、ループ構造の把握が容易となり、リリース後にループ回数を変更する修正も迅速に行えます。ちなみにNode-REDにて、ループ処理を行う場合は、大抵8の字型の接続となりますので、すぐにループ処理を見つけることができます。Sequenceパターン複数のノードから得た処理結果を、集計するパターンです。処理ノードはmsg.payloadを介して1つの値を出力すると、設計がシンプルとなります。複数のノードから取得した値を集計したい場合、単純にノードを横に繫いでしまうととmsg.payloadの値は上書きされてしまいます。Sequenceパターンでは、ノードからmsg.payloadを介して受け取った値を一旦、msg.tmp等の別変数に退避しておき、後続のノードがmsg.payloadに値を格納できるようにします。ノードから値を受け取る処理が全て終了した後、別変数に退避しておいた値を呼び出すことで、集計処理を実現します。AggregatorパターンSequenceパターンと同じく、複数のノードから得た処理結果を、集計するパターンです。Sequenceパターンは、ノードを横に繋いでいくのみであるため、処理ノードか、値を別変数に退避するノードかをノードの接続を見ただけでは、すぐ識別できません。Aggregatorパターンでは、集計ノードへ2つのノードが直接値を渡しているため、ノードの接続を見るだけで直観的に処理を把握できます。別の利点として、複数のウェブAPIに問合せた結果を集計するようなケースにて、並列してウェブAPIへリクエストできるため、処理時間を短縮できる特徴もあります。Separatorパターン1つのノードから2つの異なる値を出力するパターンです。Aggregatorパターンは「2入力」を実現するパターンであるのに対し、Separatorパターンは「2出力」を実現するパターンです。JavaScriptを記述するノードにて、サイズ2の配列をreturnし、出力数を指定するのみで実現できます。MapReduceパターンSeparatorパターンとAggregatorパターンを組み合わせて、MapReduceの処理を実現するパターンです。Map処理は、Separatorパターンを用いて記述します。Map処理を行うノードは、入力値に対してWordCount等の処理を行い、Keyを基にKey-Valueペアの出力先を決定します。Reduce処理は、Aggregatorパターンを用いて記述します。Reduce処理を行うノードは、事前に指定したMap数分の入力が来た後、同じKeyを持つValueのデータに対して集計等の処理を行います。Java等でMapReduce処理を記述すると、多重ループ等が原因で複雑になりがちですが、Node-REDではMapReduceの処理フローをノードの接続としてグラフィカルに記述できるため、簡単に作成でき、理解も容易です。Matcherパターンノードのネットワーク構造を探索して、条件に一致するか判定するパターンです。JavaScriptを記述するノードは、値をreturnしないと後続ノードの処理を実行しないという動きをします。Matcherパターンの条件ノードは、この特徴を生かし、入力値がノードの条件を満たす場合のみ、次のノードに処理を引き継ぎます。Matcherパターンでは、処理全体として満たしたい条件を、条件ノードのネットワーク構造として作成しておきます。判定したいデータを入力すると、そのネットワーク構造を探索し、ネットワーク構造から値が出てきた場合、条件に一致していることが分かります。図の例では、Matcherパターンを用いて、入力した英文の文型を判定しています。内部では、品詞を判定する条件ノードから成るネットワーク構造を通過させることで、SV、SVC、SVO、SVOO、SVOCのどの文型に該当するかを判定しています。この処理は一度、品詞を判定するノードを作成しておけば、リリース後に品詞の並びを変える必要があっても、ノード接続を変える操作だけで修正が完結します。Node-REDは、iPadやAndroidタブレットでノードの接続を変更できるため、例えば通勤電車の中等、どこでも修正作業が行えます。Stateパターン状態遷移を扱うパターンです。Stateパターンは、状態を表す状態ノードと、遷移先を表すSwitchノードから構成されます。状態ノードは、その状態に必要な処理を行い、Switchノードに判定したい値を引き継ぎます。その後、Switchノードは引き継いだ値の内容に従い判定し、次の状態ノードへ処理を移します。Java等で状態遷移を記述する場合は、状態遷移表を活用する等の方法を用いますが、コードから遷移の全体像を理解するは困難です。Node-REDを用いることで、状態の遷移が一目瞭然となります。最後に本記事を通して、新たな発見が得られれば幸いです。面白い他のデザインパターンや、もっと良いコードに気づいた方は、ご連絡ください。皆で議論し、新たなデザインパターンを見つけてゆけたら、良いなと考えています。※本デザインパターンの内容は、RedConnectの技術サイトでも紹介されました。※Store、Search、UI、Separatorパターンは、NECのNode-REDのドキュメントでも紹介されています。ソースコードNode-REDは、開発環境の右上メニュー->Import->Clipboardからソースコードを貼り付けることができます。response","z":"d4f1d484.2b0e28","name":"HTTP応答","x":590.7738914489746,"y":636.6824054718018,"wires":[]},{"id":"c58cb91a.3a7348","type":"change","z":"d4f1d484.2b0e28","name":"headers削除","rules":[{"t":"delete","p":"headers"}],"action":"","property":"","from":"","to":"","reg":false,"x":299.96350479125977,"y":636.7300310134888,"wires":[["1e70abb0.e18f54"]]},{"id":"1e70abb0.e18f54","type":"template","z":"d4f1d484.2b0e28","name":"出力HTML","field":"payload","format":"html","template":"<HTML><BODY>\nテーブルの行数は{{payload.1}}です。response","z":"d4f1d484.2b0e28","name":"HTTP応答","x":603.0953102111816,"y":1185.523699760437,"wires":[]},{"id":"a1c844c3.5e37b8","type":"change","z":"d4f1d484.2b0e28","name":"headers削除","rules":[{"t":"delete","p":"headers"}],"action":"","property":"","from":"","to":"","reg":false,"x":312.2849235534668,"y":1185.571325302124,"wires":[["43ea4055.bc15c"]]},{"id":"43ea4055.bc15c","type":"template","z":"d4f1d484.2b0e28","name":"出力HTML","field":"payload","format":"html","template":"<HTML><BODY>\nテーブルの行数は{{payload.1}}です。\n</BODY></HTML>","x":461.00000762939453,"y":1185.666612625122,"wires":[["3a14a3b7.c5eb5c"]]},{"id":"570e59a7.a8f1a8","type":"delay","z":"d4f1d484.2b0e28","name":"5秒間待機","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":248.32141876220703,"y":1228.8412942886353,"wires":[["4eb3d9c9.b14c28"]]},{"id":"4eb3d9c9.b14c28","type":"template","z":"d4f1d484.2b0e28","name":"タイムアウト表示HTML","field":"payload","format":"html","template":"<HTML><BODY>\nタイムアウトしました。upLoginユーザーは見つかりませんでした。