这是在DDD中分离聚合的最佳方法

时间:2018-08-10 10:12:29

标签: aggregate dddd

我正在学习DDD,我不清楚如何将对象分离为聚合。

示例:

我有3个对象:公司,商店,工作。

我有一些关系:一家公司有很多商店,而一家商店有很多工作。

我认为:

没有公司就不可能存在一家商店。公司必须拥有商店,这是真实世界。因此,我将公司和商店合并为一个集合。

工作是另一个汇总。

另一种想法

找工作时,我总是在意这份工作属于哪家商店。 因此,我将:将商店和工作归为一个整体。

公司是另一个集合。

哪种方法是对的?

谢谢

1 个答案:

答案 0 :(得分:1)

唯一可能的答案当然是“ 这取决于。”,但这并不是特别有用。

查看Evan的书中汇总的定义:

  

AGGREGATE是一组关联对象,我们将其视为   用于数据更改的单位...不变式,它们是   每当数据更改时必须维护的一致性规则   涉及AGGREGATE成员之间的关系。任何规则   跨度AGGREGATES不会始终保持最新   ...但是在AGGREGATE中应用的不变式将被强制执行   完成每笔交易。

因此,“什么对象构成了我的聚合”和“我的聚合根是什么?”这样的问题取决于在哪些业务交易中需要强制执行哪些业务不变量?

您不像设计关系数据库中的表那样设计聚合。您不必担心“现实生活”中实体之间关系的多重性。您正在寻找在影响(更改其实体的数据)这些动作的操作结束时哪些事实(属性,值)必须为真。

查看您的要求。查看您的系统需要支持哪些行为。你能做什么工作?创建它们?启动他们?完成他们?您可以将工作从一家商店转移到另一家商店吗?可以在公司之间转移工作吗?

哪些事实需要保持一致?例如,您是否在每个商店强制执行最大数量的工作?在“添加工作”的末尾,商店中当前的工作数量是否需要与工作的商店分配保持一致?

由于只能通过聚合根与聚合进行交互,因此需要考虑如何添加新数据。例如,您可以创建没有初始商店分配的工作吗?还是只能通过商店创建?

在事务中更新聚合时,聚合的大小/范围与数据争用的可能性之间也存在折衷。

考虑到所有这些问题,您可能想知道为什么 bother 带有聚合?好吧,他们在几件事上都很出色:

  • 命令的验证和执行是快速的,因为您需要的所有数据都包含在聚合中
  • 它们非常适合基于文档的持久性存储(例如MongoDB,其中的嵌套对象用于聚合对象),这使聚合状态的检索变得简单而高效,并通过文档级原子更新轻松实现了聚合事务边界。
  • 它们非常易于测试,因为它们可以实现为简单的类(C#或Java中的POCO / POJO)。因为它们包含您的大多数业务逻辑,所以这意味着您整个应用程序的行为也易于进行单元测试!
  • 他们专心;每个聚合都有其目的,从它们实现的数据和功能以及它们在系统中所做的工作很清楚。结合利用您在代码本身中编码的上下文的无处不在的语言,它们是您的业务行为在代码库中最直接的表达(远远超出了单独的一组数据表)
  • 由于它们是特定于用例的,因此聚合通常可以避免在更通用的解决方案中出现的泄漏抽象

如果您有兴趣阅读更多内容,沃恩·弗农(Vaughn Vernon)在其Effective Aggregate Design帖子中提供了一个不错的摘要,这些摘要是他写的一本厚实的书《实现域驱动设计》的基础。