寛容な読取側 (Kan'yōna Dokushitsugawa)

2011年5月9日 (2011 Nen 5-gatsu 9-nichi)

ウェブサービスを使用することの利点の1つは、システムのさまざまな部分をデカップリングできることです。人々は、ある程度の分離を保ちながら、別々のコードベースで作業できます。ある程度のデカップリングは実現できますが、サービスは依然としてインターフェースを介して互いに通信する必要があるため、カップリングを完全に排除することはできません。残念なことに、多くのチームはこのカップリングを本来あるべき状態よりもはるかに悪化させています。

デカップリングされた協調の支配法は、ポステルの法則である必要があります。

自分自身が行うことについては保守的に、他者から受け入れることについては寛大に。

-- Jon Postel

連携するサービスの場合、最も厄介な点の1つは進化です。サービス定義を最初に正しく作成すれば変更する必要がなくなるため、変更する必要がないと信じている人もいますが、私の常連の読者の方々は、私が彼らのパーティーに参加しないことに驚かないでしょう。サービスを進化させるためには、プロバイダーが新しい需要をサポートするための変更を行いながら、既存のクライアントへの破壊を最小限に抑えることができるようにする必要があります。

このブログエントリを書いた後、Rob Daigneauがこのパターンの完全な説明をService Design Patternsに掲載しました。

これを台無しにする一般的な方法は、何らかのスキーマ駆動型のサービスエンドポイントのバインディングを使用することです。その例としては、XSD定義からC#クラスをコード生成することが挙げられます。これは時間節約機能として宣伝されています。サービスプロバイダーはサービスのXSD定義を公開し、コンシューマーはコピーを取ってクラスを生成します。ほら、プログラミングなしです。プロバイダーがインターフェースに変更を加える必要が生じるまで、たとえばフィールドを追加するまで、うまく機能します。このようなインターフェースにフィールドを追加することは、誰にとっても破壊的な変更にはならないはずです。しかし、多くの場合、これらのスキームを破壊します。

私の推奨事項は、サービスからデータを読み取る際にはできるだけ寛容になることです。XMLファイルを使用している場合は、必要な要素のみを取得し、不要な要素は無視します。さらに、使用しているXMLの構造に関する最小限の仮定を行います。/order-history/order-list/orderのようなXPath検索を使用するのではなく、//orderを使用します。あなたの目標は、あなたのコードを壊さないはずの変更をプロバイダーが行えるようにすることです。一連のXPathクエリは、XMLペイロードに対してこれを行うための優れた方法ですが、他のものにも同じ原則を適用できます。

さらに、このようなデータペイロードを読み取るコードは1つだけであることを確認してください。Data Transfer Objectの目的の1つは、データペイロードを便利なオブジェクトでラップして、システムの残りの部分が単にanOrderHistory.ordersを実行し、寛容な読取側でさえ壊れるような変更に影響されないようにすることです。

データ転送プロトコルがバイナリの場合でも、この原則を念頭に置いておく価値があります。接続の両端にJavaプログラムがあり、メッセージサイズを小さくするためにバイナリ転送を使用したいとします。この状況にあるほとんどの人は、Javaの組み込みシリアル化メカニズムを使用してオブジェクトを直接シリアル化しますが、一方の側がフィールドを追加すると転送が中断されます。最初にデータを汎用コレクション(リストとマップ)に入れ、それからそれらのコレクションをシリアル化することで、これを簡単に回避できます。マップにフィールドを追加しても、もう一方の側で逆シリアル化され、寛容な読取側がそれを無視するのは簡単です。

サービスプロバイダーがサービスを進化させるのに役立つように、通信のどの部分を実際に読み取っているかを伝えることができます。これを行う良い方法は、読取側とそのテストを送信することです。これにより、彼らはビルドプロセスでそれらを使用して、潜在的な破壊を検出できます。皆さんの中には、これがコンシューマ駆動契約への次のステップであると認識する人もいるかもしれません。

参考資料 (Sankō Shiryō)

このパターンの完全な説明は、Service Design Patternsにあります。

同僚のIan Cartwrightは、数年前、これに関する有用なブログ記事のセットを投稿しました。彼はスキーマ検証は、偽の安心感を与えること、そしてシリアル化には危険性があること、一般的にそして特にドメインオブジェクトの場合を指摘しています。

Saleem Siddiquiは、寛容な読取側が寛大な書込側とどのようにうまく機能するかについて説明しています。