领域驱动设计模式的收益与挑战

《软件学报》在2021年第32卷第9期刊登了一篇论文:《领域驱动设计模式的收益与挑战:系统综述》。这篇论文是学术界在这一领域开山之作。

论文是对2003~2019年之间发表的相关文献进行识别、筛选、汇总和分析。

揭示DDDP的应用情况,即哪些DDDP被应用到了软件开发中,以及其所带来的收益、挑战及相应的缓解挑战方法。

对于长期在DDD中折腾的人,值得一读。

一是可以看看学术界的研究成果

二是对比自己实践,是否在康庄大道上

如果你对学术性论文不感兴趣,可以仔细阅读这篇文章,我对论文做些简单摘抄,对比一下自己实践感悟

基本介绍

论文先对DDD的一些概念、特性作了介绍

定义:

DDD是一种软件设计中应该遵循的思维方式,其目标在于加快具有复杂需求的软件项目的研发速度

理论:

通过构建领域模型来解决软件开发的复杂性问题。因为在大多数软件项目中,最困难的往往是解决业务领域复杂性,而非技术复杂性

特征:

设计与开发的绑定,DDD强调软件设计概念必须在开发过程中得以成功实现

DDDP:

DDD方法中,将一组设计实践、技术和原则合并为标准模式,即所谓的领域驱动设计模式(domain driven design pattern,简称DDDP)

基本原则

  • Evans强调设计概念必须在代码中成功实现,否则它们将会变成抽象的讨论。DDD通过引入模型驱动设计建模范式及其构造块,弥补模型与可运行软件之间的差距
  • DDD提倡迭代开发,领域驱动设计与具体实现过程间紧密关系,使得DDD比其他软件设计方法更具实用性
  • DDD追求领域模型需要依靠头脑风暴的创造性和对领域的深入了解,因此在实践过程中,开发人员与领域专家之间需要展开紧密协作
  • DDD是一种软件设计方法,而任何设计出来的领域模型都应该与架构无关。也就是除了领域模型,在软件开发过程中仍然需要架构设计,比如微服务架构或六边形架构

DDD设计模式概览

DDD由Evans作为一种大型模式语言引入,其由一组相互关联的模式组成。

模式语言提供了讨论问题的交流术语,它定义了特定场景、特定问题的解决方案,其主要目的是帮助开发者解决在设计和编程中遇到的通用问题。

模式语言在软件工程中被广泛地应用,比如设计模式、企业架构模式等。

DDD与DDDP的关系,正如同OOD与面向对象设计模式的关系。

对于DDD,最基本的模式是通用语言,它是一种供不同涉众(如开发人员和领域专家)共同使用的语言,主要用来辅助领域建模,,

一种通用语言只适用于单个限界上下文,后者作为一个电焊工的模型边界来维护模型的完整性。

根据Vernon的观点,除了通用语言之外的DDDP,要么属于战略设计模式,要么属于战术设计模式。

战略设计模式

旨在应对具有多个领域模型的大型软件开发项目的复杂性,其中,每个领域模型都属于单独的限界上下文。

限界上下文以外的其他战略设计模式关注如何管理不同限界上下文之间的关系

比如上下文映射负责描述不同领域模型间的通信,而职责分层则站在更高的抽象层级来组织不同领域模型间的概念依赖关系

战术设计模式

负责根据通用语言对单个限界上下文进行领域建模,并结合面向对象原则绑定领域建模和编码实现。包括实体、值对象、聚合、服务、资源库等。

实体和值对象用于对具有不同领域特征的领域对象进行建模;

聚合将一组领域对象绑定为一个整体,以控制事务;

服务则充当领域模型接口,具有无状态特点;

资源库用于封装领域对象的数据库访问操作


感悟

对于基础信息的介绍,可以说基本是符合当前DDD的理论知识,只是表述方式有所差异。但鉴于每个人认知差距,可能抓住的重点信息不同,从我个人认知角度,我来点评一下:

首先是定义,论文指出DDD是一种思维方式

这是种很新颖的定义。在DDD系列文章中,我们也去追寻过DDD定义。但这种定义是第一次听说。

软件设计中最困难的是什么?

论文指出是解决业务领域复杂性,而非技术复杂性。

这个应该会随着软件复杂性越来越高,人们的认知会越来越深。现在技术人员还是过于看重技术,甚至对技术驱动业务深信不疑。现实是怎么样?现在工具人的流行说法已经足以说明,驱动业务是少见的,而跟随业务是常态,成就业务已经了不得

为什么瀑布模型不适合软件行业,就因为隐藏的业务知识太多。不可能一次性就把所有业务知识提取出来,而且在软件开发进程中,业务可能还在变化中发展。

借助敏捷中迭代式开发,一次次与领域专家交流的深入,才能慢慢挖掘出隐藏在业务知识中的复杂性。

而DDD正是通过模型去捕获领域知识,对领域复杂性进行简化和提炼。

所以整合起来看,DDD是一种迭代改进试错法,还不知道什么时候该停止,甚至停止的时候你也不知道得到的到底是垃圾还是宝藏。

设计与开发绑定

这一点,是相当重要。是DDD与别的分析方法重要区别。

为什么DDD如此流行,可能跟很多技术大词一样,正如之前在中台文章所说,可能是应激者怕掉队,也可能是投机者想上位,很多人还是把它当成一种分析方法。

如果只是一种分析法,我们之前使用的ER分析,OOA,都已经够用了。

对于现流行说的DDD帮助微服务划分,那只是DDD中界限上下文这一个点,而且服务划分也不能只考虑领域界限,还有其它因素。

因此需要多思考,为什么需要DDD,DDD到底有什么独到之处?

我个人认为理由在Evans著作中提到的知识消化。学习者过多的精力放在了战术部分,什么是实体、领域服务、repository等等这些元素上。

在编程实践中,我们希望实实在在的用上DDD元素,才表示我们是在进行DDD,而其实没有DDD,对OO的深刻理解,充血模型是自然而然的。

然而,如果没有DDD战略部分,只有DDD战术元素,那只是DDD编码风格,而编码风格,没有高低之下,贫贱之分。

何为知识消化?我特此画张图:

业务方与技术方沟通业务需求,在交流中,对部分业务知识达到共识,这部分交流语言被标准化为统一语言;

在不断地交流中,对于双方达成共识部分,凝炼成到模型中,对模型review,以确定描述了业务实际情况,发现缺乏或不适当概念时,进行修正,指取新的统一语言;

当模型确认后,以模型为样本,使用代码实现它;

上面是正向流程,技术方在重构代码时,也会同步修改模型,进来提取出新的统一语言,反哺业务方。

通过正逆流程,达到修改统一语言就是修改模型,修改模型也就是修改代码;修改代码也是修改模型,修改模型也相继修改统一语言。

这样打破了知识壁垒,给予业务方与技术方一种更好的协同方式。这就是DDD的精髓。让分析模型与实现模型融合了,不再像以前的方法一样分裂。


研究结果

如上图所示,应用DDDP的相关活动主要分为4类:领域分析、领域设计、领域模型实现和普适性活动。

领域分析:与领域专家一起探索领域知识的过程。经过领域,将得到初始的领域模型;

领域设计:指将模型分成不同部分(每个部分对应着独立的限界上下文),然后扩展和细化每个限界上下文的过程,以此为开发实现做准备

领域模型实现:将模型转换为可运行代码,这一过程还通过检查模型为模型设计提供反馈

普适性活动:在应用DDDP时,可能在领域分析,领域设计,领域模型实现这3个阶段都会发生的模切活动,比如构建和更新通用语言

应用情况

在基础研究集合中,出现频次到达3次以上的DDDP,以及对应的描述和提及这些模式的研究文献

这些模式出现的频次并不平衡,战术设计模式被提及的频次明显高于战略设计,表明开发人员更容易注意到领域驱动设计的战术设计模式。

总体而言,目前只有31.1%的DDDP在基础研究中得到探讨,这也表明当前学术界对DDDP的研究存在不足。

应用DDDP的收益

下图展示了应用DDDP所带来的收益在领域分析、领域模型实现以及普适性活动中的体现情况

对每个阶段带来的收益细节详述一下

领域设计

应用DDDP收益在于使各个领域之间依赖关系更加明确,上下文映射和职责分层用于组织系统的不同部分:

前者表示不同限界上下文之间的关系,每个上下文表示一个特定的领域;

后者根据领域对象职责,将它们组织成具有清晰依赖关系的层次结构

帮助开发人员更加深入地了解系统,降低认知复杂性,有助于分析系统架构

领域模型实现

应用DDDP有助于领域模型的落地实现。

普适性活动

可以提升软件架构的质量属性,如可维护性、可扩展性、可重用性和可测试性等

应用DDDP的挑战

下图列出了在领域分析、领域设计、领域模型实现和普适性活动中,应用DDDP可能面临的挑战以及相应的缓解方法


感悟

可以看出论文对DDDP应用的收益和挑战阐述得很详细。在现实实践中,挑战远比论文中提到的还要多。我觉得主要是两方面:

一是对理论研究的不够深入,没有系统性学习

二是过于关注战术问题,不深入战略部分而不知所以然,又对OO的理解不深入使其难以落地,从而抱怨DDD

对于第一条

1、从个人学习者角度,只能自己多看看市面上已经出版的书籍,碎片化时间系统性学习,而不是随便看看几篇文章,就以为理解DDD了,现在DDD就像个筐,什么东西都在往里装,就算是Evans开山之作,也有很多时代局限性;

2、从团队角度讲,不要奢求团队每个人都去理解DDD,毕竟它的本身门槛就高,作为TL,需要自身内化DDD,制定规范,团队执行就可以,向有兴趣的同学传输背后理论。

对于第二条

3、除了需要系统性学习外,要明白DDD精髓与DDD编码风格是两码事,在实践DDD过程中,也带有个人经验特征,不仅要有自我理论作为背后支撑,也要认识到不是使用了战术元素,我们就是DDD了,而是要有DDD的知识消化过程。

总结

软件工程中是“没有银弹”的,任何理论方法都会存在一定的局限性和缺点,DDDP也是如此。因此应用各种DDDP带来的局限或者挑战,仍需要未来进一步探索和反思。

也希望我的感悟能帮助到你,如果有兴趣可以再看看论文原稿。对于高阶程序员来讲,困难的不是能不能干出来,而是怎么干才舒坦。

公众号:码农戏码
欢迎关注微信公众号『码农戏码』