【问题标题】:AggregateRoot and ChildrenAggregateRoot 和子级
【发布时间】:2017-01-31 21:03:42
【问题描述】:

AggregateRoots 与孩子的一个方面对我来说不是 100% 清楚。 而且我也没有通过谷歌找到完整的例子。

假设我有一个 AggregateRoot “客户”。 一个客户可以有多个项目。

我已经了解到我只有一个 AggregateRoot“客户”并且项目没有 Root,到目前为止一切都很好。

public class Customer : AggregateRoot
{
    private List<Project> _projects { get;set; }

    public void AddProject(Guid id, string name, int budget)
    {
        ?
    }
}

我有几个小问题。

  1. 项目是聚合(只是没有根)还是只是 POCO 类?
    • 对于应用状态以及在事件存储中保存什么很重要
  2. 我的业务规则是每个客户的项目都有一个唯一的名称。
    • 此业务规则在客户内部还是项目内部?
  3. 我的命令是否具有名称“AddProject”并存在于 Customer 命名空间或“CreateProject”并存在于 Project 命名空间中,然后在后台加载客户聚合并在客户聚合上执行“AddProject”?

亲切的问候

【问题讨论】:

    标签: c# cqrs event-sourcing aggregateroot


    【解决方案1】:

    Project 是一个聚合(只是没有根)还是只是一个 POCO 类?

    它看起来像一个实体,因为您在添加一个 ID 时传递了一个 ID。

    我有一个业务规则,即每个客户的项目都有一个唯一的名称。 这个业务规则在客户内部还是在项目内部?

    聚合的存在是为了在其中强制执行一致性和不变性,因此每个客户的唯一性概念必须存在于Customer 中。当有人尝试将Project 添加到Customer 时,需要强制执行此规则,并且只有Customer 知道它还有哪些其他项目。

    我的命令是否具有名称“AddProject”并存在于 Customer 命名空间或“CreateProject”并存在于 Project 命名空间中

    与上述相同 - 此逻辑需要存在于 Customer 中,以便强制执行项目名称唯一性的业务规则。

    【讨论】:

      【解决方案2】:

      Project 是一个聚合(只是没有根)还是只是一个 POCO 类?

      它既是一个实体又是一个 POCO。 POCO 只是意味着您的类是裸机 C#,并且不受数据访问或基础设施库内容的污染。聚合根也是 POCO。

      Project 不是 AR,因为它已经存在于 Customer AR 之下。

      我有一个业务规则,即每个客户的项目都有一个唯一的名称。 这个业务规则在哪里,在客户内部还是在 项目?

      “每个客户”清楚地表示客户范围的不变量,因此它涉及客户聚合。在这种情况下,聚合不变量由聚合根 - 类 Customer 强制执行。

      我的命令是否具有名称“AddProject”并存在于客户中 命名空间或“CreateProject”并存在于 Project 命名空间中 然后在后台加载客户聚合并执行 客户聚合上的“AddProject”

      首先,不要将命名空间与域模型设计混淆。在确定哪个域对象具有哪个方法时,命名空间并没有真正发挥作用。使用单个命名空间查看整个域层实际上很常见。

      命名空间或多或少模糊地反映了您的代码组织,不是组织本身

      话虽如此,我已经看到了命令的实现

      • 在域层中

      • 在应用层中。

      此外,由于命令是按聚合的,因此为每个聚合添加子命名空间是有意义的。

      具体来说,意思是这样的

      YourApplication.Application.Commands[.Customer].AddProject

      YourApplication.Domain.Commands[.Customer].AddProject

      【讨论】:

      • 感谢您的长篇回答!您的命名空间建议将意味着查询:YourApplication.Domain.Queries[.Project].GetProjectByName 或 YourApplication.Domain.Queries[.Customer].GetProjectByName
      • 不,查询的命名空间不应该与域有任何关系。命令查询职责分离。这是CQRS的精髓。我有一篇博客文章概述了典型的 CQRS 架构。你可以找到它here
      【解决方案3】:

      聚合根不应包含另一个聚合根。所以 Project 应该只是一个具有 Customer 聚合根的实体。至于规则,显然我会将其放在项目级别,因为为了检查此规则,您需要访问单个客户内的其他项目,这不应该是项目实体的责任,因为它不应该“了解”其他实体如何保存或引用它的方式。

      【讨论】:

      • 感谢您的回答。我认为您的第三句话是“在客户级别”,对吗?我在我的帖子中添加了第三个问题,也许你也可以对那个问题发表意见?
      • 是的,对不起,我的意思是客户级别。至于命令,它取决于这些命令应该存在于哪个级别的语义,但绝对不是项目级别,因为这两个命令都假设修改了引用项目的某些状态,但同时项目不应该知道状态结构甚至它的存在。
      猜你喜欢
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-16
      • 1970-01-01
      相关资源
      最近更新 更多