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

In Domain Driven Design, may a transaction modify more than one aggregate?

在"Domain Driven Design: Tackling Complexity in the Heart of Software"中,埃文斯定义

An Aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes.

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

但是,一个事务必须只更新一个聚合吗?如果是,为什么?

我的研究

我问是因为,在 "Implementing Domain Driven Design",第 360 页,Vernon 写道:

Both the referencing aggregate and the referenced aggregate must not be modified in the same transaction. Only one or the other may be modified in a single transaction.

但没有给出此规则的原因。

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

在第 437 页,弗农还写道:

Be careful not to overuse the ability to commit modifications to multiple aggregates in a single transaction just because it works in a unit test environment. If you aren't careful, what works well in development and test can fail severely in production because of concurrency issues.

哪些并发问题?

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

让我们看看在适当的机制下什么会导致并发异常:

  1. 用户 Foo 加载聚合 A,版本为 V1。
  2. V1版本的用户栏负载聚合A。
  3. 用户 Foo 更改聚合 A 并保留(版本为 增加到 V2)。
  4. 用户 Bar 更改聚合 A 并尝试坚持但会得到一个 并发异常,因为他的更改是基于 V1,但是 聚合现在是 V2.

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

聚合根 (AR) 是交易边界,其中不变量是交易一致的,所以如果您发现自己试图修改同一笔交易中的多个 AR 这意味着您的 AR 边界可能是错误的,并且您可能错过了将隐含概念显式化的机会。

但是请注意,在一次交易中创建多个AR应该没有问题。

设计 AR 时的常见错误是通过过于重视语句中的关系词来创建大集群,例如:

"Posts have comments"

如果没有需要这种组合的不变强制,则没有理由将 PostComment 聚集在一起。两位作者同时发表同一条评论是否会导致并发异常?答案可能是否定的,具体取决于您的域,但是如果 Post 包含 Comment.

的集合

But what if the business does not care, and developers simply find it convenient?

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