在领域驱动设计中,一个事务可以修改多个聚合吗?

mer*_*ike 6 java domain-driven-design transactions aggregateroot

在“领域驱动设计:解决软件核心的复杂性”中,埃文斯定义了

骨料是相关联的对象的簇,我们把作为数据更改的目的的单元。

显然,这意味着必须在单个事务中更新聚合。

但是,事务是否必须只更新单个聚合?如果是这样,为什么?

我的研究

我问是因为,在“实施领域驱动设计”,第 360 页,弗农写道:

不得在同一事务中修改引用聚合和被引用聚合。在单个事务中只能修改一个或另一个。

但没有给出这个规则的理由。

我知道如果业务规则需要单个事务,这表示隐藏的不变量,这将要求实体成为同一聚合的一部分。但是,如果业务不在乎,而开发人员只是觉得方便怎么办?

在第 437 页,弗农还写道:

注意不要仅仅因为它在单元测试环境中工作就过度使用在单个事务中提交对多个聚合的修改的能力。如果您不小心,在开发和测试中运行良好的方法可能会由于并发问题而在生产中严重失败。

那些并发问题是什么?

pla*_*alx 6

乐观并发通常用于在存在争用的环境中避免数据丢失。

让我们看看什么会导致使用该机制的并发异常:

  1. 用户 Foo 加载了 V1 版本的聚合 A。
  2. 用户栏负载聚合 A,版本 V1。
  3. 用户 Foo 更改聚合 A 并保持不变(版本增加到 V2)。
  4. 用户栏更改了聚合 A 并尝试持久化,但会收到并发异常,因为他的更改基于 V1,但聚合现在处于 V2。

如果您允许每个事务修改多个聚合,则会增加并发异常的风险,这可能会损害系统的可伸缩性,直至使其无法使用。

聚合根 (AR) 是事务边界,其中不变量是事务一致的,因此如果您发现自己试图在同一事务中修改多个 AR,则意味着您的 AR 边界可能是错误的,并且您可能会错过进行隐式的机会概念明确。

但是,请注意,在单个事务中创建多个 AR应该没有问题。

设计 AR 时的常见错误是通过过分重视以下语句中的关系词来创建大型集群:

“帖子评论”

我们没有理由对集群PostComment在一起,如果没有不变的执法这就要求组成。两位作者同时发表同一评论是否会导致并发异常?答案可能是否定的,具体取决于您的域,但如果Post包含Comment.

但是,如果业务不在乎,而开发人员只是觉得方便怎么办?

好吧,如果企业不关心他们的系统由于糟糕的设计决策而无法扩展,我想这是他们的选择,但开发人员不应该养成为了方便而设计的习惯。DDD 是按照域的方式对域进行建模,而不是建模方便的方式。