33

ドメイン内にいくつかの異なる境界コンテキストがあります。CRUD 操作の検証は、各 Bounded Context に組み込まれています。

たとえば、作成者がグループ リーダーである場合にのみ、GAME というエンティティを作成できます。

この例では、境界付けられたコンテキスト (BC) が 2 つあります。1 つはGame BCで、もう1 つはUser BCです。この問題を解決するには、ゲーム BCで、ゲームの作成に進む前に、ユーザー BCに対してIsGroupLeader()などのドメイン サービス呼び出しを行う必要があります。

このタイプの通信は、DDD によって推奨されているとは思いません。Game BCにもUser エンティティを含めることができますが、同じUser エンティティが別の BC の別のコンテキストで異なる方法で使用されているため、使用したくありません。

私の質問は次のとおりです。

  1. Game BCがUser BCにイベントを送信してUser のステータスを尋ねる場合、ドメイン イベントを使用する必要がありますか? このアプローチでは、 IsGroupLeader のような同期呼び出しを行わず、is_group_leaderというイベントを呼び出します。次に、ゲーム BC は、ユーザー BC がイベントを処理してステータスを返すまで待機する必要があります。ゲーム BC は、ユーザー BC がイベントを処理した後でのみ、ゲーム エンティティを作成します。

  2. CQRS は私の問題の解決策ですか?

どんなアイデアでも大歓迎です。

4

6 に答える 6

35

BC を統合する場合、いくつかのオプションがあります。外部 BC への呼び出しが推奨されない理由は、両方の BC が同時に動作している必要があるためです。ただし、これは多くの場合、まったく問題なく受け入れられ、別の方法よりも簡単です。別の方法として、ゲーム BC にユーザー BC からのイベントをサブスクライブさせ、必要なデータ (この場合はユーザーがグループ リーダーであるかどうかに関する情報) のローカル コピーを保持する方法があります。このように、ゲーム BC がユーザーがグループ リーダーであるかどうかを判断する必要がある場合、ユーザー BC を呼び出す必要はなく、ローカルに保存されているデータを読み取るだけです。このイベント ドリブンの代替案の課題は、イベントの同期です。ゲーム BC がユーザー BC からすべての適切なイベントを受信して​​いることを確認してください。もう一つの課題はBCは任意の時点でわずかに同期していない可能性があるためです。

CQRS は、この問題とはある程度直交しています。

于 2013-05-23T14:59:37.417 に答える
4

私はあなたがほとんどそこにいると思います。良い解決策に近い。これら2つを2つのBCに分割する必要があるかどうかはわかりません。User Aggregateroot (?) と Game は 1 つの BC に属し、相互に依存している可能性があります。ユーザーは「1つまたは複数の」ゲームへの「メンバーシップ」を持っています(エンティティの関係を推測するだけです)。しかし、私は今ブレインストーミングを行っているところです。従うようにしてください:)さまざまなアプローチが続きます:

最初 の GameBC には、実際に UserMembership をパラメータとして取る Create() メソッドがあります。(ユーザー メンバーシップ) を作成します。次に、UserMembership エンティティを通じて、メンバーシップの種類とこれがユーザーであることがわかります。承認された場合、ゲームが作成されます。例外がスローされない場合、またはゲームがルール違反メッセージを受け取る場合は、クライアントにどのようなアプローチで通信するかによって異なります。ドメインの知識を漏らすことなく、アプリケーション層で調整を行うことができます。

2番目 に、他の回答の1つとして行います。Game.Create(UserId) メソッド内で CreateGameEvent を発生させます。そのイベントは、アプリケーション層に存在し、リポジトリを介して UserMembership を検索する EventHandler (アプリケーションの起動時に IoC によって登録される) によってキャッチされます。ドメイン知識のわずかな漏えいは、アプリケーション層で検証されることを誰が許可されているかを知るビジネス ルールです。これは、CreateGameEventHandler に UserId と RuleRef (文字列「CAN_CREATE_GAME」または列挙型) を取得させ、UserPermission オブジェクトに権限を確認させることで解決できます。そうでない場合。アプリケーション層で例外がスローされ、キャッチされます。欠点は、Create メソッドでアクセス許可参照文字列をハードコーディングする必要がないことです。

3 番目は、2 番目のアプローチが終了するところまで続きます。SRP の原則に従っている場合、GameBC はユーザー権限の検索を行うのに適切な場所ではない可能性があることを知っています。しかし、何らかの形でそのメソッドの周りでアクションがトリガーされます。別の方法として、Create (GroupLeader ユーザー) を使用することもできます。または、Game.Create(User user) を使用して、User が GroupLeader タイプであることを検証できます。Create(GroupLeader) は、このメソッドを呼び出す必要があることを示します。

最後 これを書いているとき、私が今より好きな代替案かもしれません。エンティティを作成するときは、通常、その Create(Save) メソッドをリポジトリに配置します。IGameRepository インターフェイスは、ドメイン アセンブリ プロジェクトの Game Entity の隣にあります。ただし、Game Entity のライフサイクルの開始を担当する GameFactory を作成することもできます。ここにも Create メソッドを置くのに適した場所があります... GameFactory.Create(GroupLeader) { return new Game.OwnerUserId = GroupLeader.Id; 次に、それを保存するだけです IGameRepository.Save(Game)

次に、他の開発者に「ゲームを作成するには GroupLeader インスタンスが必要です」と伝える直感的で自己記述的な方法があります。

最後に、ドメインを知っていること、そして自分に最も適したものを見つけられることを願っています。実用的になり、Eric Evan のハードコアに行かないでください。物事がどのように行われるかという「宗教」に固執している開発者が非常に多くいます。プロジェクトの規模、お金、時間、他のシステムへの依存度なども、DDD をどれだけ厳密に実行できるかに影響します。

幸運を。

于 2013-05-24T13:12:41.083 に答える
0

ユーザーとユーザー情報の役割を渡し、ゲーム BCGame bounded context serviceの内部にも配置することをお勧めします。GroupLeader value objectこのようにして、誰が誰であるかを常に知ることができますgroup_leader

于 2019-11-06T09:54:07.543 に答える