DDD:聚合根需要来自另一个聚合根的信息
DDD: aggregate root needs information from another aggregate root
我正在考虑设计一个相当简单的问题,但我想听听其他解决方案来妥善处理它。
此时我有 2 个聚合根:
User
:包含有关用户的信息,例如 display name
、linked accounts
和 profile
,可以是 patient profile
或 care provider profile
。这样的患者资料包含 birth date
和 gender
等信息。我有一个 UserRepository
负责获取和保存用户。
Screening
:包含有关健康的信息,例如长度和体重测量值,以及基于这些长度和体重的所有类型的计算信息,例如“短期进化”。我有一个 ScreeningRepository
负责获取和保存用户。
所以Screening
里面有一个Calculate()
的方法,目的是在weight
and/orlength
的时候加上一个screening
,像short term evolution
这样的健康属性会立即重新计算,使screening
始终处于一致和正确的状态。
问题是这个计算还需要用户的 gender
和 birth date
,它们存储在 patient profile
.
所以基本上,聚合根 screening
依赖于聚合根 user
。所以我想知道如何去做...
根据 DDD,聚合根不应引用另一个聚合根。而且,如果我让 user
成为 screening
的 属性,ScreeningRepository
也将负责使用户非物质化,这当然不是他的任务。
如果 screening
没有参考 user
,那么 Calculate()
没有所有需要的信息。所以这意味着我可能应该将它移动到域服务,它获取 user
和 screening
作为输入,并进行计算。美好的。但是,我怎样才能确保将测量添加到筛选时,触发 Calculate
?
我考虑的另一个选择是不使 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作为参考。
我们的目标是将属于一起的不变量放在一个聚合中,并将不属于的不变量分开,所有这些都是为了性能。
我正在考虑设计一个相当简单的问题,但我想听听其他解决方案来妥善处理它。
此时我有 2 个聚合根:
User
:包含有关用户的信息,例如display name
、linked accounts
和profile
,可以是patient profile
或care provider profile
。这样的患者资料包含birth date
和gender
等信息。我有一个UserRepository
负责获取和保存用户。Screening
:包含有关健康的信息,例如长度和体重测量值,以及基于这些长度和体重的所有类型的计算信息,例如“短期进化”。我有一个ScreeningRepository
负责获取和保存用户。
所以Screening
里面有一个Calculate()
的方法,目的是在weight
and/orlength
的时候加上一个screening
,像short term evolution
这样的健康属性会立即重新计算,使screening
始终处于一致和正确的状态。
问题是这个计算还需要用户的 gender
和 birth date
,它们存储在 patient profile
.
所以基本上,聚合根 screening
依赖于聚合根 user
。所以我想知道如何去做...
根据 DDD,聚合根不应引用另一个聚合根。而且,如果我让
user
成为screening
的 属性,ScreeningRepository
也将负责使用户非物质化,这当然不是他的任务。如果
screening
没有参考user
,那么Calculate()
没有所有需要的信息。所以这意味着我可能应该将它移动到域服务,它获取user
和screening
作为输入,并进行计算。美好的。但是,我怎样才能确保将测量添加到筛选时,触发Calculate
?我考虑的另一个选择是不使
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作为参考。
我们的目标是将属于一起的不变量放在一个聚合中,并将不属于的不变量分开,所有这些都是为了性能。