CQRSベースのシステムでのコマンドハンドラー、アグリゲート、リポジトリ、およびイベントストア間の関係の詳細を理解したいと思います。
私がこれまでに理解したこと:
- コマンドハンドラはバスからコマンドを受け取ります。彼らは、リポジトリから適切なアグリゲートをロードし、アグリゲートのドメインロジックを呼び出す責任があります。終了すると、バスからコマンドを削除します。
- アグリゲートは、動作と内部状態を提供します。州は決して公開されません。状態を変更する唯一の方法は、動作を使用することです。この動作をモデル化するメソッドは、コマンドのプロパティからイベントを作成し、これらのイベントをアグリゲートに適用します。アグリゲートは、それに応じて内部状態を設定するイベントハンドラーを呼び出します。
- リポジトリでは、特定のIDにアグリゲートをロードし、新しいアグリゲートを追加するだけです。基本的に、リポジトリはドメインをイベントストアに接続します。
- イベントストアは、最後になりましたが、データベース(または使用されているストレージ)にイベントを保存し、これらのイベントをいわゆるイベントストリームとしてリロードする役割を果たします。
ここまでは順調ですね。今、私がまだ得ていないいくつかの問題があります:
- コマンドハンドラーがまだ存在するアグリゲートで動作を呼び出す場合、すべてが非常に簡単です。コマンドハンドラーはリポジトリへの参照を取得し、そのloadByIdメソッドを呼び出して、集計が返されます。しかし、まだ集計がない場合、コマンドハンドラーは何をしますが、集計を作成する必要がありますか?私の理解では、アグリゲートは後でイベントを使用して再構築する必要があります。これは、集約の作成がfooCreatedイベントに応答して行われることを意味します。ただし、任意のイベント(fooCreatedイベントを含む)を保存できるようにするには、集計が必要です。したがって、これは鶏が先か卵が先かという問題のように見えます。イベントなしでアグリゲートを作成することはできませんが、イベントを作成する必要がある唯一のコンポーネントはアグリゲートです。つまり、基本的には次のようになります。新しい集計を作成するにはどうすればよいですか。誰が何をしますか。
- アグリゲートがイベントをトリガーすると、内部イベントハンドラーがそれに応答し(通常はapplyメソッドを介して呼び出されます)、アグリゲートの状態を変更します。このイベントはどのようにリポジトリに渡されますか?「新しいイベントをリポジトリ/イベントストアに送信してください」アクションを開始したのは誰ですか?骨材自体?集約を監視することによるリポジトリ?内部イベントに登録している他の誰か?...?
- 最後になりましたが、イベントストリームの概念を正しく理解するのに問題があります。私の想像では、これは単にイベントの順序付きリストのようなものです。重要なのは、それが「順序付けられている」ということです。これは正しいですか?