集約をトランザクション境界とする
ルール
1つのコマンド(ユースケース)で変更できる集約は1つだけ。複数の集約を同一トランザクションで変更してはならない。
複数の集約にまたがる変更が必要な場合は、**ドメインイベントと結果整合性(Eventual Consistency)**で実現する。
❌ 複数集約を同一トランザクションで変更
beginTransaction()
order.confirm()
inventory.reduce(order.items) // 別の集約
commitTransaction()
✅ イベント経由で結果整合性
beginTransaction()
order.confirm() // OrderConfirmedイベントを記録
commitTransaction()
// 非同期でInventoryServiceがイベントを受け取り在庫を減らす(別トランザクション)
理由
同一トランザクションで複数の集約を変更すると:
- ロック競合が起きやすく、スループットが下がる
- 集約の境界が有名無実化し、設計上の意図が失われる
- スケールアウトが困難になる(1つのDBトランザクションが複数のサービス・テーブルを跨ぐ)
集約をトランザクション境界とすることで、各集約が独立してスケールできる。
例外
- 同一集約内のエンティティ間の変更(それは1集約1トランザクション内)
- 業務上絶対に強整合性が必要で、パフォーマンス上の問題も許容できる場合(ただし設計を再検討する余地を検討する)
関連概念
- → 集約
- → 副作用はドメインイベントで表現する
- → 集約は小さく保つ
出典
実践ドメイン駆動設計(Vaughn Vernon)第10章