16

とが私のモデルの集合ルートであるBookと仮定します。Author

AuthorsAndBooks読み取りモデルでは、著者と書籍のリストであるテーブルがあります。Book.AuthorId

イベントが発生したときに、新しい行を作成するためのデータBookAddedを受信したいと思います。AuthorAuthorsAndBooks

は集約ルートであるためBook、に関する情報はイベントAuthorに含まれません。また、 rootにはゲッターがないため(CQRSとイベントソーシングに関するすべての例と投稿のガイドラインによる)、これをBookAdded含めることはできません。Author

通常、私はこの質問に対して2種類の回答を受け取ります。

  1. イベントハンドラーで必要なすべてのデータでドメインイベントを強化します。しかし、私が言ったように、私はAggregatesRootsに対してそれを行うことはできません。
  2. ビューモデルから利用可能なデータを使用しますAuthorつまり、ビューモデルからロードし、それを使用してAuthorsAndBooks行を作成します。

最後のものには、並行性に関するいくつかの問題があります。BookAddedイベントの処理中は、作成者データをビューモデルで使用できません。

これを解決するためにどのようなアプローチを使用しますか?ありがとうございました。

4

5 に答える 5

3

あなたの質問にはいくつかのコンテキストが欠けています。たとえば、このイベントにつながるユーザーシナリオは何ですか、また、開始している状態は何ですか?この場合のBDDテストを作成している場合、それらはどのようになりますか?これを知っていると、質問に答えるのに大いに役立ちます。

本を著者に関連付ける問題をどのように解決するかは、ドメインによって異なります。まず、ドメインにAuthor用のアグリゲートとBook用のアグリゲートがあることが理にかなっていると想定しています。たとえば、ライブラリシステムを作成している場合、私は気にしないので、著者用のアグリゲートがあるとは思えません。本を持たない作家、私が気にかけているのは本です。

ゲッターの欠如に関しては、OOPのtell-don't-askスタイルが優先されるため、集約ルートにはゲッターがないことに言及する価値があります。ただし、あるARに何かを実行するように指示し、必要に応じて別のARに何かを指示することができます。重要なことの一部は、ARが、要求して渡すコードを書くのではなく、ARが他の人に自分自身について伝えることです。

最後に、本を追加するときに著者のIDがないのはなぜですか。そのとき、著者が誰であるかをどうやって知ることができますか?私はあなたが次のことをすることができると思います(私のコードはあなたがARの作成に流暢なインターフェースを使用していると仮定していますが、ファクトリー、コンストラクター、あなたが使用するものは何でも置き換えることができます):

CreateNew.Book()
  .ForAuthor(command.AuthorId)
  .WithContent(command.Content);

おそらくシナリオは、新しい著者と一緒に本を追加することです。これを2つの別々のコマンドとして処理するか(ドメインにとってより意味がある場合があります)、次のようにコマンドを処理します。

var author = CreateNew.Author()
  .WithName(command.AuthorName);

var book = CreateNew.Book()
  .ForAuthor(author.Id)
  .WithContent(command.Content);

おそらく問題は、集約ルートIDにゲッターがないことです。これは、必要または一般的ではないと思います。ただし、Idのカプセル化が重要である場合、またはBookAddedイベントで、Idに沿って提供できるよりも多くの作成者に関する情報が必要な場合は、次のようにすることができます。

var author = CreateNew.Author()
  .WithName(command.AuthorName);
var book = author.AddBook(command.Content);

// Adds a new book belonging to this Author
public Book AddBook(BookContent content) {
  var book = CreateNew.Book()
    .ForAuthor(this.Id)
    .WithContent(command.Content);
}

ここでは、著者に本を追加するように指示しています。その時点で、本の集約ルートが作成され、そのIDが本に渡されます。次に、作成者のIDを持つイベントBookAddedForAuthorを作成できます。

最後の1つには欠点がありますが、複数の集約ルートを介して動作する必要があるコマンドを作成します。可能な限り、最初の例がうまくいかない理由を理解しようと思います。

また、私はあなたが探している実装があなたの特定のドメインコンテキストによってどのように決定されるかを十分に強調することはできません。

于 2011-02-27T20:53:07.280 に答える
3

一般的なアドバイスとして、イベントハンドラーをべき等にし、順不同のメッセージ処理を処理できることを確認します(再キューイングするか、欠落データを埋めるためのメカニズムを組み込むことによって)。一方、著者と本がなぜそのような絶望的な集合体のルーツであるのか疑問に思ってください。たぶん、本を追加するときに著者からコピーする必要があります(f *が「本を追加する」とは、そのコマンドはどうですか)。問題は、これらすべての作り上げられた例です。現実の世界に降りてください、私はあなたの問題が存在することを疑っています。

于 2011-02-20T17:18:15.820 に答える
2

IMHO、著者/本のイベントから読み取りモデルにデータを入力し、並べ替えを使用して、イベントが順序どおりにならないケースを処理します(ビューハンドラーは独自の整合性境界内にあり、とにかく順序付け/重複排除のケースを処理する必要があります)。

于 2011-02-19T19:10:00.857 に答える
0

最後のものには、並行性に関するいくつかの問題があります。BookAddedイベントの処理中は、作成者データをビューモデルで使用できません。

「後でイベントを処理する」のはどうですか?したがって、このデータが利用可能になるまで、キューの最後に配置するだけです(おそらく、x回の試行と各試行の間にx回の時間の制限があります)。

于 2011-02-19T18:53:05.057 に答える
0

私が最初に尋ねるのは、読み取りモデルに並行性の問題がある理由です。クライアントがAddBookコマンド内で作成者アグリゲートへの参照を送信している場合、どこから情報を取得しましたか?本と著者が同時に作成された場合、あなたのイベントはおそらく豊かになる可能性があります。ここで何かが足りない場合はお知らせください。

于 2011-02-18T23:36:32.520 に答える