Robotics Studioの肝である“SOA”を理解するうえで、最も重要となるのが「ポート」と「ハンドラ」です
SOAのサービスは、メッセージを交換することによって処理を進めます。その際にポイントとなるのが、「ポート」と「ハンドラ」です。
ポートとは“メッセージの受け口”、ハンドラとは“そのメッセージに対する動作を定めるプログラム”を指します。
そこで、今回はSOAを支える2本柱ともいえるポートとハンドラについて解説します。
前回、Microsoft Visual C# 2005 Express SP1(以下、VC#)のテンプレートを使ってサービスを作り、ロボットの状態を実装し、Visual Programming Language(以下、VPL)から読み出す作業を行いました。
今回はテンプレートに対して、ポートとハンドラを実装し、VPLを使ってメッセージを投げ込み、ハンドラが正常に動作するかどうかをチェックしてみましょう(注)。
一般的に、サービスの規模が大きくなると受信するメッセージは増えるので、当然、それらメッセージを受けるポートの数も増加します。しかし、ポートが増えることでプログラム内に同じ形式の文を繰り返し記述することになり、プログラムの可読性(信頼性)は低下してしまいます。
この問題を避けるためには、連載第2回「身近な例から学ぶ“サービス”」で説明したように、いくつかのポートをまとめて“ポートセット(port set)”とし、メッセージを一括して受信するようにします。いい換えれば、「一般の家庭のように、1つの郵便受けで家族全員の郵便を受け、そこから郵便を取り出して、家族に分配する」といったイメージです。
連載第3回「サービスはロボットの状態と連動して動くもの」では、ロボットの状態を処理するプログラムを作りました。その際、VC#のテンプレートに対して状態のプロパティを定義し、Getメソッドを使ってそれらを呼び出してダイアログを表示しました。
実はこのGetメッセージは、MSRSのポートセットを使って処理を行っていたのです。
前回は、状態に注目してプログラムを作りましたが、前述のとおり今回は視点を変えてポートセットとハンドラに注目してプログラムを作ります。
まず、VC#を起動して、連載第1回「サービス開発の基礎と流れ」で解説した方法に従って、新規プロジェクト「MyProj2」を作成します。
作成されたテンプレートを眺めてみてください。前回のようにGetメッセージを処理するプログラムが書き込まれているはずです。
「早速、プログラムを作成しましょう!」。
と、いきたいところですが、まずはテンプレート内の「Get」を解析することから始めましょう。
MyProj2プロジェクトの[ソリューション エクスプローラ]で、MyProj2Types.csをダブルクリックします。
編集ウィンドウに表示されたプログラムを上から下へたどって、「MyProj2Operation」クラスを見つけてください(ソース1)。
これが、ポートセットを定義するクラスです。ポートセットを定義するクラスには、[ServicePort()]という属性が付いています。
ソース1の最初のセンテンスは、以下のようになっています。
public class MyProj2Operations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get>
コロンの左側の“MyProj2Operations”は、ここで使用するポートセットのクラス名です。また、コロンの右側の“PortSet”は、MSRSが定義したクラスの名前です。この記述は「MyProj2Operationsは、MSRSのPortSetクラスを継承している」ことを示します。
つまり、ここでは3種のメッセージ
を受け取るポートセット「MyProj2Operations」を定義しているのです。
次に、MyProj2Types.csのソースを見てください。ソース2のようなGetメッセージを定義しているクラスがあります。
ポートセットには、複数のメッセージが投函(とうかん)されるので、投函されたメッセージをソートして、おのおのハンドラへ送り込む必要があります。そのため、ポートセットを作るときには、必ずそのポートセットが受け取るメッセージ(厳密にいえば、メッセージのクラス)を定義する必要があります。
ソース2の最初のセンテンスは、以下のようになっています。
public class Get : Get<GetRequestType, PortSet<MyProj2State, Fault>>
コロンの左側の“Get”はメッセージに付けた名前であり、コロンの右側の“Get”は、MSRSが定義したクラスです。つまり、MSRSにGetというメッセージのクラスが定義されているので、そのクラスを使ってGetというメッセージを作ったということです。名前が同じなので、混同しないように注意してください。
次に、[ソリューション エクスプローラ]でMyProj2.csをダブルクリックしてください。
編集ウィンドウに表示されたプログラムを上から下へたどると、メインのポートを生成するセンテンスがあります(ソース3)。
ここでは[ServicePort()]属性を付けて、メインポートを生成しています。これで、ポートセットのインスタンス(_mainPort)が作成されるのです。
さらに、MyProj2.csを下にたどるとメッセージGetに対するハンドラがあります(ソース4)。
メッセージのハンドラに対して、[ServiceHandler()]という属性を付けています。
最初のセンテンス、
public virtual IEnumerator<ITask> GetHandler(Get get)
によって、GetHandlerというハンドラを登録しています。“GetHandler”はハンドラの名前なので、どのような名前を付けても構いませんが、引数の「(Get get)」は、ハンドラをソートする際の識別子なので変更できません。
また、メッセージのGetは状態を返すプログラムなので、
get.ResponsePort.Post(_state);
によって、サービスの状態(_state)をResponsePortへ投函します。
これまでの解析結果からメッセージを作成するに当たって、
という順番でプログラミングを進めることにします。
Copyright © ITmedia, Inc. All Rights Reserved.