我正在开始一个新的DDD项目,我觉得我还没有真正掌握这些概念。到目前为止,我的域名中有两个聚合根,Recipe
和Food
。他们的关系是这样的:
`Recipe`->*`Ingredient`->`Food`
Ingredient
是数量+ Food
我认为可能在Food
聚合中使用聚合(Recipe
)是不好的,但它非常方便,因为它允许通过导航关系来计算配方的营养价值。
我也没有存储计算结果,我每次都会重新计算,所以如果食物被更改,食谱会自动更新,我不知道这是不是一个好主意。
此外,为Recipe
+ Ingredient
设置单个存储库是好的,因为它们在同一个聚合中,我必须加载所有成分,以便我可以在构造函数中传递它们食谱无论如何?
答案 0 :(得分:3)
对于Recipe + Ingredient有一个单独的存储库是好的,因为它们在同一个聚合中,我必须加载所有成分,所以我可以在配方的构造函数中传递它们吗?
这是大多数人所期望的 - 一个加载聚合边界内所有状态的存储库。
我认为可能在配方聚合中使用聚合(食物)是不好的,但它非常方便,因为它允许通过导航关系来计算配方的营养价值。
聚合的动机是限制模型中数据的更改方式,以便每次更改都使模型处于内部一致状态。
如果您的域没有任何一致性约束来强制执行(例如,当您的数据模型实际上只是一个数据库,并且数据模型对提议的更改没有否决权时),则问题空间不会#&# 39;在选择良好的聚合边界方面提供了很多指导。
聚合背后的基本原则是您正在创建一种数据防火墙,您永远不必担心此聚合的更改将违反的规则聚合。除其他外,这意味着任何两个聚合都不应该共享可变数据。
共享值很好 - 每个聚合都获得自己的值的不可变副本,而在一个聚合中更改值根本不会影响另一个。共享实体很糟糕,因为实体是可变的。
拥有一个能够非常方便地生成具有错误答案的查询的模型并不像确保答案正确的模型那样有价值。
通常会发生的是,一个聚合将通过ID引用另一个聚合。所以你的食谱看起来像
`Recipe`->*`Ingredient`->`Id<Food>`
Id<Food>
只是另一个不可变的值类型;配方可以很容易地改变它使用的食物,但它不能以任何方式改变食物。这反过来意味着你永远不必担心改变一个Recipe
会破坏另一个。{/ p>