如何创建聚合
这次我想到的问题是构建聚合所需的必要抽象级别应该是什么。
例如 订单由 OrderWorkflowHistory 组成,
我是否同意评论
订单 <>- OrderWorkflowHistory <>- WorkflowActivity
订单<>-评论历史<>-评论
或
订单 <>- WorkflowActivity
Order <>- Comment
其中 OrderWorkflowHistory 只是一个对象,它将封装发生的所有工作流活动。它维护一个列表。订单只是将维护活动列表的工作委托给该对象。
CommentHistory 类似地是用户附加的(列表)评论的包装。
当涉及到数据库时,最终订单将被写入 ORDER 表,工作流活动列表将被写入 WORKFLOW_ACTIVITY 表。对于持久性而言,OrderWorkflowHistory 并不重要。
从 DDD 的角度来看,这将是最佳的。请分享您的经验!
Well this time the question I have in mind is what should be the necessary level of abstraction required to construct an Aggregate.
e.g.
Order is composed on OrderWorkflowHistory, Comments
Do I go with
Order <>- OrderWorkflowHistory <>- WorkflowActivity
Order <>- CommentHistory <>- Comment
OR
Order <>- WorkflowActivity
Order <>- Comment
Where OrderWorkflowHistory is just an object which will encapsulate all the workflow activities that took place. It maintains a list. Order simply delegates the job of maintaining th list of activities to this object.
CommentHistory is similarly a wrapper around (list) comments appended by users.
When it comes to database, ultimately the Order gets written to ORDER table and the list of workflow activities gets written to WORKFLOW_ACTIVITY table. The OrderWorkflowHistory has no importance when it comes to persistence.
From DDD perspective which would be most optimal. Please share your experiences !!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如您所描述的,容器(
OrderWorkflowHistory
、CommentHistory
)似乎没有封装太多行为。在此基础上,我投票忽略它们并直接在Order
中管理列表。需要注意的是。您可能会发现列表所需的行为数量不断增加(例如复杂的搜索)。如果发生这种情况,引入一个/两个容器来封装该逻辑并阻止
Order
变得臃肿可能是有意义的。我可能会从简单的解决方案(无容器)开始,并且仅在如上所述合理的情况下才引入它们。只要外部客户端通过
Order
的接口进行所有调用,您就可以在内部重构Order
而不会影响客户端。嗯。
As you describe it, the containers (
OrderWorkflowHistory
,CommentHistory
) don't seem to encapsulate much behaviour. On that basis I'd vote to omit them and manage the lists directly inOrder
.One caveat. You may find increasing amounts of behaviour required of the list (e.g. sophisticated searches). If that occurs it may make sense to introduce one/both containers to encapulate that logic and stop
Order
becoming bloated.I'd likely start with the simple solution (no containers) and only introduce them if justified as above. As long as external clients make all calls through
Order
's interface you can refactorOrder
internally without impacting the clients.hth.
这是一个很好的问题,如何建模和丰富您的领域。但很难回答,因为不同领域的情况差异很大。
我的经验是,当我开始使用 DDD 时,我最终得到了很多存储库和一些值对象。我重读了一些书籍,并以开放的心态研究了几个 DDD 代码示例(实现 DDD 的方法有很多种。并非所有方法都适合您当前的项目场景)。
我开始尝试记住“更多的价值对象,更多的价值对象,更多的价值对象”。为什么?
Well Value 对象带来了不那么严格的依赖关系和更多的行为。
在上面的一对多 (1-n) 关系示例中,我已经解决了 1-n 关系。根据我的用例以不同的方式使用域。
(1)有时我创建一个包装类(如您的 OrderWorkflowHistory),它是一个值对象。子对象的整个列表是在创建对象时设置的。当您有一组必须在一个请求期间设置的子对象时,此方案非常有用。例如,问卷调查表上的问题权重。然后,所有问题都应该通过 Questionaire.ApplyTuning(QuestionaireTuning) 方法获取其问题权重,其中 QuestionaireTuning 就像您的 OrderWorkflowHistory,是列表的包装器。这给域增加了很多:
a) 问卷永远不会处于无效状态。一旦我们应用调整,我们就会针对问卷中的所有问题进行调整。
b) QuestionaireTuning 可以提供良好的访问/搜索方法来检索特定问题的权重或计算平均权重分数...等。
(2)另一种方法是让 1-n 包装类不是 Value 对象。如果您想偶尔添加子对象,则此方法更适合。由于有 x 个子对象,父对象不能处于无效状态。这个典型的包装类有 Add(Child...) 方法和几个搜索/包含/存在/检查方法。
(3)第三种方法是将 IList 公开为只读集合。您可以使用扩展方法(.Net 3.0 中的新功能)添加一些搜索功能,但我认为这是一种设计味道。最好通过列表包装类封装提供的列表访问方法。
请参阅 http://dddsamplenet.codeplex.com/ 了解方法一的一些示例。
我相信对价值对象、实体建模以及谁负责什么行为的整个讨论是 DDD 中最核心的。请围绕这个主题分享您的想法...
This is a good question, how to model and enrich your domain. But sooo hard to answer since it vary so much for different domain.
My experince has been that when I started with DDD I ended up with a lots of repositories and a few Value Objects. I reread some books and looked into several DDD code examples with an open mind (there are so many different ways you can implement DDD. Not all of them suits your current project scenario).
I started to try to have in mind that "more value objects, more value objects, more value objects". Why?
Well Value objects brings less tight dependencies, and more behaviour.
In your example above with one to many (1-n) relationship I have solved 1-n rel. in different ways depending on my use cases uses the domain.
(1)Sometimes I create a wrapper class (like your OrderWorkflowHistory) that is a value object. The whole list of child objects is set when object is created. This scenario is good when you have a set of child objects that must be set during one request. For example a Qeustion Weights on a Questionaire form. Then all questions should get their question weight through a method Questionaire.ApplyTuning(QuestionaireTuning) where QuestionaireTuning is like your OrderWorkflowHistory, a wrapper around a List. This add a lot to the domain:
a) The Questionaire will never get in a invalid state. Once we apply tuning we do it against all questions in questionaire.
b) The QuestionaireTuning can provide good access/search methods to retrieve a weight for a specific question or to calculate average weight score... etc.
(2)Another approach has been to have the 1-n wrapper class not being a Value object. This approach suits more if you want to add a child object now and then. The parent cannot be in a invalid state because of x numbers of child objects. This typical wrapper class has Add(Child...) method and several search/contains/exists/check methods.
(3)The third approach is just having the IList exposed as a readonly collection. You can add some search functionality with Extension methods (new in .Net 3.0) but I think it's a design smell. Better to incapsulate the provided list access methods through a list-wrapper class.
Look at http://dddsamplenet.codeplex.com/ for some example of approach one.
I believe the entire discussion with modeling Value objects, entities and who is responsible for what behaviour is the most centric in DDD. Please share your thoughts around this topic...