0

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

一个例子:

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

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

我想:

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

Job 是另一个聚合体。

另一个想法

找工作时,我总是关心这份工作属于哪家商店。因此,我将:购物和工作归为一个集合。

公司是另一个集合体。

哪种方式是正确的?

谢谢

4

1 回答 1

1

当然,唯一可能的答案是“视情况而定”。不过,这并不是特别有用。

回顾 Evan 书中聚合的定义:

AGGREGATE 是一组关联对象,我们将其视为一个单元,用于数据更改。不变量是在数据更改时必须维护的一致性规则,将涉及 AGGREGATE 成员之间的关系。任何跨越 AGGREGATES 的规则都不会一直是最新的……但是在 AGGREGATE 中应用的不变量将在每个事务完成时强制执行。

所以“什么对象构成了我的聚合”和“什么是我的聚合根”的问题。取决于需要在哪些业务事务中强制执行哪些业务不变量?

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

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

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

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

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

考虑到所有这些事情,您可能想知道为什么还要为聚合而烦恼?好吧,他们擅长以下几件事:

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

如果您有兴趣阅读更多内容,Vaughn Vernon 在他的Effective Aggregate Design帖子中有一个很好的总结,这是他的厚书“实施领域驱动设计”的基础。

于 2018-10-02T22:39:29.180 回答