【问题标题】:Update two aggregate instances in a single transaction在单个事务中更新两个聚合实例
【发布时间】:2021-07-05 08:49:40
【问题描述】:

假设我们有一个用于银行服务的 Account 聚合。有人想将钱从他们的账户转移到另一个人的账户。有许多规则:付款人需要在他们的账户中有足够的钱,并且收款人的账户必须是活跃的。如果这些规则通过,则两个账户的余额都会更新。在传统系统中,这可以很容易地在单个酸数据库事务中完成。

在 DDD 中这是不允许的,因为我们不能在一个事务中更新两个聚合实例?首先,为什么?其次,这是否意味着使用最终一致性来处理两个帐户?如果是这样,我可以看到如何做到这一点,但这会增加很多复杂性。

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    在 DDD 中这是不允许的

    不是真的 - 这里发生了很多事情。

    Evans (2003) 和 Vaughn 2013 写道,事务管理不是域模型问题,而是事务控制属于应用程序代码。

    然而,同时更改多个聚合存在一个真正的问题:这样做假设您可以同时获取这些实体上的锁,并将所有这些更改一起提交。

    当您要更改的所有聚合都存储在单个关系数据库中时,这相对简单;但是当聚合存储在不同的地方时变得非常困难。

    如果您设计系统时假设所有聚合都存储在一起,那么您会极大地限制您的扩展选项。

    注意不要仅仅因为它在单元测试环境中工作而过度使用在单个事务中提交对多个聚合的修改的能力 -- Vaughn 2013。


    这是否意味着使用最终一致性来处理两个帐户

    那,或者改变你对聚合建模的方式。有时两者兼而有之。

    例如,处理(短期)进程的聚合有点常见,这与长期聚合不同。

    当我查看信用卡对帐单时,收费通常会处于以下三种状态之一:尚未发布到我的对帐单中(不可见),或待处理(可见)​​,或实际上已作为收费发布(可见的)。显然,“其他地方”发生了一些事情,这些信息最终被复制到我可以看到的声明中。


    我可以看到如何做到这一点,但它增加了很多复杂性。

    是的。如果它不复杂/复杂,我们就不会创建自己的模型;相反,我们会自行购买一些通用解决方案。

    Greg Young 在2011 presentation 中谈到了这一点:领域驱动设计在我们可以从我们所做的工作中获得竞争优势的地方是有意义的。换句话说,我们在让业务控制复杂性提高底线的地方使用它。

    确保您在构建与购买线的正确方面工作是重要的一步。不要跳过它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-05
      • 2019-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-11
      • 1970-01-01
      • 2019-12-04
      相关资源
      最近更新 更多