在聚合之间强制实施不变量的最佳方法是什么?

时间:2017-11-08 13:04:44

标签: domain-driven-design

处理聚合之间一致性的最佳方法是什么?有一个来自Vaugn Vernon书的例子,你有BacklogItem聚合和SprintAggregate。当引发BacklogItemEvent时,事件处理程序捕获它并尝试更新Sprint Aggregate。如果此操作失败怎么办?如何找到处理这种情况的最佳方法?据我了解,有3种选择: 1)更新一个事务中的所有聚合。我们失去了可扩展性,但我们获得了一致性。 2)什么都不做。只需记录和错误,然后等待手动干预。 3)使用传奇。这使设计复杂化并迫使我们实现每个用例,这些用例必须在单独的对象(saga)中对聚合之间的envaria进行包围。如果Sprint更新失败,saga将尝试取消提交Backlog项目(补偿)。   您将选择以下哪个选项,以及您所依据的标准是什么?

2 个答案:

答案 0 :(得分:2)

  

处理聚合之间一致性的最佳方法是什么?

如果您的聚合设计正确,那么您将随着时间的推移处理聚合之间的“一致性”(也就是:最终一致性)。

  

如果此操作失败怎么办?

仔细阅读Race Conditions Don't Exist; Udi Dahan提出一个论点,即协作域中的操作应该失败。

  

在一个交易中更新所有聚合。

你可以这样做;但这实际上意味着这两个实体实际上是单个隐式聚合的一部分。换句话说,它强烈暗示您没有在正确的位置获得聚合边界。

尝试在单个事务中修改多个聚合实际上是两阶段提交,并且由此产生了所有其他复杂情况。

  

什么都不做。只需记录并错误并等待手动干预。

烨;比如说; Greg Young对warehouse systems and exception reports所说的话。

  

使用传奇。这使设计复杂化并迫使我们实现每个用例,这些用例必须在单独的对象(saga)中的聚合之间强制执行不变量。

现在,您通常会看到“流程管理器”而不是“saga”,它具有更具体的含义。但是,是的,如果域模型需要在聚合之间进行编排,那么您将需要在某处描述编排逻辑。

您可能想查看Rinat Abdullin对Evolving Business Processes的讨论;他提出了一个很好的论据,即自动化只是复制人类操作员所采取的行动。

  

您将选择以下哪个选项,以及您所依据的标准是什么?

我非常喜欢简单到容易。所以我的目标是异常报告,理由是:(a)这些失败无论如何都应该是罕见的,因此我们不希望在远离快乐道路的工作中投入大量设计资金,以及(b)如果我们在系统中有失败的命令,那么我们应该有一个机制来报告失败的命令无论如何,所以我只是利用已经存在的命令。

如果我被挤压了一段时间,如果项目尚未成功到足以需要扩展,如果我手头没有报告件,我可能更愿意将更改隐藏到单个交易中,然后在开发过程中提出一个异常报告,提请注意以后需要做更多工作的事实。

答案 1 :(得分:1)

  

您将选择以下哪个选项,以及您的标准是什么   基于?

  1. 域专家输入。如果他们始终要求极其严格的正确性,那么最终的一致性很可能无法实现。还有一些时候,补偿行动需要在给定领域几乎不可行的人工干预。或者,将人类包括在循环中可能是非常简单和有益的。与商务人士交谈将教会您更广泛的域名流程,并发现或排除某些选项。

  2. 交易分析。如果他们没有强大的并发访问权限,那么在单个事务中更新2个聚合可能不会有问题。相比之下,识别"hot" aggregates可以让您在重要的地方利用更松散的一致性。

  3. 使用案例复杂性。并非所有最终的一致性场景都需要Saga。如果操作非常简单,只需更新聚合作为事件的结果,并在不太可能发生更新失败的情况下回滚原始更改,那么您可能不需要这样复杂,长期存在的模式。 / p>