在“领域驱动设计:解决软件核心的复杂性”中,Evans 定义
An Aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes.
显然,这意味着聚合必须在单个事务中更新。
但是,一个事务必须只更新一个聚合吗?如果是,为什么?
我的研究
我问是因为,在“实现领域驱动设计”,第 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 页,Vernon 还写道:
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.
哪些并发问题?
最佳答案
乐观并发通常用于避免存在竞争的环境中的数据丢失。
让我们看看在适当的机制下什么会导致并发异常:
- 用户 Foo 加载版本 V1 的聚合 A。
- 用户 Bar 负载聚合 A,版本为 V1。
- 用户 Foo 更改聚合 A 并保留(版本为 增加到 V2)。
- 用户 Bar 更改聚合 A 并尝试坚持但会得到 并发异常,因为他的更改是基于 V1,但是 聚合现在处于 V2。
如果您允许在每个事务中修改多个聚合,则会增加并发异常的风险,这可能会损害系统的可扩展性,直至无法使用。
聚合根 (AR) 是事务边界,其中不变量是事务一致的,因此如果您发现自己试图修改多个 AR同样的交易,这意味着您的 AR 边界可能是错误的,并且您可能错过了将隐含概念明确化的机会。
但是请注意,在单个事务中创建多个 AR 应该没有问题。
设计 AR 时的常见错误是通过过于重视语句中的关系词来创建大型集群,例如:
"Posts have comments"
如果没有需要这种组合的不变强制,则没有理由将 Post
和 Comment
聚集在一起。两位作者同时发表同一条评论是否会导致并发异常?答案可能是否定的,具体取决于您的域,但如果 Post
包含 Comment
的集合,则答案是肯定的。
But what if the business does not care, and developers simply find it convenient?
好吧,如果企业不关心他们的系统由于糟糕的设计决策而无法扩展,我想这是他们的选择,但开发人员不应该养成为了方便而设计的习惯。 DDD 是按照领域的本来面目对领域进行建模,而不是方便建模的方式。
关于java - 在领域驱动设计中,一个事务可以修改多个聚合吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28222444/