DDD:聚合根问题

16

假设我有两个实体 - Foo 和 Bar。Foo 是一个聚合根,包含 Bar。据我所知,它应该看起来像这样:

public class Foo{
    private readonly Bar Bar;
}

我希望为用户提供从定义的列表中选择Bar对应于Foo的功能(并进行更改)。

如果存储库仅用于聚合根,这意味着没有Bar实体的存储库。

这导致问题-无法在没有对Foo的引用的情况下单独创建/更新Bar。

这是否意味着尽管没有Foo,但是Bar应该有一个存储库?


1
没有所谓的愚蠢问题,只有愚蠢的回答 ;) 顺便说一句,这个问题帮了我很多。 - Eldar
3个回答

18
如果你想从一个与Foo没有关联的Bars列表中进行选择,那么这不是一个聚合根。例如,你无法获取OrderItems列表而不包含其Order,因此这是单个聚合根(Order),但是你可以获取产品列表来分配给OrderItems,所以Product不是Order聚合根的一部分。
请注意,虽然OrderItem是Order聚合根的一部分,但你仍然可以独立创建和更新它。但是,如果没有对Order的引用,你无法获取它。同样适用于你的Bar,即使它是Foo的一部分,你也可以获取每个(Foo.Bars)并使用它,或者执行Foo.AddBar(new Bar())。但如果需要在没有Foo的情况下获取列表,则Bar不是Foo的聚合根的一部分。它是一个独立的实体。
这就是我在这里看到DDD的方式,但我当然不是Eric Evans。

这很有道理。如果你还有什么要说的,请继续。 :) - Arnis Lapsa
我学到的东西-我的领域中有太多的聚合根。有些实体被作为根而不应该独立更新。更糟糕的是,有些根可以被替换为值对象。 - Arnis Lapsa
1
我想到的另一个建议是,如果你的“Bar”既是独立的(可以作为单独的列表呈现),又同时依赖于“Foo” - 也许你实际上有两个实体。一个简短的例子:组{名称、价格} - 应该同时在订单/产品中,也可以单独呈现,但如果你将其拆分成组{name}和产品组{组、价格},你可以单独展示组,同时保持产品组作为聚合的一部分。 - queen3
@queen3;我理解你的观点,但能否请你为我澄清一些事情。举个不同的例子...客户是一个聚合根,它有一个国家。为了设置国家,您需要从国家列表中进行选择...这样就使国家成为一个聚合根,对吗? - Craig
我认为这使得Country成为一个独立的实体。如果它包含其他实体(例如Region),那么它将是一个聚合根。如果我正确理解“聚合根”和“实体”是不同的概念,但它绝对不是客户聚合根的一部分。在某些情况下,它可以是客户的一部分...例如,在虚拟世界游戏中,用户创建自己的国家,国家可能是“玩家世界”的一部分。但我想这不是你的情况。 - queen3
显示剩余2条评论

8
拥有聚合根的原因如下:
  1. 它们提供对复合实体的控制和定向访问。
  2. 它们可以强制执行规则以确保整个聚合是有效的。
我的看法: 如果您需要选择没有FooBar对象,请使用BarRepository但是... 如果您更新了一个Bar,并且它破坏了其父级Foo的验证规则,如果这种情况可能发生,您应该通过其父级Foo访问Bar

然而,如果您需要访问一堆Bar对象(例如批处理作业或报告),而且您知道Foos不会被破坏,请继续通过BarRepository进行访问。

请记住,聚合根可以由其他聚合根组成。您可能会发现Bar本身就是一个聚合根,从而为您提供使用BarRepository的理由 :)


2

你确定需要将Bar作为一个实体吗?在领域中,你是否需要跟踪和更改它?如果你可以将其视为值对象,我建议你从服务中获取它,然后将选择的值对象与Foo实体“连接”起来。例如,通过下拉列表。


为什么实体不能通过服务获取并连接到Foo? - Arnis Lapsa
如何在没有实体上下文的情况下创建/更新值对象?这样做不会将服务伪装成存储库吗?因为值对象不应该具有这个功能。 - Arnis Lapsa
让我解释一下我是如何做到这一点的;我需要一种从持久层获取数据的方法。我可以使用DTO来获取数据,但我更愿意使用值对象,因为这样我就可以在域中使用对象,而无需从DTO映射到值对象。我正在使用的对象是聚合根中的一个类,对于你的情况是Bar。如果我要为实体执行此操作,我想我会使用DTO(通过服务获取)来填充列表(组合框等),当我选择正确的Bar后,我将请求存储库从聚合根中获取完整的对象。希望这有意义。 - Fossmo
我在想这个解决方案是否适用于我的验证问题,并根据来自聚合之外的数据选择默认值。https://dev59.com/6FXTa4cB1Zd3GeqP3aLa - jpierson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接