ドメインイベントとは
「ドメインイベント」は、ドメインで起こった出来事をモデリングする仕組みです。ドメインイベントを使うことで、複雑になりがちな出来事を管理し、システム間の連携を柔軟にすることができます。
DDD本の発売後に発展してきた概念のため正式な定義は書かれていませんが、エヴァンス氏は
ドメインイベントは、ドメインモデルの一部であり、ドメイン内で発生する何かの出来事を表す。
と述べており、出来事をモデリングする有用な手法と認識していることがわかります。
ドメインイベントのモデリング方法
「エンティティ」や「値オブジェクト」ではオブジェクトの属性や振る舞いに対してモデリングを行ってきました。これに対して、ドメインイベントは「ドメインエキスパートが注目する出来事」にフォーカスします。具体的にはドメインエキスパートが話す「〜する時に」や「〜した場合」といったフレーズに注目します。
また、イベントは「システム的な観点」から導入するケースもあります。例えば、特定のシステムで発生した出来事を外部システムに通知する場合や、境界づけられた同じコンテキスト内のトランザクションを分離する場合などです。
ドメインイベントがもたらすメリット
ドメインイベントには、結果整合性(結果として一貫性が保たれること)を用いたシステムの構築が容易となるメリットがあります。ドメインイベントを利用することで、密結合になりがちな他システムとの連携や、他の集約へのデータ反映を疎結合にできます。
バッチ処理に関する考え方の変化
イベントの概念を導入すると「バッチプログラム」の設計も変わってきます。多くのシステムでは集計処理を行う夜間ジョブが動作しています。通常、前日の変更データを複雑なクエリーで取り出し、長いトランザクションを使って変換する処理を行っています。しかし、ドメインイベントを導入することで、発生したイベントは随時通知され、反映が必要なシステムを取り込むだけでよくなります。その結果、従来のバッチプログラムが不要になる場合があります。
集約の制約からの開放
また、DDDの集約(10章)には「単一のトランザクションでは単一の集約の固まりだけを変更しなければいけない」という推奨ルールが存在しています。しかしモデリングをしていると、別の集約も更新したい出来事が発生することがあります。こうした場合にイベントを活用することで、トランザクションの範囲を広げることなく結果整合性を保てます。
同様にリモートシステムにおいても、分散トランザクションを意識せずにすみます。その結果、スケーラブルでパフォーマンスに優れたサービスを構築しやすくなります。
ドメインイベントの導入
イベントを導入していくには、ドメインエキスパートの「その結果どうなるのか」「いつ無視するべきか」といった業務的な観点からイベントの要否を判断します。次に「他システム連携は必要か」「イベントソーシングは必要か」などの技術的な観点からイベントの連携方式を検討します。
イベントを用いた処理の例
SaaSOvasionのアジャイルプロジェクト管理コンテキストの場合「バックログアイテムがコミットされたら、コミット先のスプリントやその他の関係者たちに通知する」といった要件があります。この例をイベントを用いて制御する場合、次の流れとなります。
- 集約のコマンド「スプリントにバックログアイテムをコミットする」が呼び出される。
- 集約のコマンドで、コミットされた旨の「ドメインイベント」が生成される。
- 「ドメインイベントパブリッシャー」がイベントを発行(出版)する。
- 「サブスクライバ」がイベントを受信(購読)する。
- 「サブスクライバ」でメールを送信する。
IDDDではイベントの発行を「パブリッシャー」で行い、イベントの受信を「サブスクライバ」で行います。
サブスクライバが処理する内容としては、大きく次の3つの傾向があります。
(1)同期処理
イベントに応じた処理を、イベント発行と同じトランザクションで実施します。サブスクライバで処理が完結します。
(2)イベント格納処理
同一トランザクションではイベントの記録だけ行います。後述する「イベントストア」等を活用して、イベントに応じた処理は別途実行されます。
(3)分散処理
イベントを他システムにリアルタイムで転送し、2フェーズコミットなどの「分散トランザクション」で制御を行います。この分散トランザクションの導入は製品固有の知識が必要なため、難易度が高くなる傾向にあります。
簡単な処理の場合はサブスクライバのみで処理が完結しますが、外部システム連携が必要なイベントの場合はイベントストアや分散トランザクションの利用を検討する必要があります。