WCF / SOA-単純な要求のパラメーターオブジェクトを作成する理由


12

当社はかなり大規模なSOAイニシアチブを開始しています。私たちは多くのことを正しくやっています。良いコミュニケーションがあります。必要に応じてツールの費用。そして、移行に役立ついくつかの優れた専門知識をもたらしました。

私たちはグループとして従うことができる標準を開発しようとしていますが、提案されている標準の1つが私をかなり悩ませています。

すべての操作が要求オブジェクトを受け取り、応答オブジェクトを返すパターンを標準化しました。

私はこれが多かれ少なかれ多くの人々にとって標準的なアプローチであることを理解していますが、なぜ私は気にする必要があるのでしょうか?(私は受け取った知恵があまり得意ではありません。なぜか必要です)。

私が提供するサービスのほとんどは、単純な組織メタデータの取得です。たとえば、特定のユーザーのセキュリティポリシーを見つけます。これにはユーザーIDのみが必要です。標準では、この要求をオブジェクトにラップし、返されたポリシーを応答オブジェクトにラップする必要があると説明されています。

私の不安は、契約から生成されるWSDLを見ると増幅されます。WCFは要求および応答メッセージを自動的に生成し、要求/応答オブジェクトもラップします。

複雑なリクエストを行う場合は、複雑な入力オブジェクトが必要であることを完全に理解しています。これは、サービスが関与していなくても行うことです。

私の質問は、次の場合に要求と応答を自動的にラップする必要がある理由です。

  • シンプルなサービスの表現力が低下します
  • とにかく複雑なサービスのためにそれをするでしょう
  • とにかくWCFは要求/応答メッセージを作成します

このアプローチを支持する次の議論を見つけました。

オプションのパラメーターを要求オブジェクトに組み込むことにより、バージョン管理をサポートします。

当時、私はかなりの量のCOMを実行していましたが、これはバージョニングのほぼアンチパターンと考えています。いくつかの点で、私はそれが助けになると思いますが、それが助けになる場所では、とにかく既にパラメータオブジェクトを持っていると期待しています。

共通のデータと動作を基本クラスに分離できます

これは私にいくらかの重さをもたらします。

RPCスタイルの動作からメッセージング動作に人々を誘導します

マイクロソフトのサイトでこれを読んで、教祖から聞いたが、それが何を意味するのか、なぜそれが価値があるのか​​、まだはっきりとはわからない。自然に見えるインターフェースは、人々がリモートサービスを呼び出していることを忘れがちなのでしょうか?

おそらく300のメソッドのシグネチャをリファクタリングすることを検討しているので、これは些細なことではありません。私は実装における一貫性の大ファンですので、私は喜んで痛みを引き受けます。それは最終的にすべての価値があることを知るのに役立ちます。

回答:


3

バージョニングはおそらく最良の議論だと思います。次のような既存の運用契約がある場合

int GetPersons(int countryId);

後で別のフィルターなどで強化したい

int GetPersons(int countryId, int age);

一意でなければならないため、新しい操作コントラクトを新しい名前で記述する必要があります。または、下位互換性のために古いv1を引き続き使用して、名前を保持してサービスの新しいv2を公開します。

パラメータをオブジェクトにラップすると、デフォルト/オプションのパラメータでいつでも拡張でき、同じ操作コントラクトを再利用しても既存のクライアントはすべて影響を受けません。

ただし、オブジェクトに適切な名前を付けることもお勧めします。単にintをラップしている場合でも、最初からIntMessage類似したものを使用している場合は、それを拡張することに賛成しているわけではありません。たとえばPersonFilter最初から名前を付ける必要があります。つまり、このサービス呼び出しが意味的にパラメータとして何を期待するべきか、したがって何をすべきかについて少し考える必要があります。たぶん(それは非常に曖昧かもしれませんが)適切なサービスを開発し、適切なサイズのAPIを維持するのに役立つでしょう。

共通のデータと動作を基本クラスに分離できます

これには注意が必要です。継承とデータコントラクトはうまく連携しません。それは機能しますが、回線を経由する可能性のあるコントラクトのすべての既知のサブタイプを指定する必要があります。そうしないと、データコントラクトシリアライザーが不明なタイプについて不平を言って失敗します。

しかし、あなたができることは(しかし、おそらくそうすべきではない、私はまだこれについて未定だ)異なるサービス間で同じメッセージを再利用することだ。データコントラクトを別のdllに置くと、クライアントとサービス間で共有でき、基本的に同じメッセージを期待する異なるサービスを呼び出すときにタイプ間で変換する必要がありません。たとえば、PersonFilterを作成し、それを1つのサービスに送信して個人のフィルターリストを取得し、次に別のサービスに送信して、クライアントに同じオブジェクトを保持します。しかし、そのための良い実世界の例を見つけることはできません。そして、危険は常に、データ契約の拡張がこの契約を使用するすべてのサービスにとって十分ではないということです。

全体として、バージョニングを除いて、私はそれをそのように行うための致命的な理由も本当に見つけることができません。


私が取る理由
アンディデイビス

(申し訳ありませんが、コメントインターフェイスは私に悲しみを与えています)答えてくれてありがとう。私がそのような粗雑さでバージョン管理の引数を取る理由は、新しい引数を追加した場合、おそらくセマンティクスを変更したためだと思います。(あなたの例のように)年齢を追加したばかりの場合、セマンティクスはおそらく検索用であり、そこには「検索オブジェクト」が最初からありました。
アンディデイビス

次に、セキュリティポリシーの例を考えてみましょう。おそらく、セキュリティポリシーを適切に提供するために、ユーザーだけでなく、ユーザーが作業している施設を知る必要があると判断するでしょう。これは、引数を追加するだけではなく、呼び出しのセマンティクスを変更しました。以前のバージョンの呼び出し元にこの情報を何らかの方法で提供できると仮定すると、サービス契約をバージョン管理する方が理にかなっていると思います。そうすれば、古いバージョンの実装を分離でき、古いセマンティクスと新しいセマンティクスを混在させることはありません。
アンディデイビス

0

ここでは、データ転送オブジェクトに関するMartin Fowlerのメモが適切だと思います。

Remote Facade(388)などのリモートインターフェイスを使用している場合、それを呼び出すたびにコストがかかります。その結果、コールの数を減らす必要があります。つまり、各コールでより多くのデータを転送する必要があります。これを行う1つの方法は、多くのパラメーターを使用することです。ただし、これはプログラムを作成するのが面倒です。実際、単一の値のみを返すJavaなどの言語では不可能です。

解決策は、コールのすべてのデータを保持できるデータ転送オブジェクトを作成することです。接続を通過するには、シリアル化可能である必要があります。通常、サーバー側でアセンブラを使用して、DTOと任意のドメインオブジェクト間でデータを転送します。

同じことが要求に適用される場合があります。RPCについて、およびその悪い理由:

自然に見えるインターフェースは、人々がリモートサービスを呼び出していることを忘れがちなのでしょうか?

それは本当だと思うが、主な理由ではない。RPCを回避するもう1つの理由は、密結合クライアントとサービスを促進できることです。


入力に感謝しますが、DTOの議論はそれほど重要ではないと思います。呼び出しの数は同じです。WSDLを見ると、すべてが要求と応答オブジェクトに自動的にパッケージ化されています。規約は目に見えるセマンティクスに関するものです。つまり、人々はこれをリモートメソッド呼び出しではなく、リクエストとレスポンスと考えるべきです。
アンディデイビス

密結合クライアントとサービスを奨励するRPCについて詳しく説明していただけますか?これがサービスにまったく影響を与えることはわかりません。クライアントにとって、何かが実際にどのように変化するかはあまりわかりません。どちらの場合でも、サービスによって提供される多くの操作を記述するプロキシを保持しているクライアントがいます。サービスの反対側を実際に実装するのは、いずれにしてもクライアントのビジネスではありません。
アンディデイビス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.