这次我想到的问题是构建聚合所需的抽象级别应该是什么。
e.g。 订单由OrderWorkflowHistory,Comments
组成我和你一起去吗?
订单<> - OrderWorkflowHistory<> - WorkflowActivity
订单<> - CommentHistory<> - 评论
或的
订单<> - WorkflowActivity
订单<> - 评论
其中OrderWorkflowHistory只是一个对象,它将封装发生的所有工作流活动。它维护一个列表。 Order只是将维护活动列表的工作委托给该对象。
CommentHistory同样是用户附加的(list)注释的包装器。
说到数据库,最终订单被写入ORDER表,工作流活动列表被写入WORKFLOW_ACTIVITY表。在持久性方面,OrderWorkflowHistory并不重要。
从DDD的角度来看,这将是最优的。请分享您的经历!!
答案 0 :(得分:1)
正如您所描述的那样,容器(OrderWorkflowHistory
,CommentHistory
)似乎没有包含太多行为。在此基础上,我会投票省略它们并直接在Order
中管理列表。
一个警告。您可能会发现列表需要增加的行为量(例如复杂的搜索)。如果发生这种情况,引入一个/两个容器来封装该逻辑并阻止Order
变得臃肿可能是有意义的。
我可能从简单的解决方案(没有容器)开始,只有在如上所述的情况下才引入它们。只要外部客户端通过Order
的界面进行所有调用,您就可以在内部重构Order
而不会影响客户端。
第h
答案 1 :(得分:1)
这是一个很好的问题,如何建模和丰富您的域名。但是很难回答,因为它对于不同的领域变化很大。 我的经验是,当我开始使用DDD时,我最终得到了大量的存储库和一些价值对象。我重读了一些书籍并以开放的心态研究了几个DDD代码示例(有很多不同的方法可以实现DDD。并非所有这些都适合您当前的项目场景)。 我开始尝试记住“更多的价值对象,更多的价值对象,更多的价值对象”。为什么? Well Value对象带来的依赖性较小,行为也较多。 在上面的例子中,有一对多(1-n)关系,我已经解决了1-n rel。根据我的用例以不同的方式使用域名。
(1)有时我创建一个值对象的包装类(如OrderWorkflowHistory)。创建对象时设置子对象的完整列表。当您有一组必须在一个请求期间设置的子对象时,此方案很好。例如,问卷表格上的Qeustion权重。然后所有问题都应该通过一个方法Questionaire.ApplyTuning(QuestionaireTuning)得到他们的问题权重,其中QuestionaireTuning就像你的OrderWorkflowHistory,一个List的包装器。这为域名增加了很多: a)问卷调查永远不会处于无效状态。一旦我们应用了调整,我们就会对所有问卷中的问题进行调整。 b)QuestionaireTuning可以提供良好的访问/搜索方法来检索特定问题的权重或计算平均体重评分等。
(2)另一种方法是让1-n包装类不是Value对象。如果您想要偶尔添加子对象,这种方法更适合。由于x个子对象,父级不能处于无效状态。这个典型的包装类有Add(Child ...)方法和几个search / contains / exists / check方法。
(3)第三种方法是将IList暴露为只读集合。您可以使用Extension方法添加一些搜索功能(.Net 3.0中的新功能),但我认为这是一种设计气味。最好通过list-wrapper类封装提供的列表访问方法。
关于方法一的一些例子,请看http://dddsamplenet.codeplex.com/。
我相信整个讨论与建模Value对象,实体以及谁负责什么行为是DDD中最为中心的。请分享您对此主题的看法......