什么属于聚合根

jle*_*bke 32 entities domain-driven-design aggregate root

这是一个实用的领域驱动设计问题:

从概念上讲,我认为在获得定义之前我会得到Aggregate.

我有一个Employee实体,它已表现为聚合根.在业务中,一些员工可以针对他们记录与工作相关的违规行为:

员工-----*违规

由于并非所有员工都受此限制,我认为违规行为不会成为员工总数的一部分,对吗?

因此,当我想与Employees及其相关的违规行为合作时,某个服务是否有两个独立的Repository交互?

最后,当我添加一个Violation时,是Employee Entity上的那个方法吗?谢谢您的帮助!

jle*_*bke 25

在做了更多的研究之后,我想我已经回答了我的问题.

Paul Stovell对DDD留言板上的类似问题进行了略微编辑.将"客户"替换为"员工",将"订单"替换为"违规",您就明白了.

仅仅因为客户引用订单并不一定意味着订单属于客户聚合根目录.客户的地址可能是,但订单可以是独立的(例如,您可能有一个处理所有新订单的服务,无论客户是谁.必须去客户 - >订单在这种情况下没有意义).

从域的角度来看,您甚至可以质疑这些引用的有效性(客户引用了订单列表).您实际需要多长时间才能获得客户的所有订单?在某些系统中它是有道理的,但在其他系统中,一个客户可能会订购许多订单.您可能希望客户在日期范围或未处理的客户订单或未付款的订单之间订购,等等.您需要所有这些场景的场景可能相对不常见.但是,在处理订单时,您更有可能需要客户信息.所以在代码中,Order.Customer.Name它很有用,但是Customer.Orders[0].LineItem.SKU- 可能不那么有用.当然,这完全取决于您的业务领域.

换句话说,更新客户与更新订单无关.在我的情况下,订单或违规行为可以设想独立于客户/员工处理.

如果违规具有明细行,则违规和违规行将成为同一集合的一部分,因为更改违规行可能会影响违规.

编辑**我的域名中的皱纹是违规没有行为.它们基本上是发生事件的记录.还不确定其含义.


Mos*_*osh 21

Eric Evan在他的书" 领域驱动设计:解决软件核心的复杂性"中指出,

AGGREGATE是一组关联对象,我们将其视为数据更改的单位.

这里有两个重点:

  1. 应将这些对象视为"单元".
  2. 出于"数据更改"的目的.

我相信你的场景,Employee和Violation不一定是一个单元,而在Order和OrderItem的例子中,它们是一个单元的一部分.

在对聚合边界进行建模时,另一个重要的事情是聚合中是否有任何不变量.不变量是应在"整体"聚合中有效的业务规则.例如,对于Order和OrderItem示例,您可能有一个不变量,表明订单的总成本应小于预定义的金额.在这种情况下,只要您想要向Order添加OrderItem,就应该强制执行此不变量以确保您的订单有效.但是,在您的问题中,我看不到您的实体之间存在任何不变量:Employee和Violation.

如此简短的回答:

我认为员工和违规都属于2个单独的聚合.这些实体中的每一个也都是它们自己的聚合根.所以你需要2个存储库:EmployeeRepository和ViolationRepository.

我也相信你应该有从Violation到Employee的单向关联.这样,每个Violation对象都知道它属于谁.但是,如果您想获取特定员工的所有违规列表,那么您可以询问ViolationRepository:

var list = repository.FindAllViolationsByEmployee(someEmployee);
Run Code Online (Sandbox Code Playgroud)