ddd-domain-event について
ddd-domain-eventは、ドメイン駆動設計におけるドメインイベントのモデリングを説明するスキルです。イベントを使う場面や命名・構成を判断し、コマンドや同期メソッド呼び出しとの混同を避ける方法を示します。
主な機能
- 01不変で過去形のイベント定義
- 02購読者に必要なイベントデータの選定
- 03集約境界を越えた連携
- 04状態変更の成功後にイベントを公開
- 05イベントとコマンドの区別
活用シーン
- 01別の境界づけられたコンテキストへの業務イベント通知
- 02プロジェクション、監査ログ、検索インデックスの構築
- 03独立したトランザクション間の処理連携
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-domain-eventインストール後、Claude Code で/ddd-domain-eventを入力して読み込まれたか確認します。
詳細
1 行でまとめると
ドメインイベントとは、ビジネス上重要な出来事が起きたことを記録する不変のレコードです。過去形で、ユビキタス言語で名付けられ、後続のリスナーが反応するために必要なデータを持ちます。
このスキルを使う場面
- 集約の境界を越える場合 — 2 つの集約が連携する必要があるものの、別々のトランザクションに属している。
- ある境界づけられたコンテキストで注目すべき出来事が起きたことを、ほかの境界づけられたコンテキストに伝える場合。
- リードモデル、プロジェクション、または後続の連携(監査ログ、分析、検索インデックス)を構築する場合。
- ビジネス自体が語るライフサイクルの遷移を通知する場合:注文が行われる、支払いが決済される、返金が発行される、出荷品が倉庫を出る。
このスキルを使わない場面
- 状態変更が 1 つの集約内で完結し、リスナーもいない場合 — メソッドを直接呼び出してください。
- 「イベント」が実際には何かをするよう求める命令(命令的なリクエスト)の場合。コマンドとイベントは異なります。
PlaceOrderはコマンドで、OrderPlacedはイベントです。 - 1 つのトランザクション内で同期的にやり取りする必要がある場合 — それはイベントではなく、メソッド呼び出しです。
核となる内容
ドメインイベントには過去形の名前を付けます:OrderPlaced、PaymentSettled、RefundIssued、ShipmentDispatched。名前自体がユビキタス言語の一部です。ドメインエキスパートが「支払いを決済する」と言うなら、イベントは PaymentSettled です。
イベントは不変であり、自己記述的です。公開されたイベントが変わることはありません。サブスクライバーはイベントを保存、再生、または転送できます。イベントには ID と、サブスクライバーが反応するために必要な最小限のデータを含めます。通常は集約識別子、タイムスタンプ、いくつかの重要なフィールドです。
イベントは、発行元の集約の状態変更が成功した後に公開します。通常、その状態変更とトランザクション上で一緒に公開します(アウトボックスパターン、トランザクショナルイベントバス)。これにより、状態変更が実際にコミットされた場合に限り、サブスクライバーがイベントを受け取ります。
サブスクライバーはほかの集約またはほかのコンテキストに属します。サブスクライバーは非同期に反応します。集約内の状態変更にはイベントは不要です。イベントはまさに境界を越えるために存在します。
ドメインイベントは、CQRS やイベントソーシングとは独立して役立ちます。通常のリレーショナルストア、アウトボックステーブル、パブリッシャーを使って利用できます。イベントソーシングを行う必要はありません。
判断のヒューリスティクス
- ドメインエキスパートが「何が起きたか」を名詞(決済、承認、配達など)で表す場合、それはモデル化する価値のあるイベントである可能性が高いです。
- イベントを利用するのが、イベントを発行した同じ集約だけの場合は、イベントを削除してメソッドを直接呼び出してください。
- 過去形は必須です。
UpdateOrderEventと書いているなら、イベントではなくコマンドをモデル化しています。
アンチパターン
- 命令形のイベント名(
UpdateOrder、ProcessRefund) — これらはコマンドです。 - エンティティグラフ全体を含む肥大化したイベント — サブスクライバーがイベント経由で参照をたどる必要がないようにしてください。
- 1 つのトランザクション内の同期的な制御フローにイベントを使う — イベントは明確に境界を越えるためのものです。
- 状態変更がコミットされる前にイベントを公開する — トランザクションがロールバックされたとき、サブスクライバーに実在しないイベントが届きます。
関連項目
ddd-aggregate— イベントは集約の境界を越えて連携するための標準的な方法です。ddd-context-mapping— ドメインイベントは、コンテキスト間で公開される言語として機能することがよくあります。ddd-deeper-insight— 暗黙の「何が起きたか」という概念をイベントとして明示するのは、Part III における典型的な手法です。
参考文献
- Evans, Domain-Driven Design(2003)、第 5 章ではドメインサービスの文脈でイベントに簡単に触れています。標準的な解説は後年、Vernon の Implementing Domain-Driven Design(2013)で示されました。