DDD に関するすべての資料は、これを厳密なノーノーとして指定していますが、私は最近、別の考え方を説得力のあるケースにするシナリオに出くわしました。2 つの集約ルート Template と Document を想像してください。Template --> (1:n) TemplateParam, Document --> (1:n) ParamValue
最終的に 2 つのルートには参照がありますDocument --> (n:1) Template
。
集約ルートの制約を指定ParamValue
すると、 への参照を永続化することはできません。集約ルートTemplateParam
を介して取得した一時的な参照を介してのみ参照できますTemplate
。「ドキュメントの各 ParamValue は、所有するドキュメントによって参照されるテンプレートに属する有効な TemplateParam を参照する必要があります」のようなルールを強制したい場合。理想的には、db レベルで、ParamValue に TemplateValue への FK を持たせます。DDD パラダイムでそれを行う方法は??
2 に答える
これを行う 1 つの方法は、インスタンスTemplate
を作成するためのファクトリ メソッドをエンティティに持たせることです。これにより、すべてのインスタンスが適切な に関連付けられているDocument
という制約を適用できます。ドキュメントが不変の場合は、完了です。それ以外の場合は、関連するテンプレートを使用してドキュメントに更新を適用できます。このテンプレートは、ドキュメントから直接参照することも、ID を使用して参照することもできます。この場合、操作に必要なときにカプセル化アプリケーション サービスがテンプレートを取得します。AR 間の直接参照は、DDD の厳密な違反ではありません。実際、青本は、外部 AR によって参照できる唯一のものであると指定しています。一貫性、パフォーマンス、ORM マッピングなどの他の考慮事項のために、最近では制約になっています。ParamValue
TemplateParam
いくつかのインスピレーションを得るための効果的な骨材設計に関するこの一連の記事。
集約ルートには理由があります。それらは、不変条件を強制するために、関連するエンティティのグループへの単一のエントリ ポイントとして機能します。外部オブジェクトがこれらのエンティティを台無しにして、不変条件に違反する可能性がないことを確認します。
ただし、特定のシナリオでは、ParamValue が TemplateParam への直接参照を保持している場合でも、TemplateParam は Document 集約内のエンティティによって変更されるリスクはありません。特定のドキュメントのパラメーターに関連付けられた値は変更されますが、パラメーター自体は変更されません。
これが事実であることを確認するには、TemplateParam を不変の値オブジェクトにすることができます。
(C#)
public class TemplateParam
{
private readonly string name;
public TemplateParam(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
したがって、TemplateParam の「外部化」によって Template 集約の不変条件の 1 つが壊れるリスクなしに、TemplateParam を ParamValue にカプセル化できます。
技術的に言えば、これは DDD の集約ルートの制約に違反している可能性がありますが、「外部化された」エンティティを不変に保ち、それが元々属していたオブジェクト グラフを変更しない限り、精神的にはそうではないと思います。