web-dev-qa-db-ja.com

ドメイン駆動設計とクロスドメイン相互作用

私は比較的DDDの初心者ですが、私の知識を引き出して蒸留するために手に入れることができるすべてのものを読んでいます。

私はこのDDDの質問に出くわし、その答えの1つに興味をそそられました。

DDDバインドされたコンテキストとドメイン?

回答の1つで、ポスターは、製品が少なくとも2つのドメインにあるeコマースシステムの例を示しています。

1)製品カタログ2)在庫管理

わかりました。つまり、eコマースのフロントエンドでは、商品情報の表示に関心があり、在庫管理には関心がありません。

だが。在庫レベルをWebページに表示したり、在庫のエディション番号を表示したりすることができます(在庫が本、雑誌などであるとします)。この情報は、インベントリドメインから取得されます。

それで、これをどのように処理しますか?あなたは

a)製品ドメインと在庫ドメインの両方の集合体をロードしますか? b)在庫数と在庫数の製品ドメインエンティティの一部のプロパティを保持し、在庫エンティティが更新されたときにドメインイベントを使用してこれらを更新しますか?

最後の質問です。私たちはドメインの永続性を忘れ/無視し、ドメインについて考えることを意図していることを知っています。しかし、これをよく考えてみると、上の例では、製品カタログと製品在庫用に2つのDBテーブルが存在する可能性があります。これらは同じ製品であるため、これらに同じ識別子を使用しますか?または、データに1つのテーブルと1つのテーブル行を使用して、関連するデータを集計プロパティに単にマップできますか?

10
PendorPaul

在庫レベルをWebページに表示したり、在庫のエディション番号を表示したりすることができます(在庫が本、雑誌などであるとします)。この情報は、インベントリドメインから取得されます。

この時点で気づく主なことは、ビューについて話しているということです。つまり、古いデータの使用は許容されます。

とは言っても、アグリゲート(変更がビジネスインバリアントに違反しないようにする責任がある)と対話する必要はありませんが、アグリゲートの状態の最新のコピーを表示する必要があります。

したがって、私が通常期待するのは、製品カタログに対して実行されるクエリと、在庫に対して実行されるクエリであり、ビューをサポートするために2つをDTOに構成するものです。

製品ドメインと在庫ドメインの両方の集合体をロードしますか?

これがcloseです。何も変更しないので、アグリゲートをロードする必要はありません。しかし、私たちは彼らの状態が必要です。それをロードすることができました。そうは言っても、私は通常、2つのドメインが異なるプロセスで実行されていることを期待します。したがって、両方をロードするのではなく、両方を呼び出すことになります。

在庫数と在庫数の製品ドメインエンティティのプロパティをいくつか保持し、在庫エンティティが更新されたときにドメインイベントを使用してこれらを更新しますか?

「小川を渡らないでください。それは悪いことです。」

イベントを使用してドメインコンテキスト全体で情報を調整する:great idea。あるドメインに属している概念を別のドメインにプッシュすること。それ以外は、素晴らしいアイデアの反対です。

ドメインをクリーンに保ちたい。ドメインと対話するapplicationsは、それほど重要ではありません。したがって、たとえば、Inventoryアプリケーションが製品アプリケーションのサービスを呼び出して、ビューに追加する製品固有の概念を照会するのは妥当です。またはその逆。

単一のアプリケーションを単一のドメインに制限する必要がある理由はわかりません。単一の真の情報源がある限り、トランザクションを好きなように分散できます。

しかし、これをよく考えてみると、上の例では、製品カタログと製品在庫用に2つのDBテーブルが存在する可能性があります。これらは同じ製品であるため、これらに同じ識別子を使用しますか?.

それは簡単な方法でしょう。大まかに言うと、実世界のエンティティは同じなので、同じ識別子を使用します。 2つの異なる境界コンテキストmodelそのエンティティは異なりますが、モデルは実際のエンティティではありません。

それが機能しない場合は、ギャップを埋めるために使用するクエリが必要になります。これの最も一般的なバリエーションは、新しいエンティティが古いエンティティのIDを保持することです。これは、1つのBC内でも確認できます。申請者は、承認されるとクライアントになります。それは別の集計です(クライアントに関連付けられた状態は、申請者の状態とは異なる不変条件の対象となります)。そのため、永続化レイヤーがイベントストリームを使用している場合、新しい集約のストリームには別の識別子が必要になります。したがって、「この申請者はこのクライアントになった」と言う状態がどこかにあるでしょう。

または、データに1つのテーブルと1つのテーブル行を使用して、関連するデータを集計プロパティに単にマップできますか?

YIKES!いいえ、それを行わないでください。ビジネス上の理由なくトランザクションの競合を追加している。

8
VoiceOfUnreason

あなたの質問では、2つの直交するオプションのセットが本当に必要だと思います-

  • 2つのオブジェクトをロードしてそれらのデータを一緒に表示しますか、それとも、必要なすべてを含む1つのオブジェクトをロードしますか?

  • ものを表示するために集約を使用していますか?

CQRSのアプローチを信じている場合、集計は読み取りに最適ではない可能性があることがわかります。アグリゲートをロードするたびに、そのデータを表示するか、それを変更するかに関係なく、並行性と競合をシステムに追加します。また、アグリゲートは、表示用に調整されたアドホックな読み取りモデルを使用する場合よりも、かさばってロードが遅くなる可能性があります。

解決策a)Qから、これらの多くの落とし穴の影響を受けるようです。オプションb)は有効ですが、InventoryManagement集計を変更するときに不変条件を適用するためにProduct BCからのデータが必要な場合にのみ使用します。アグリゲートに変更時にビジネスルールをチェックするために必要なすべてのデータが含まれている方が良いですが、読み取り側ではどこにでも置くことができます。

データに関しては、一般的な推奨事項は、バウンドコンテキストに独自のデータベースを提供することです(展開性とSoCの理由から)。 2つのBC間で製品を一致させる場合は、おそらく同じ識別子を使用する必要があります。

BC間の相互作用については、 https://stackoverflow.com/questions/16713041/communicating-between-two-bounded-contexts-in-ddd もご覧ください。

3
guillaume31

DDDは、ビジネスロジックが複雑なアプリケーション向けです。 「何かを印刷する」ことは、複雑なビジネスロジックではありません。実際にはビジネスロジックではありません。

1つのコンテキストのビジネスロジックが、いくつかのユースケースを適切に処理するために何らかの情報を必要とする場合、その情報はそのコンテキストの一部です。したがって、1つの境界コンテキストが、異なる境界コンテキストで利用可能な情報を必要とする可能性があるという考えは意味がありません。境界コンテキストには必要なすべての情報があるからです。

1
Euphoric

私の観点から見ると、「製品」にはさまざまな定義があります。すべての境界コンテキストには、「製品」ドメインの独自の定義がありません。

  • Content-Management-Bounding-Contextでは、製品には画像と説明テキストがあります。
  • Inventory-Bounding-Contextでは、製品には在庫数量、製品販売者、製品が入手可能になる時期の予測があります。
  • Price-Caculation-Bounding-Contextには、製品が数量ごとにいくらかかるかというルールがあります。

これらの上に、独自の製品定義(他の境界コンテキストの製品ドメインの関連する組み合わせ)を付けて追加のShop-Bounding-Contextを追加します。

Shop-Productには、コンテンツからの「イメージと説明テキスト」と「在庫」からの在庫がありますが、在庫からの「製品販売者」はありません。

この追加のShop-Bounding-Contextは、Bounding-Context-sのコンテンツ、在庫、価格によって異なります

1
k3b