📐
集約の設計原則(Vernon の4ルール)
「小さく保て」「IDで参照せよ」など、誤った集約設計を防ぐVernon が提唱する4つの実践ルール
背景
集約の概念を理解しても、「何を集約に含めるか」という判断で多くの設計が失敗する。Vernon は IDDD 第10章で4つの経験則を明示した。これは集約の誤った設計パターン(巨大集約)を防ぐための実践ガイド。
ルール1: 真に必要な不変条件だけを集約に含める
集約の境界はビジネスの不変条件(invariant)が要求する範囲によって決まる。「同時に変更されなければならないもの」だけを同じ集約に入れる。
❌ 「関連があるから」同じ集約に入れる
✅ 「同一トランザクションで一貫していなければならない」から同じ集約に入れる
例: Order と Customer は関連するが、別々に変更されてよい → 別集約。
ルール2: 集約を小さく設計する
大きな集約はロックの競合・パフォーマンス劣化・テストの複雑化を招く。
❌ Forum(大集約)
├── Post × 1000
│ └── Comment × 1000
└── Moderator × 10
✅ Forum(集約ルート、IDのみ保持)
Post(別集約、forum_id を持つ)
Comment(さらに別集約、post_id を持つ)
大抵の場合、集約は2〜5個のオブジェクトで十分。
ルール3: 別の集約を参照するにはIDのみを使う
集約間の参照はオブジェクト参照ではなくIDに限定する。
# ❌
class Order:
customer: Customer # 直接参照
# ✅
class Order:
customer_id: CustomerId # IDのみ
IDのみの参照により:
- 集約の境界が明確になる
- ロード時に不要な集約をメモリに展開しない
- 集約間の変更が独立する
ルール4: 結果整合性を使って集約の整合性を保つ
「2つの集約を同時に整合させる必要がある」と感じたとき、その多くは結果整合性で解決できる。
同期(1トランザクション): Order.place() が在庫を直接減らす ← ❌
非同期(結果整合性): Order.place() → OrderPlaced イベント
→ 在庫コンテキストが非同期で在庫を減らす ← ✅
「即時一貫性が本当に業務要件か」をドメインエキスパートに確認する。大抵は数秒の遅延が許容される。
判断フローチャート
1. これは同じトランザクションで変更しなければならないか?
YES → 同じ集約に含める
NO → 別集約へ(IDで参照、イベントで連携)
2. 集約が巨大になっていないか?
YES → 不変条件を再確認し、分割できるものを分割
3. 別集約への参照がオブジェクト参照になっていないか?
YES → IDのみの参照に変更
関連概念
- 1. 🗺️サブドメイン(コア・サポート・汎用)
- 2. 🗾コンテキストマップ
- 3. ⬡六角形アーキテクチャ(ポートとアダプター)
- 4. 🪪エンティティ(Entity)
- 5. ⚙️ドメインサービス(Domain Service)
- 6. 📣ドメインイベント(Domain Event)
- 7. 🫧集約(Aggregate)
- 8. 📐集約の設計原則(Vernon の4ルール)
- 9. 🗄️リポジトリ(Repository)
- 10. 🏭ファクトリ(Factory)
- 11. 📦モジュール(Module)
- 12. 🎛️アプリケーションサービス(Application Service)
- 13. 🔌境界づけられたコンテキストの統合
- 14. ⚡CQRS(コマンドクエリ責任分離)
- 15. 📜イベントソーシング(Event Sourcing)
出典: 実践ドメイン駆動設計(Vaughn Vernon)第10章