あなたの質問にはいくつかのコンテキストが欠けています。たとえば、このイベントにつながるユーザーシナリオは何ですか、また、開始している状態は何ですか?この場合の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つには欠点がありますが、複数の集約ルートを介して動作する必要があるコマンドを作成します。可能な限り、最初の例がうまくいかない理由を理解しようと思います。
また、私はあなたが探している実装があなたの特定のドメインコンテキストによってどのように決定されるかを十分に強調することはできません。