concurrency - 拆分聚合根以避免并发冲突

标签 concurrency domain-driven-design aggregateroot

越来越多地了解聚合根,特别是来自 Vaughn Vernon 的 I-DDD,我提出了一个关于并发的问题。

一个系统同时被多个用户访问。 (当前)核心域 是关于教育中心的“注册”,因此有一个代表业务主要客户的 Student 实体。 Student 是一个聚合根,当然有很多信息。

假设一个 Student 有一个 PersonalAddressAcademicInformation(过去的学校,成绩,...)都建模为 Value Aggregate 中的对象,并且 - 为了争论 - 在同一个 Aggregate 中没有其他 EntityStudent AggregateEntity 中使用类似版本属性的乐观并发,因此对其数据的任何更改都会增加该版本。

问题是,如果两个不同的用户试图同时修改同一 StudentPersonalAddressAcademicInformation,其中之一即使地址和学术信息完全无关,这些尝试也会失败;虽然两者都是VO,但它们属于同一个聚合

我想我可以拆分 Aggregate 以避免并发冲突,因为除了“属于”之外,没有与 PersonalAddressAcademicInformation "给同一个 Student。但那些是 VO 没有自己的身份。我将不得不创建另一个实体并将它们放在不同的聚合根中,它们都包含与同一学生相关的信息片段,因此可以同时修改它们。

所以问题是:

  1. 如何避免修改被建模为值对象(PersonalAddress, AcademicInformation)?
  2. 如我之前解释的那样,将 Student Aggregate 拆分为两个或更多不同的Aggregate Roots 是一种“好方法”™吗?
  3. 即使这种特殊情况可以通过其他方式解决(如果分享的话,我将不胜感激),如何从更普遍的角度解决这个问题?

我认为一切都取决于用户尝试并发修改信息的频率,并据此决定拆分聚合是否值得...但我不知道。

非常感谢。

最佳答案

1) 您可以通过其他方式使用乐观并发:基于旧值,而不是版本号。例如。改变学生的命令应该看起来像 new ChaneStudentCmd { StudentId = ...; OldAddressStreet = "xxx"; NewAddressStreet = "yyy"},实现应该确保当前的 strret 在改变它之前是“xxx”。如果不是“xxx”应该抛出并发异常。

2)我认为没有理由拆分聚合。

3) 一般方法可以使用更具体的更新命令,而不是简单的“更新所有学生属性”。业务层应该有关于那个确切的用户想要更新的信息。有了这些信息,考虑到并发性和其他需求,它将能够优雅地处理更新。

关于concurrency - 拆分聚合根以避免并发冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47723264/

相关文章:

java - 多线程状态相关问题

domain-driven-design - 如何在领域驱动设计中设计自引用聚合

java - 线程转储显示不正确的线程状态

Java:重新设计开源库的并发性

emacs - 在多台机器之间远程运行 Emacs

domain-driven-design - 何时更新审计字段? DDD

domain-driven-design - Lightbend 响应式(Reactive)架构认证

python - Django 和领域驱动设计

validation - 领域驱动设计 : How to handle a conceptually large aggregate root?

repository - DDD 和 MVC : The Contoller gets the AggregateRoot from Factory not Repository? 是吧?