DDD:聚合根需要来自另一个聚合根的信息

DDD: aggregate root needs information from another aggregate root

我正在考虑设计一个相当简单的问题,但我想听听其他解决方案来妥善处理它。

此时我有 2 个聚合根:

  1. User:包含有关用户的信息,例如 display namelinked accountsprofile,可以是 patient profilecare provider profile。这样的患者资料包含 birth dategender 等信息。我有一个 UserRepository 负责获取和保存用户。
  2. Screening:包含有关健康的信息,例如长度和体重测量值,以及基于这些长度和体重的所有类型的计算信息,例如“短期进化”。我有一个 ScreeningRepository 负责获取和保存用户。

所以Screening里面有一个Calculate()的方法,目的是在weightand/orlength的时候加上一个screening,像short term evolution这样的健康属性会立即重新计算,使screening始终处于一致和正确的状态。

问题是这个计算还需要用户的 genderbirth date,它们存储在 patient profile.

所以基本上,聚合根 screening 依赖于聚合根 user。所以我想知道如何去做...

  1. 根据 DDD,聚合根不应引用另一个聚合根。而且,如果我让 user 成为 screening 的 属性,ScreeningRepository 也将负责使用户非物质化,这当然不是他的任务。

  2. 如果 screening 没有参考 user,那么 Calculate() 没有所有需要的信息。所以这意味着我可能应该将它移动到域服务,它获取 userscreening 作为输入,并进行计算。美好的。但是,我怎样才能确保将测量添加到筛选时,触发 Calculate

  3. 我考虑的另一个选择是不使 screening 成为聚合根,而使它只是与父 user 的聚合。这也使我能够更好地验证 screening,因为我也可以访问 User。它将解决有关计算的所有问题,因为我手头有所有信息,但这样一来,UserRepository 也将负责处理 screening,而我的聚合根负责 [=48] =] 和 screenings

在这一点上,最后一个选项似乎是唯一可以轻松解决问题的选项,但我很想听听任何关于事情的想法,因为我可能会遗漏明显的概念。

没有魔法。

如果 Screening 的域逻辑需要性别和出生日期,那么您将需要将这些值的副本放入聚合中。这反过来意味着要么 (a) 您传入值,要么 (b) 您传入支持查询值的功能。

通常情况下,聚合会缓存数据的本地副本"belongs"到另一个聚合。在这种情况下,您可能需要解决如果缓存数据需要失效会发生什么情况(例如:如果我们后来发现生日数据输入错误会发生什么情况?)

聚合是 DDD 中最容易被误解的概念。

User: holds information about a user like display name

它永远与数据无关,它始终与行为有关。只是一个实践建议:在第一次迭代中,将整个有界上下文作为一个聚合,所有内容都在一个对象中。

会发生什么?首先,您现在能够满足限界上下文中可能存在的每个不变量。好吧,但你会说这太疯狂了,我不能把所有东西都加载到一个对象中,这会非常慢,而且在此期间没有其他人可以使用该对象。正确的!聚合只存在一个原因:性能优化!找到永远不会相互影响的不变量取决于您,以便您可以拆分对象以提高系统的性能。如何拆分对象?

似乎患者资料可能是聚合根的一个很好的候选者,方法 Screen() 封装了当前筛选逻辑和 SetWeightInKg(w) 来修改权重。护理提供者概况可能是另一个集合。再算一个。都只是持有一个UserId作为参考。

我们的目标是将属于一起的不变量放在一个聚合中,并将不属于的不变量分开,所有这些都是为了性能。