DDD 集約の境界と一貫性の設計方法¶
集約の定義¶
集約とは「常に一貫していなければならないデータと、それを操作するロジックをまとめた境界」。
集約の 5 つのルール¶
| ルール | 内容 |
|---|---|
| 集約ルートが唯一の入り口 | 外部から内部オブジェクトに直接アクセスしない |
| 強い整合性を保つ範囲が境界 | 「常に一緒に変わる必要があるデータ」をまとめる |
| 他の集約は ID で参照 | 集約を丸ごと内部に持たない(参照の独立性) |
| 状態はメソッドを通してのみ変更 | 集約ルートのメソッド経由でのみ状態を変える |
| 1 トランザクション = 1 集約 | 原則として 1 つのトランザクションで変更する集約は 1 つ |
コード例(Python)¶
class Order: # 集約ルート
def __init__(self, order_id: str):
self._id = order_id
self._items: list[OrderItem] = []
self._status = OrderStatus.PENDING
def add_item(self, product_id: str, qty: int) -> None:
# 外部から _items に直接アクセスさせない
if self._status != OrderStatus.PENDING:
raise DomainError("確定済み注文には追加不可")
self._items.append(OrderItem(product_id, qty))
def confirm(self) -> None:
if not self._items:
raise DomainError("明細なしでは確定不可")
self._status = OrderStatus.CONFIRMED
集約の対象外¶
-
登録・参照・更新・削除が中心の単純な機能(CRUD 中心)は集約を使いすぎない
-
複雑なビジネスロジックや複数の整合性制約がある場合に集約設計が効く
要点¶
-
集約の境界は「何が一緒に変わる必要があるか」で決める
-
他の集約は丸ごと持たず ID で参照することで結合を下げる
-
1 トランザクション = 1 集約の原則で並行性の問題を減らす
-
CRUD 中心の機能に無理やり集約を使う必要はない