DDD中的多对多关系

Ser*_*kiy 19 c# domain-driven-design

我是DDD的新手,而且我遇到了多对多的关系.例如,我们有两个聚合根 - 任务和工人.

合同绝对不是聚合根,因为没有Task和Worker就没有意义.所以,它应该是某些聚合的一部分.但它属于哪个聚合体?我们需要知道所有工作合同的汇总成本和所有工人合同的汇总成本.我很自然地在Task和Worker中收集合同.

好吧,我可以将费用计算转移到域名服务,但我担心这是贫穷模型的一步.有没有通用的方法来处理多对多关系并保留覆盖域模型?

谢谢!

类图

Dom*_*nic 15

通过关注侧边栏中链接的相关问题,我发现了这篇有趣的文章:

DDD和多对多对象关系映射

它似乎建议我无论如何都在直觉地思考:事实上,对于工人和任务来说,依赖合同是不自然的.也就是说,没有"合同"的概念(类似于任务),"工人"的概念仍然是有意义的,因此体现该概念的实体不应该依赖于合同实体.

要显示分配给给定任务的合同或分配给给定工作人员的合同,您需要运行域查询.这实际上是域服务的合适用途,如果您考虑它,可以更好地反映您的域的实际情况.

我还注意到你说"合同绝对不是聚合根,因为没有任务和工人就没有意义".这实际上是Contract 聚合根的确切原因.

所以,我的建议,根据评论纳入了arootbeer的见解: 提出新的类图

  • 我认为将 `GetCosts()` 放在 `Task` 和 `Worker` 上是很混乱的事情 - `Task` 和 `Worker` 都没有体现明确的成本;那显然是“合同”的领域。`Worker` 有一个 `Rate`,一个 `Task` 有一个 `Period` 或 `Duration`;`Contract` 中两者的组合指定了 `Cost`。`GetCosts()` 可能是一个域搜索聚合函数。 (2认同)

aro*_*eer 5

Contract在我看来,你的设计是一流的对象.你声称它在a worker和a 的上下文之外没有意义,这task当然是正确的,但这并不意味着它本身不是一个聚合根.

据推测Contract,它有自己的逻辑来计算其成本,基于它的一些属性taskworker与之相关.同样,有上下文TaskWorker含有不相关的Contract.

跳转所需的差距是将相关上下文移动到Contract对象中.让它存储worker的速率和task周期(除了相应的ID,仅在上面隐式建模),并动态计算成本.

- 编辑 -

正如Domenic所述,您的评论是后续问题的良好候选人.但我要说的是,一旦你获得了ID TaskWorkerID Contract,报告就变成了一项微不足道的任务.