停止教条式的领域驱动设计 - CodeOpinion


领域驱动设计的主流思想是关于实体、值对象、聚合、存储库、服务、工厂……各种技术模式。因此,大多数人认为他们不需要领域驱动设计,因为这对他们的领域来说很复杂。
为什么你需要所有这些“东西”?好吧,也许你不需要!
在一个大型系统中,如果您正确使用存储库模式,建模您的领域、定义边界以及它们之间的关系远比关心您自己重要得多。
 
边界对我来说可能是领域驱动设计中最重要的方面。但是,您将在网上找到的关于 DDD 的绝大多数内容或讨论都围绕着战术模式:实体、值对象、存储库、服务、聚合等。虽然战术模式具有价值,但它们必须在理解使用有界上下文定义边界的概念和价值之后出现。虽然有界上下文确实得到了领域驱动设计爱好者的很多关注,但它并不是人们在教程或“示例”应用程序中首先被介绍的内容。
 
以下是我看到的与领域驱动设计最相关的一些评论和问题:

  • DDD 仅在您的业务逻辑复杂时才强大

虽然我同意复杂性是一个驱动因素,但我也认为在处理更大的系统时它对我帮助最大。来自领域的复杂性以及来自大型系统的复杂性。
  • 在 DDD 中,您应该使用存储库模式。

您需要使用工厂来创建实体或值对象。
  • 您的实体中没有逻辑,因此这是一个贫血的域模型,这是一种反模式。

如果您认为自己已经有了领域模型,但实际上拥有包含事务脚本的数据模型,那么这只是一种反模式。随着您对问题的理解不断发展,从这一点开始并转向更丰富的领域模型并没有任何问题。
  • 领域模型中不能有依赖项

人们不遗余力地避免在他们的领域模型中存在依赖关系。虽然再次避免依赖是一个很好的做法并且值得努力,但有时您实际上需要依赖。使用Double Dispatch还不错,因为您将依赖项传递给方法,并且有人告诉您所有依赖项都必须通过构造函数注入。
 
教条领域驱动设计
我认为上述所有问题都忽略了领域驱动设计的好处。只关心战术模式是一种教条的DDD
对我来说,领域驱动设计是关于理解你的领域、语言、其中不同人的背景上下文( 上下文为王 )、问题和解决方案空间,并尝试对其进行建模。而且一开始你不会做对,因为在你获得的洞察力的基础上迭代构建需要时间。
像聚合这样的战术模式(这是一个一致性边界)是有价值的但这不应该是重点。仅仅因为你有存储库、聚合、实体,并不意味着你在做领域驱动设计。你只有一堆模式。
 
统一语言与术语
我发现语言是理解边界和定义系统内有界上下文的好方法。一个很好的例子来自康威定理的Mel Conway。

当一个政客用“你好吗?”和一个护士用“你好吗?”来问候你时,他们是完全不同的问题,尽管他们的发音和拼写都是一样的。

这说明机器翻译有什么意义?

根据您在域中与谁交谈,根据他们所在的子域或他们所扮演的角色,他们可能有不同的上下文。
正如 Mel 所指出的那样,上下文对语言和意图的使用方式很重要。
例如,在运输货物/货物的运输公司中,有多个子域。招聘是招聘司机,确保他们拥有适当的执照、合规性等。运营部门关注实际发货以及取货和交付的货物。
两者都有车辆的概念。但两者对车辆是什么都有非常不同的关注和观点。他们使用相同的术语“车辆”,但根据他们的上下文,对对我来说重要的事情有非常不同的看法。
在招聘中,车辆的概念可能由驾驶员(称为所有者操作员)拥有。他们可能关心车辆安全要求和其他合规性。运营部门关心车辆的可用性以及它是否可以在给定时间进行特定的运输。非常不同的担忧。
 
领域发现
起初,您没有房间实际外观的心理模型。当你慢慢地在房间里闪烁灯光时,你会得到一个更好的关于天花板有多高、房间的形状、地板上有什么的心理模型。当你发光时,你的理解会慢慢增长。
理解域的边界需要付出努力,并且是能够理解问题和解决方案空间的关键。这是领域建模的关键。
 
领域驱动设计
标题说明了一切。这不是模式驱动设计,而是领域驱动设计。不要陷入专注于战术模式的教条多数派。再次,是的,它们很有价值。聚合设计是定义一致性边界的好方法。我不是在贬低模式,但这不是重点。模式是达到目的的手段。