Domain driven design 聚合根引用其他聚合根
我目前正在大量使用DDD,当从其他聚合根加载/操作聚合根时,我面临一个问题 对于模型中的每个聚合根,我还有一个存储库。存储库负责处理根目录的持久性操作 假设我有两个聚合根,其中有一些成员(实体和值对象) AggregateRoot1和AggregateRoot2 AggregateRoot1有一个引用AggregateRoot2的实体成员Domain driven design 聚合根引用其他聚合根,domain-driven-design,repository,aggregate,loading,aggregateroot,Domain Driven Design,Repository,Aggregate,Loading,Aggregateroot,我目前正在大量使用DDD,当从其他聚合根加载/操作聚合根时,我面临一个问题 对于模型中的每个聚合根,我还有一个存储库。存储库负责处理根目录的持久性操作 假设我有两个聚合根,其中有一些成员(实体和值对象) AggregateRoot1和AggregateRoot2 AggregateRoot1有一个引用AggregateRoot2的实体成员 加载AggregateRoot1时,是否也应加载AggregateRoot2 AggregateRoot2的存储库是否应该对此负责 如果是,Aggregate
public void SomeMethod()
{
AggregateRoot1 root1 = AggregateRoot1Repository.GetById("someIdentification");
root1.EntityMember1.AggregateRoot2 = new AggregateRoot2();
AggregateRoot1Repository.Update(root1);
}
public class AggregateRoot1Repository
{
public static void Update(AggregateRoot1 root1)
{
//Implement some mechanism to detect changes to referenced roots
AggregateRoot2Repository.HandleReference(root1.EntityMember1, root1.EntityMember1.AggregateRoot2)
}
}
这只是一个简单的例子,不包括德米特法或其他最佳原则/实践:-)
欢迎进一步评论。也许AggregateRoot1存储库在构建AggregateRoot1实体时可以调用AggregateRoot2存储库
我不认为这会使ddd失效,因为存储库仍然负责获取/创建它们自己的实体。我自己也经历过这种情况,并得出结论,让子聚合以优雅的方式工作太令人头疼了。相反,我会考虑你是否真的需要把第二个聚合作为第一个孩子的引用。如果只保留聚合ID的引用,而不是实际聚合本身,则会使工作更轻松。然后,如果存在涉及这两个聚合的域逻辑,则可以将其提取到域服务,如下所示:
public class DomainService
{
private readonly IAggregate1Repository _aggregate1Repository;
private readonly IAggregate2Repository _aggregate2Repository;
public void DoSomething(Guid aggregateID)
{
Aggregate1 agg1 = _aggregate1Repository.Get(aggregateID);
Aggregate2 agg2 = _aggregate2Repository.Get(agg1.Aggregate2ID);
agg1.DoSomething(agg2);
}
}
编辑:
我真的推荐这些关于这个主题的文章:这种方法有一些问题。首先,您应该为每个聚合及其完成设置一个存储库。一个存储库调用另一个存储库违反了这一规则。其次,关于聚合关系的一个良好实践是,一个根聚合应该通过其id与另一个根聚合进行通信,而不是使用其引用。这样做,可以使每个聚合独立于另一个聚合。在根聚合中只保留对组成相同聚合的类的引用。我也考虑过这一点,但是如果Aggregate2引用了Aggregate3,Aggregate3引用了另一个,那么又会怎样呢。这可能是一个相当大的对象图。这些场景的建议策略是什么?是的,我知道您不必太担心DDD中的实现,但在这一点上,如果我认为图太大,我会懒散地加载聚合。好的,到目前为止还不错。:-)但是,当我在AggregateRoot1.Entity1-->AggregateRoot2之间创建关系时,这应该通过AggregateRootRepository1.AddRoot2ToEntity1(root1,root2)还是通过AggregateRepository2.AddRoot2ToRoot1(root1,root2)或更直接的赋值来实现,我个人认为没有。我会通过以下方式分配它:“entity1.Entity2=Entity2”,然后存储库应该能够检测到这种关系,并做它需要做的事情(即,更新数据库列,如果它是底层存储),谢谢TWith2Sugars,但我真的希望在结束这个问题之前有更多的反馈。我个人很欣赏你的回答,我可以看到目前的方法越来越混乱,我认为DavidMaster84的解决方案更为优雅。Ie将引用作为id保留,并将这种类型的域逻辑提取到域服务中。我可以这样说,因为我最初尝试以同样的方式实现这个问题,我发现自己陷入了一个混乱:)你可能也想在这里阅读关于类似问题的建议:我听到了,但那里的存储库不是用来管理聚合根,并怀着某种善意,管理根之间的关系的吗。和域服务来处理不适合单个实体的行为?在我看来,在阅读域服务的定义时,让域服务负责处理根之间的引用是错误的。。。我可能是错的,所以如果能提供更多的支持,我们将不胜感激,谢谢;它可以调用涉及多个聚合的功能,即“自然不适合单个实体的行为”。在大多数模型中,所有聚合都以某种形式以关系数据库的形式相互关联,聚合的目的是将依赖关系图分解为可管理的组。如果你在模型中保持所有聚合之间的关系,那么它将违背聚合的观点;您的问题是关于在聚合根之间运行操作,我认为这是域服务适合的地方。我想很快你就会问自己兔子洞有多深…+1。这也是沃恩·弗农(Vaughn Vernon)在其“根据身份引用其他集合”规则中所主张的。其优点包括总体聚合大小可以提高性能和简化分区。我想它的缺点是有时会降低模型代码的表达能力,因此它是一个t