如何使用DDD中的大型Domain类?

时间:2012-09-30 21:43:41

标签: domain-driven-design

当您开发OO / DDD风格的架构并对某个域实体进行建模时,例如订单实体您将与订单相关的整个逻辑放入订单实体。 但是当应用程序变得更加复杂时,Order实体会收集越来越多的逻辑,而这个类变得非常庞大。 与贫血模型相比,是的,它显然是反模式,但所有巨大的逻辑在不同的服务中分开。

处理大型域名实体或我理解错误是否可以?

3 个答案:

答案 0 :(得分:8)

当您尝试创建富域模型时,请将实体集中在身份和生命周期上,从而尽量避免它们因属性或行为而变得臃肿。

域服务可能是放置行为的地方,但我倾向于看到许多域服务方法具有更好地分配给值对象的行为,因此我不会通过将行为移动到域服务来开始重构。域服务倾向于在连接到当前域模型之外的事物(即屏蔽基础结构问题)之前作为直接的外观/适配器工作得最好。

您还可以将行为放在应用程序服务中,但要问问自己该行为是否属于域模型之外。作为一般规则,尝试将应用程序服务更多地集中在跨越实体,域服务和存储库的编排式任务上。

当遇到膨胀的实体时,首先要做的是寻找一组具有凝聚力的实体属性和相关行为,并通过将这些隐式概念提取到值对象中来使这些隐式概念显式化。然后,实体可以将其行为委托给这些值对象。

由于我们都倾向于对实体更加满意,因此尝试更偏向于价值对象,这样您就可以获得价值对象提供的不变性,封装和可组合性的好处 - 让您转向更柔顺的设计。

值对象使您能够将更多功能样式(例如,无副作用的函数)合并到域模型中,从而使您的实体免于处理将复杂行为添加到管理身份负担的复杂性和生命周期。有关详细信息,请参阅Eric Evan的http://domainlanguage.com/ddd/patterns/和蓝皮书中的实体和值对象的模式摘要。

答案 1 :(得分:6)

  

在开发OO / DDD样式和建模的架构时   一些域实体,例如您正在整理逻辑的订单实体   与订单实体的订单相关。但是当应用程序成为时   更复杂的是,Order实体收集的逻辑越多越好   上课变得非常庞大。

容易变得庞大的类通常是具有重叠职责的类。 订单是一个典型的类,可能有多个职责,可以在您的应用程序中扮演不同的角色。

鉴于上下文出现订单,它可能是具有可变状态的实体(即,如果您正在管理订单的商业条件) ,在协商阶段<​​/ em>期间,但如果您的应用程序正在管理物流,那么订单可能会扮演不同的角色:不可变的值对象可能是后勤环境中最好的实现。

  

与贫血模型相比,是的   显然是反模式,但所有巨大的逻辑都被分开了   不同的服务。

...和分离是一件好事。 : - )

我感觉原始模型可能是以数据为中心的,并且用于不同目的的数据(订单创建,付款,订单履行,订单交付)堆积在同一个容器(Order类)中。不能从这里说出来,但这是一个非常频繁的模式。并非所有这些数据都可以同时用于同一目的。

通常,像你所描述的那样臃肿的类是有界上下文之间缺少分离的气味,和/或在同一内容中不完整的聚合分离有限的背景。我想看看:

  • 一起改变的事情;
  • 出于同样原因而改变的事情;
  • 履行行为所需的信息;

并尝试相应地重新定义聚合边界。还有:

  • 申请的不同目的;
  • 不同的利益相关者;
  • 不同的隐式模型/语言;

当涉及到发现所涉及的背景时。

在大型应用程序中,您可能拥有多个模型,从而导致单个域概念的多个表示形式,至少对于扮演多个角色的概念而言。

这是保罗方法的补充。

答案 2 :(得分:3)

在DDD中使用服务很好。您通常会在域,应用程序或基础架构层看到服务。

Eric在他的书中使用这些指南来发现何时使用服务:

  • 该操作涉及的领域概念不是ENTITY或VALUE OBJECT的自然组成部分。
  • 界面是根据域模型中的其他元素定义的
  • 操作无状态