在域驱动设计中,事务是否可以修改多个聚合?

时间:2015-01-29 18:57:37

标签: java transactions domain-driven-design aggregateroot

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

  

聚合是一组关联对象,我们将其视为一个单元,用于更改数据。

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

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

我的研究

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

  

引用聚合和引用的聚合都不能在同一事务中修改。在单个交易中只能修改一个或另一个。

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

我理解,如果业务规则需要单个事务,则表示隐藏的不变量,这将要求实体成为同一聚合的一部分。但是,如果业务不关心,开发人员只是觉得它很方便呢?

在第437页,弗农还写道:

  

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

那些并发问题是什么?

1 个答案:

答案 0 :(得分:4)

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

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

  1. 用户Foo加载版本为V1的聚合A.
  2. 用户栏加载版本为V1的聚合A.
  3. 用户Foo更改聚合A并保持不变(版本为     递增到V2)。
  4. 用户栏更改聚合A并尝试保留但会得到一个     并发异常,因为他的更改是基于V1,但是     聚合现在是V2。
  5. 如果允许每个事务修改多个聚合,则会增加并发异常的风险,这可能会损害系统的可伸缩性,直至使其无法使用。

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

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

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

      

    “帖子评论”

    如果没有需要该组合的不变执行,则没有理由将PostComment聚合在一起。两个作者是否应该同时在同一个评论上发布会导致并发异常?答案可能是否定的,具体取决于您的域名,但如果Post包含Comment的集合,则会回答。

      

    但是,如果企业不关心,开发人员只是找到它   方便?

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