---
name: domain-event
description: >-
  ドメインイベントの特定・設計と対話的なイベントストーミングのファシリテーションを行う。
  次のような依頼があったときに使う:「ドメインイベントを抽出する」
  「イベントストーミングをする」「ドメインイベントを設計する」「イベントを洗い出す」
  「domain eventを定義する」「イベント駆動にする」「イベント設計をレビューする」
  「イベントの粒度を見直す」。
  または、ドメインイベント、イベントストーミング、event storming、イベント駆動に言及する場合にも使う。
version: 0.1.1
argument-hint: "[ドメインやビジネスプロセスの説明]"
allowed-tools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash"]
---

# ドメインイベント抽出

DDD におけるドメインイベントの特定・設計と、対話的なイベントストーミングのファシリテーションを行う。

## ドメインイベントとは

ドメインで発生した重要な出来事を表す不変のオブジェクトである。過去形で命名し、ビジネス上の意味を持つ事象のみをイベントとする。

**命名規則:**
- 過去形を使う: `OrderPlaced`, `PaymentReceived`, `ShipmentDelivered`
- ドメイン用語を使う: 技術用語（`DataSaved`, `RecordUpdated`）は使わない
- 具体的にする: `OrderChanged` ではなく `OrderItemAdded`, `OrderCancelled`

## 対話的イベントストーミング

ユーザーと対話しながらイベントを洗い出す。以下のステップで進行する。

### Step 1: ビジネスプロセスの全体像把握

まず以下の質問でプロセスの始点と終点を特定する:

1. **このビジネスプロセスはどこから始まるか？**（トリガーイベント）
2. **最終的にどうなったら成功か？**（ゴールイベント）
3. **途中で失敗・中断するケースはあるか？**

### Step 2: イベントの洗い出し

時系列でイベントを列挙する。以下の質問を繰り返す:

- **「[前のイベント]の後、次に何が起きるか？」**
- **「その間に何か判断や承認が必要か？」**
- **「例外的なケースではどうなるか？」**
- **「外部システムとのやり取りはあるか？」**

### Step 3: イベントの分類と整理

洗い出したイベントを以下の観点で整理する:

| 分類 | 説明 | 例 |
|------|------|-----|
| **コマンド** | イベントを発生させるアクション | PlaceOrder, CancelOrder |
| **ドメインイベント** | 発生した事実 | OrderPlaced, OrderCancelled |
| **ポリシー/リアクション** | イベントに反応する処理 | 在庫引当、通知送信 |
| **外部システム** | 連携先 | 決済ゲートウェイ、配送API |
| **集約** | イベントを発行するエンティティ | Order, Payment |

### Step 4: イベントフロー図の作成

整理結果を可視化する:

```
[コマンド] → [集約] → [ドメインイベント] → [ポリシー] → [次のコマンド]
```

## ドメインイベントの設計ガイドライン

### イベントに含めるべき情報

```
イベント名（過去形）
├── イベントID（一意識別子）
├── 発生日時
├── 集約ID（発行元の識別子）
├── イベントデータ（状態変更の内容）
└── メタデータ（相関ID、因果関係ID等）
```

**設計原則:**
- イベントは不変（immutable）にする
- イベントだけで意味が通じるよう十分な情報を含める
- 集約の内部状態を丸ごとコピーしない。変更に関連するデータのみ含める
- イベントのスキーマはバージョン管理する

### イベントの粒度判断

```
イベントの粒度は適切か？
├─ 1つのビジネス事実を表す       → 適切
├─ 複数の事実を含む             → 分割する
├─ 技術的な変更を表す           → ドメインイベントではない
└─ 受信側が不要な情報が多い     → 分割または情報を削る
```

## イベントと集約の関係

- 1つの集約操作で1つ以上のイベントを発行できる
- イベントは集約の状態変更を記録する
- 集約間の整合性はイベントによる結果整合性で保つ
- 同一トランザクション内でイベントを永続化する（Transactional Outbox パターン）

## イベント駆動パターン

| パターン | 用途 | 複雑度 |
|---------|------|--------|
| **ドメインイベント** | 同一コンテキスト内の副作用 | 低 |
| **統合イベント** | コンテキスト間の連携 | 中 |
| **Event Sourcing** | イベントを唯一の真実の源とする | 高 |

**注意:** Event Sourcing は必要になるまで導入しない。ドメインイベントから始めて段階的に進化させる。

## アンチパターン

- **CRUDイベント**: `OrderUpdated` のような汎用イベント → 具体的なビジネスイベントにする
- **巨大イベント**: 集約の全状態を含むイベント → 変更に関連するデータのみにする
- **技術イベント**: `DatabaseRecordInserted` → ドメイン用語で命名する
- **イベントの双方向依存**: 発行側が受信側を知る → 発行側は受信側を知らない設計にする

## 擬似コード例

`examples/` ディレクトリに具体例がある:
- **`examples/event-storming-result.md`** — EC サイトのイベントストーミング結果例
