Skip to content
uupaa edited this page May 11, 2016 · 11 revisions

Postal.js はメッセージの送信により、オブジェクトを疎結合にする仕組みを提供します。
よく似た仕組みには Observer パターンや Pub/Sub パターンなどが存在します。

密結合と疎結合

システムを構成する部品同士が複雑に絡み合い、固着した状態を 密結合 と呼びます。
反対に、各部品が互いの存在をそれほど意識せず、フレキシブルに機能する状態を 疎結合 と呼びます。

密結合なシステムから疎結合なシステムへ

密結合のシステムを図式すると、マンガの集中線のように、 3〜4個の中心的なオブジェクトから周囲のオブジェクトに多くの交差する線が引かれてしまう状態になります。
このようなシステムは時間と共に線が増え、メンテナンスも難しくなります。

メソッドを直接呼び出している部分をメッセージの送信に置き換え、
オブジェクトが互いの存在を強く意識せずに済む状態にできれば、
システムをフレキシブルで、部品の入れ替えが可能な"疎"な状態に維持できます。

郵便配達の流れを模倣したAPIセット

Postal.js を使ってメッセージを配達する流れは、現実世界の郵便配達の流れとよく似ています。

  1. 郵便局に受取人の住所を登録します ( Postal#register )
    • receiver には郵便受け( inbox メソッド )が実装されている必要があります
  2. 宛先が書かれた封筒を用意します ( Postal#to, Envelope )
  3. 封筒にメッセージを入れて投函します ( Postal#send, Postal#post )
  4. 宛先の郵便受けにメッセージが届きます ( call receiver.inbox(message, params ...) )

これを Postal で実装すると、以下のようになります。

// メッセージを受け取るオブジェクト( receiver )を用意します。
var receiver = {
        inbox: function(message, param...) {  // 4. 宛先にメッセージが届きます
            console.log("message: " + message);
            return "world";
        }
    };

var postal = new Postal();                  // 郵便局(Postal)を作成します
postal.register(receiver);                  // 1. 郵便局(Postal)に受取人(receiver)を登録します

var envelope = postal.to(receiver);         // 2. 宛先が書かれた封筒(Envelope)を用意します
var resultObject = envelope.send("hello");  // 3. 封筒にメッセージ("hello")を入れて投函(send)します

resultObject は、receiver.inbox() の実行結果が格納されたオブジェクトです、
resultObject からメッセージの送信結果を取得できます。

var receiverID = postal.id(receiver);       // receiver の ID を取得する

resultValue = resultObject[receiverID];     // ID で戻り値を検索
console.log( resultValue );                 // -> "world"

また、1人の receiver から反応を貰えれば良い場合は、 first を使い、以下のようにメッセージの受け取りを簡略化できます。

var envelope = postal.to(receiver);         // 2. 宛先が書かれた封筒(Envelope)を用意します
// var resultObject = envelope.send("hello");  // 3. 封筒にメッセージ("hello")を入れて投函(send)します
// var receiverID = postal.id(receiver);       // receiver の ID を取得する
// resultValue = resultObject[receiverID];     // ID で戻り値を検索
// console.log( resultValue );                 // -> "world"

var resultValue = envelope.first("hello");    // 3. 封筒にメッセージ("hello")を入れて投函(send)し、結果を1つだけ返します
console.log( resultValue );                   // -> "world"

Postal のメリット

Postal のメリットは以下になります。

  • メッセージを使ったゆるい規約に基づいてシステムを後から拡張できます
  • 相手の状態をあまり意識せず、とりあえずメッセージを投げられます
    • 相手が居なくなっている場合はメッセージは届かず、エラーにもなりません
  • 同期, 非同期でメッセージを簡単に投げられます
    • 同期送信( send, first )を使うと戻り値が得られます
  • メッセージと共に任意の数の引数を渡せます

デメリットは特にありません。

システムの登場人物が数人程度なら Postal.js は特に必要ないでしょう。
大所帯になって来たタイミング(8人〜)で組み込むと、理想的に機能するはずです。