Cqrsアーキテクチャで新しい集約ルートを作成するにはどうすればよいですか?この例では、最初の1つのAR1への参照を保持する新しい集約ルートAR2を作成します。
開始点としてAR1メソッドを使用してAR2を作成しています。これまでのところ、いくつかのオプションが表示されます。
createAr2RootOpt1
_ new AR2()
を呼び出して、リポジトリにアクセスできるドメインサービスを使用して、このオブジェクトをimediatellyにdbに保存できます。たとえば、最初の集約ルートでイベントを発行できます。 _SholdCreateAR2Event
_そして、これに反応してコマンド_CreateAR2Command
_を発行するステートレスサガがあり、これが処理されて実際にAR2を作成し、_AR2CreatedEvent
_を発行します。イベントソースを使用する場合、_SholdCreateAR2Event
_は最初の集約ルートの状態に影響しないため、イベントストアに保持されません。 (または、これをイベントストアに保存する必要がありますか?)
_class AR1{
Integer id;
DomainService ds;
//OPTION 1
void createAr2RootOpt1(){
AR2 ar2 = new AR2();
ds.saveToRepo(ar2);
}
//OPTION 2
void createAr2RootOpt2(){
publishEvent(new SholdCreateAR2Event()); //we don't need this event. Shoud it still be preserved in event store?
}
}
class AR2{
Integer id;
Integer ar1Id;
void handle(CreateAR2Command command){
//init this AR with values and save
publishEvent(AR2CreatedEvent()); //used for projections afterwards and saved inside AR2 event store
}
}
class Saga{
void handle(SholdCreateAR2Event ev){
emitCommand(new CreateAR2Command());
}
}
_
これを行うためのより適切な方法はどれですか?
Cqrsアーキテクチャで新しい集約ルートを作成するにはどうすればよいですか?
作成パターンはweirdです。
Udi Dahanには、一般的な問題についていくつかの便利な点があります: Do n't Create Aggregate Roots 。基本的なポイントは、その集合体がどこからともなく出てくるわけではなく、それらがどのように表示されるかを説明するドメイン言語があり、ドメインモデルに取り込む必要があるということです。
ツイストする傾向があるのは、コマンドを処理しているドメインモデル内のエンティティがないエンティティがトランザクションによって変更されることです。それは間違いではありません。 (エンティティに自分自身を変更するように依頼する場合と比較して)奇妙です。
2番目のアプローチも問題ありません。 「実際にデータベースに保存せずに発生させるイベント」は、「ドメインイベント」と呼ばれることもあります
基本的な考え方は、同じトランザクション内で、コマンドハンドラーがイベントを発生させ、それがバスに沿ってイベントハンドラーに移動し、2番目の集約がそれ自体を作成できるようにすることです。おそらく、コードのまとまりが多少良くなります。
注:イベントソースシステムでは、通常、この方法でイベントを使用しません。
イベントソースを使用する場合、ShouldCreateAR2Eventは最初の集約ルートの状態に影響しないため、イベントストアに保存されません。
注:通常、イベント名は過去形です-ShouldCrateAR2のスペルが間違っています。
はい、イベントを同期バスにスローしてリモートコードを実行しているだけの場合は、そのイベントを記録簿に保存しないでください。このスケールでの実装の詳細にすぎません。
それとも、これをイベントストアに保存する必要がありますか?
同じトランザクションで2つの異なるイベントストリームを変更しないでください。この作成がAR1への変更も表す場合、通常の答えは、このトランザクションでAR1を変更することです。asynchronousのサブスクライバーは、 AR2を作成するコマンドを起動する責任があります。
べき等のコマンド処理は、ここで非常に役立ちます。
私はそのオプションはないと思います。 2は解決策ですが、小さな重要な変更が加えられています。AR1
は、AR2
を作成することを目的としたイベントを発行するのではなく、AR1WasCreated
イベントを発行する必要があります。このイベントは、AR1
の誕生を示す重要なイベントであるため、イベントストアに永続化する必要があります。次に、Saga
がAR1WasCreated
イベントをリストし、AR2
を作成するコマンドを生成します:CreateAR2Command
。
オプションno.1は非常に間違っています。この種のドメインサービスをAggregate
に挿入しないでください。 Aggregates
は純粋である必要があり、イベントの生成以外の副作用はありません。
追伸オブジェクトのインスタンスの作成(プログラミング言語の意味で)とAggregate
の作成(必要に応じて誕生)には違いがあるため、私はAggregate
のコンストラクターからイベントを発行しません。 handle
メソッドからのみイベントを発行します(command
を処理する場合)。