web-dev-qa-db-ja.com

RESTful APIは貧血ドメインモデルを奨励する傾向がありますか?

私は、ドメイン主導の設計とRESTをサービス指向アーキテクチャーに適用しようとしているプロジェクトに取り組んでいます。100%については心配していませんRESTコンプライアンス。リソース指向のHTTP APIを構築しようとしていると言ったほうがいいでしょう(〜 レベル2 RichardsonのREST成熟度モデル) 。それにもかかわらず、RPCスタイルのHTTPリクエストの使用を避けようとしています。つまり、POSTを使用してIsPostalAddressValid(...)、 例えば。

ただし、これを強調すると、ドメイン主導の設計を適用しようとする試みが犠牲になるようです。 GETPOSTPUTDELETEとその他のめったに使用されないメソッドのみを使用して、CRUDdyサービスを構築する傾向があり、CRUDdyサービスは貧血ドメインモデル。

POST:データを受信して​​検証し、データベースにダンプします。 GET:データを取得して返します。そこには実際のビジネスロジックはありません。また、サービス間でメッセージ(イベント)を使用していますが、ビジネスロジックのほとんどは、その周りに構築されているように思えます。

RESTおよびDDDがある程度の緊張状態にありますか?(または、ここで何か誤解していますか?何か他のことを間違っているのでしょうか?)サービス指向で強力なドメインモデルを構築することは可能ですか? RPCスタイルのHTTP呼び出しを回避しながらアーキテクチャ?

34
Kazark

Martin Fowlerの最初の分散システムの法則: "オブジェクトを配布しないでください!" リモートインターフェイスは粗く、内部インターフェイスは細かくする必要があります。多くの場合、リッチドメインモデルは 制限付きコンテキスト 内でのみ適用されます。

REST APIは、2つの異なるコンテキストを分離します。どちらにも独自の内部モデルがあります。コンテキストは、「貧血」オブジェクト(DTO)を使用した粗粒度のインターフェース(REST API)を介して通信します。

あなたの場合、あなたはREST APIである境界を越えてコンテキストを広げようとしているように聞こえます。これはきめ細かなリモートインターフェースまたは貧血モデルにつながる可能性があります。プロジェクトによっては、問題ではないかもしれません。

39
simoraman

POSTは意図的に"意図的に曖昧;"となるように設計されましたPOSTは実装固有のものです。Twitterや他のAPIデザイナーが行うことを妨げているのは、各POSTメソッドをAPIの非CRUD部分に独自の要件に従って定義しますか?POSTはキャッチオール動詞です。他の動詞は、実行する操作に適しています。

別の言い方をすれば、あなたの質問は"「スマート」オブジェクトはRPCスタイルのデザインを奨励しますか?" Martin Fowler( "Anemic Domain Model"と名付けた)でさえもそれを認めていますDTOにはいくつかの利点があります。

ドメインオブジェクトに動作を組み込むことは、ドメインロジックを永続性やプレゼンテーションの責任などから分離するためにレイヤーを使用するという確固たるアプローチと矛盾しないはずです。ドメインオブジェクトに含める必要のあるロジックはドメインロジック-検証、計算、ビジネスルール-呼び出したいものは何でもかまいません。

Richardson Maturity Model については、「貧血ドメインモデル」について気にすることなく、レベル3に到達できます。動作をブラウザーに転送するつもりはないことを覚えておいてください(モデルを介してJavascriptを挿入する予定がない限り)。

RESTは主にマシンの独立性についてです。 RESTモデルを実装して、エンドポイントにリソースを表現させ、APIのコンシューマーがこれらのリソースに標準的な方法で簡単にアクセスして維持できるようにします。それが貧弱であると思われる場合、それならそれでいい。

関連項目
私はもっと動詞が必要です

10
Robert Harvey

REST APIは、プレゼンテーションレイヤーの一種にすぎません。ドメインモデルとは関係ありません。

あなたが投稿した質問は、どういうわけか互いに適応させる必要があるという混乱から来ています。あなたはしません。

ドメインモデルをORMを介してRDBMSにマップするのと同じ方法で、ドメインモデルをREST APIにマップします。このマッピングレイヤーが必要です。

ドメイン←ORM→RDBMS
ドメイン←RESTマッピング→REST API

4

これ 記事は主題にかなり関連しており、私はあなたの質問に答えると信じています。

私があなたの質問に非常によく答えると思う中心的な概念は、言及された記事の次の段落に要約されています:

「REST AP​​Iのリソースとドメインドリブンデザインのドメインエンティティを区別することは非常に重要です。ドメインドリブンデザインは、物事の実装側(API実装を含む)に適用され、REST AP​​Iは、APIの設計と契約を推進します。APIリソースの選択は、基盤となるドメイン実装の詳細に依存するべきではありません。」

3
Majix

私見彼らは貧血ドメインモデル(ADM)を奨励する傾向があるとは思わないが、彼らは時間をかけて物事を考える必要がある。

まず第一に、ADMの主な特徴は、ADMの動作がほとんどまたはまったくないことです。これは、システムに動作がないと言っているのではなく、通常、ある種のServiceクラスにあるということです( http://vimeo.com/4359819 を参照)。

そしてもちろん、その振る舞いがADMに存在しない場合、何をしますか?もちろん答えはデータです。そして、これはどのようにREST APIにマップされますか?データはリソースのコンテンツにマップされ、動作はHTTP動詞にマップされます。

したがって、リッチドメインモデルを構築するために必要なものがすべて揃い、HTTP動詞がデータのドメイン操作にどのようにマッピングされるかを確認し、それらの操作をデータをカプセル化する同じクラスに配置する必要があります。

問題が発生する傾向があるのは、動作が単純なCRUDを超えている場合、つまりドメインの他の部分に副作用がある場合に、HTTP動詞がドメインの動作にどのようにマッピングされるかを確認するのが難しいことです。 HTTPリクエストによって変更されるリソース。この問題を解決する1つの方法は、ドメインイベント( http://www.udidahan.com/2009/06/14/domain-events-salvation/ )を使用することです。

3
RibaldEddie

私が見て/構築したいくつかの合理的に成功した実装は、エンティティに作用する粗い「ビジネスフレンドリーな」メソッドを使用して動詞と名詞のメタファーをどのように混合するかという質問に答えます。

したがって、(終了した)getName()メソッド/サービスの代わりに、getPerson()を公開し、identifier-type/IDなどを渡して、Personエンティティ全体を返します。

そのようなコンテキストでのPersonエンティティの動作は適切に伝達できないため(おそらく、このようにデータ中心のコンテキストにあるべきではありません)、次の要求/応答ペアのデータ(対オブジェクト)モデルを定義することは完全に合理的です。サービス。

サービスと定義された動詞自体が、ドメインに許可された動作、コントロール、さらにはエンティティーの状態遷移規則さえも追加します。たとえば、transferPerson()サービス呼び出しで発生することに関してドメイン固有のロジックがありますが、インターフェース自体は入力/出力エンティティ/データのみを定義し、それらの内部動作を定義しません。

たとえば、transfer動詞の実装はPersonクラスに属するか、Person中心のサービスに関連付けられていると言う著者には同意しません。実際、Personとそのオプション(この単純な例では)のtransferのメソッドは、Carrierによってより適切に定義されます。ここで、Person利用可能な転送方法や転送が行われる方法(ジェットエンジンの動作方法を知っている人)さえ知らない可能性があります。

これはPersonエンティティを貧血にしますか?私はそうは思いません。

外部クラスによって定義されるべきではない、健康状態のようなPersonの内部にあるPerson固有のものに関するロジックが存在する可能性があります。

ただし、ユースケースによっては、トランスポートシステムの座席割り当てサービスなど、特定のシステムではエンティティクラスに重要な関連動作がないことはまったく問題ありません。そのようなシステムは、Personインスタンスと関連する識別子を処理するRESTベースのサービスを実装する可能性がありますが、それらの内部動作を定義/実装することはありません。

1
Darrell Teague

POSTをできるだけ使用して、モデルを動詞の基本セットに詰め込もうとしているのが問題ですか?

それは必要ではありません-ほとんどの人にとってRESTはPOST、GET、PUT、DELETEを意味しますが、http rfcはこう言っています:

HTTP/1.1の一般的なメソッドのセットを以下に定義します。このセットは拡張できますが、個別に拡張されたクライアントとサーバーで同じセマンティクスを共有する追加のメソッドを想定することはできません。

SMTPなどのシステムは、同じスタイルの動詞ベースのメソッドを使用しますが、まったく異なるセットを使用します。

したがって、これらを使用する必要がある理由はありません。好きな動詞のセットを使用できます(ただし、基本的な4で必要なすべてのことを少し考えて実行できることがわかります)。 RESTを他のメカニズムと区別するのは、これらの動詞を実装するそのステートレスで一貫した方法です。基本的には行っていないので、階層間でメッセージパッシングシステムを実装しないでください= REST次に、代わりにメッセージパッシング、RPC、またはメッセージキューメカニズムを使用します。これにより、RESTの利点が間違いなく失われます(つまり、それはそれがhttp接続で本当にうまくいくようにします)。

フル機能の複雑なメッセージングプロトコルが必要な場合は、それを構築します(Webで実行できる場合は、RESTが非常に人気がある理由があります)。それ以外の場合は、 RESTのアーキテクチャ設計。

0
gbjbaanb