トランザクションをUseCase層に張るかRepository層に張るか¶
要約¶
トランザクションは UseCase 層(アプリケーションサービス層)に張るのが DDD の原則に沿っている。Repository でトランザクションを張ると、複数集約を更新する場面で「どちらの Repository がオーナーか」が決められず設計が崩れる。トランザクション境界は集約単位が理想で、複数集約をまたぐ整合性が必要に見えるときはまず結果整合性を検討する。
ポイント¶
- Repository はオブジェクトコレクションのエミュレーションであり、DB アクセスの代名詞ではない
- Repository でのトランザクションは「Repository の抽象度とトランザクションの抽象度が一致していない」問題を引き起こす
- DDD 原則: 1トランザクション = 1集約。複数集約をまたぐ必要があるように見えたら集約境界設計を見直す
- 結果整合性(ドメインイベント + 非同期更新)で代替できるケースが多い
- どうしても複数集約の同期更新が必要なら UseCase 層でスコープを開始し各 Repository に明示的に渡す
- context などで暗黙伝搬させる方式は便利だが保守性が下がる
関連¶
- Martin Fowler の Unit of Work パターン(PoEAA)
- Vaughn Vernon の集約設計指針「1トランザクションで更新するのは1集約のみ」