16

假设我有 2 个实体 - Foo 和 Bar。Foo 是聚合根并包含 Bar。据我了解,它应该是这样的:

public class Foo{
    private readonly Bar Bar;
}

我想为用户提供从定义的列表中选择 Bars for Foos 的功能(并更改它)。

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

这会导致问题 - 如果没有对 Foo 的引用,就无法独立创建/更新 Bar。

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

4

3 回答 3

18

如果您想从与 Foo 不关联的 Bars 列表中进行选择,则这不是聚合根。例如,如果没有 Order,您无法获取 OrderItems 列表,因此这是单个聚合根 (Order),但您可以获取要分配给 OrderItems 的产品列表,因此 Product 不是 Order 聚合根的一部分。

请注意,虽然 OrderItem 是 Order 聚合根的一部分,但您仍然可以独立创建和更新它。但是,如果不参考 Order,您将无法获得它。您的 Bar 也是如此,即使它是 Foo 的一部分,您也可以获取 each(Foo.Bars) 并使用它,或者执行 Foo.AddBar(new Bar())。但是,如果您需要在没有 Foo 的情况下获取 List,则 Bar 不是 Foo 聚合的一部分。它是一个单独的实体。

好吧,这就是我对 DDD 的看法,但我当然不是 Eric Evans。

于 2009-09-25T17:39:28.603 回答
8

具有聚合根的原因是:

  1. 它们提供对复合实体的受控和定向访问
  2. 他们可以强制执行规则以确保整个聚合是有效的

我的看法: 如果您需要选择Bar没有 a 的对象Foo,请使用 a BarRepository

但是... 如果您更新 a Bar,并且它破坏了它的 parent 的验证规则Foo怎么办?如果发生这种情况,您应该Bar通过它的 parent访问Foo

但是,如果您需要访问一堆Bar对象(例如,对于批处理作业或报告),并且您知道它们Foos不会被破坏,请继续并通过BarRepository.

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

于 2009-09-26T19:44:20.207 回答
2

您确定 Bar 需要是一个实体吗?您是否需要在域中对其进行跟踪和更改?如果您可以将其视为值对象,我建议您从服务中获取它,然后将选定的值对象“连接”到 Foo 实体。对于瞬间通过下拉列表。

于 2009-09-25T17:25:42.880 回答