エバンスは、彼の本「ドメイン駆動設計」の第6章「集合体」で、集合体の概念を紹介しています。彼はさらに、その概念を実装に変換するためのルールを定義しています(Evans 2009、pp。128-129):
ルートENTITYは内部ENTITIESへの参照を他のオブジェクトに渡すことができますが、それらのオブジェクトは一時的にしか使用できず、参照を保持できない場合があります。
他のルールについて詳しく説明した後、彼はそれらをこの段落に要約します。
エンティティと値オブジェクトを集合体にクラスター化し、それぞれの周りに境界を定義します。各Aggregateのルートになるエンティティを1つ選択し、ルートを介して境界内のオブジェクトへのすべてのアクセスを制御します。外部オブジェクトがルートへの参照のみを保持できるようにします。内部メンバーへの一時的な参照は、単一の操作内でのみ使用するために渡すことができます。ルートはアクセスを制御するため、内部構造の変更によって盲目的に対処することはできません。この配置により、Aggregate内のオブジェクトおよびすべての状態変化におけるAggregate全体に対してすべての不変式を適用することが現実的になります。
では、一時的な使用とは正確にはどういう意味ですか?
私の同僚は、集約ルートのみがクライアントのパブリックインターフェイスを公開していることを理解しています。クライアントは、集約ルート以外のエンティティで操作を呼び出す機会がありません。
引用された文に対する私の理解は異なります。実際、クライアントが内部エンティティの操作を呼び出すことを明示的に許可していることを理解しています。しかし、それらをルートから取得した後にのみ。
具体的な例を見てみましょう:
Cart
多くので構成されているとしましょうItems
。それぞれにItem
がありQuantity
ます。モデルはユースケース「1つの特定のアイテムの数量を増やす」をサポートする必要があります。アイテムの外部に影響を与える不変式に違反することはできません。
クライアントが呼び出しによってこれを実行できる場合、cart.item(itemId).increaseQuantity()
またはクライアントに呼び出しのみを許可する必要がある場合、モデルは上記のルールに違反していcart.increaseItemQuantity(itemId)
ますか?後者の利点は何でしょうか?
cart.increaseItemQuantity(itemId)
、他の理由がない限り、デメテルの法則違反ではない場合は、カートがで数量の増加を制御できるようにするほうが理にかなっています。呼び出すとcart.increaseItemQuantity(itemId)
、カートの合計金額を更新するなどの操作を実行できます。