DDD开篇总结

之前写了两篇《DDD开篇》《DDD应对复杂》,是时候总结一下了

对于DDD的启蒙,不管是国内还是国外思维逻辑都是一样的。或者说如果你想写本关于DDD的书,大纲似乎是一样的

首先DDD是什么?给出定义,定义有些抽象,难以一次性接受,那就通过以往问题引出DDD,这时模型、复杂度、开发流程都是自然附带出的概念,再后面就是DDD的知识结构是什么,最后就是讲解一个实例,也有些会把实例穿插到各个篇章中

在DDD这个系列中,我也打算是这种思路,很平易近人

经过了之前两篇,对于第一部分的DDD是什么?为什么需要DDD基本都问答清楚了。

DDD是什么

DDD根本上是一种软件开发的建模方法论,其中使用了面向对象分析思想,并不是独立于外全新的体系

模型是对现实世界的抽象,那建模是对现实世界的抽象过程,但模型毕竟是模型,不能代替现实,就像类比不能代替问题本身一样。建模过程与建模者的观察视角和对问题的认知有直接关系,所以我们要带着审视的眼光看待模型

软件开发的最大问题之一便是业务人员和技术人员需求某种翻译才能交流,那么模型的质量就取决于翻译的还原度

建模不仅要还原实现世界,更要把重要的东西进行显示化。是一个软件之所以是这个软件的核心

建模可以通过建模=构造块+语法范式表达,各类语言都可以通过这种范式表达出来

(1) 自然语言建模

构造块:常用的那几千个汉字(或者英语的10万单词)

语法规则:主谓宾定状补

(2)计算机语言建模

构造块:加/减/乘/除,if-else, for, while..

语法规则:程序员最熟悉,此处就不说了

(3)过程建模

构造块:函数

语法规则:整个系统描述成一个个过程,每个过程通过函数的层层调用组成

(4)对象建模

构造块:对象

语法规则: 整个系统描述成对象与对象之间的关系

(5) DDD领域建模

构造块:实体/值对象/领域服务/领域事件/聚合根/工厂/仓库/限界上下文

语法规则:就是“构造块”之间的联系(不是很明显,这个需要深入研究。也正是DDD难掌握的地方)

为什么需要DDD

之前介绍过软件复杂度以及应对复杂度之道,DDD是其中一种术

  1. 使领域专家和开发者在一起工作,这样开发出来的软件能够准确地传送业务规则
  2. “准确传达业务规则”意思是说此时的软件就像如果领域专家是编码人员时所开发出来的一样
  3. 帮助业务人员自我提高。没有任何一个领域专家或管理者敢说他对业务已经了如指掌,业务知识需要长期学习过程,在
    DDD中,每个人都在学习,同时每个人又是知识贡献者
  4. 关键在于对知识的集中,因为这样可以确保软件知识并不只是掌握在少数人手中
  5. 在领域专家、开发者和软件本身之间不存在“翻译”,意思是当大家都使用相同的语言进行交流时,每个人都能听懂他人所说
  6. 设计就是代码,代码就是设计。设计是关于软件如何工作的,最好的编码设计来自多次试验,这得益于敏捷的发现过程
  7. DDD同时提供了战略设计和战术设计两种方式,战略设计帮助我们理解哪些投入是最重要的,哪些既有软件资产是可以重新拿来使用的,哪些人应该被加到团队中?战术设计帮助我们创建DDD模型中各个部件

上面的比较学术,简单讲:理解DDD的本质是统一语言、边界划分和面向对象分析的方法

  1. 统一语言,主要思想是让应用能和业务相匹配,这是通过在业务与代码中的技术之间采用共同的语言达成的。也就是设计及代码,代码及设计
  2. 面向对象,DDD核心是领域模型,先找到业务中的领域模型,以领域模型为中心,驱动项目开发,指引我们如何实现面向服务架构或业务驱动架构。领域模型设计精髓在于面向对象分析,对事物的抽象能力,一个领域驱动架构师必然是一个面向对象分析大师
  3. 业务语义显示化,统一语言也好,面向对象也好,最终目标都是为代码可读性和可维护性服务,统一语言使得核心领域概念无损地在代码中呈现,从而提升代码的可理解性
  4. 分离业务逻辑和技术细节,让两个维度的复杂度被解开和分治,比如整洁架构

对于最终目标来讲,在软件项目中,任何方法论如果最终不能落在“减少代码复杂度”,都是有待商榷的

DDD挑战

DDD在实践中有很高的门槛

  1. 持续地将领域专家引入项目
  2. 为创建通用语言腾出时间和精力
  3. 改变开发者对领域的思考方式

最大挑战之一便是:需要花费大量的时间和精力来思考业务领域,研究概念和术语,并且和领域专家交流,以发现、捕捉和改进通用语言

在开发过程中,最大的鸿沟之一便是在于领域专家和开发者之间,通常领域专家关注放在交付业务价值上,而开发者则将注意力放在技术实现上。并不是说开发者动机是错误的,面是说开发者的眼光被自然而然地吸引到实现层面。即使让领域专家与开发者一同工作也只是表面协作,这样在开发的软件中产生了一种映射:业务人员所想的映射到开发者所理解的,软件便不能完全反映领域专家的思维模型,随着时间推移,这种鸿沟将增加软件开发成本

DDD将领域专家与开发人员聚焦在一起,这样所开发的软件能够反映出领域专家的思维模型,这并不意味着我们将精力都花在对“真实世界”的建模上,而是交付最具业务价值的软件,在实用和理想之间存在冲突时,根据它们的互异程序,在DDD中选择实用性

领域专家与开发人员一起创建一套适用于领域建模的通用语言。通用语言必须在全队范围之内达成一致;所有成员都使用通用语言进行交流,通用语言是对软件模型的直接反映

作为开发者,我们都是技术思想者,技术实现对于我们来说并不是什么难事。并不是说技术地思考不好,只是说有时少从技术层面去思考会更好。这么多年来,我们习惯了单从技术层面完成软件开发,那现在是时候考虑一种新的思考方式了。为你的业务领域开发一门通用语言便是一个好的出发点

技术负债

程序员工作时间大部分在新增新功能,996式加班大多为了赶工上线,而对赶工出来的软件质量是在打个问题,而技术负债在软件质量领域是一个很能重要概念,对于软件工程来讲,这真是个特别的东西

Martin Fowler定义技术负债就是增加新功能所需要的额外成本

软件质量不同于其他商品质量。购买一个商品,在使用过程中会直接发现该商品质量问题,而软件质量不是直接被软件系统的使用者所感知的,也就是说客户如果同时使用两种质量不同的系统,用户是无法发现两者的区别,不过随着时间推移,自己的产品交付过程越来越长了

软件质量问题不是直接面向用户,而是面向软件的开发团队。因为软件质量差,新程序员很难快速上手,无法形成生产力;修改别人的代码时可能一走在不得要领;bug丛生,修复一个可能使得系统崩溃,一个都不修复系统反而正常工作;修复bug时牵一动百,修改一处却引起其他连锁故障反应。。。,这些都是软件质量低下的外在表现

正是由于软件质量不是最终用户所能感知的,导致行业内对软件质量没有过多重视–客户都没有提出改进要求,那么一切为客户服务的软件公司自然没有动力去提升软件质量,而且行业内对软件质量存在认知误区:便宜确实没好货,但是质量高必然导致成本 上升,而客户又不会察觉质量好坏,那么产品如何卖出好价格

软件并不是质量越高,成本就越高。这似乎违反常识,背后其实也与技术负债有关。如果将技术负债看成是一种前进中的累赘,累赘遍布于代码各处,那么提高软件质量就是通过良好设计或重构来减轻这种累赘,从而能轻装上阵,新增功能就能更加快捷,交付效率也会大大提升。

降低技术负债意味着软件质量提高,软件质量越高,修改拓展起来就越方便。

如何降低技术负债?这存在一个适度问题,代码越多,复杂性越高,技术负债肯定越高,那么就需要惜墨如金。有时为了写正确可运行的简洁代码,可能要删除数十倍的代码,但也不是代码越少越好。有的代码只是考虑功能实现,没有考虑到功能的对接或扩展,那么当需要对功能实现扩展时,就发现难以下手,甚至需要采取黑客破解方式强行入侵系统,这此都是原来代码过于简单僵化的表现

适度是在过度和不足中探索平衡的结果。代码适度的一个衡量标准是单一职责原则,即每个函数或类只能有一个职责。

面向对象编程中还有另一个原则:DRY原则。对这个原则的共同理解是代码不应该重复,如果两段代码表示的是同一个职责,那么合并它们。但这种抽象合并导致共享内核或共享库,最张造成代码各处对共享库或内核的依赖,这就很自然地引入了不必要的、偶然的复杂性–一旦共享库发生修改,牵一动百的事情就可能发生。很多时候重复的代码可能会带来相当大的优势,重复能拖延决策,这是软件开发的黄金。这样,延迟到适当时机从多个专业化角度重构,这比从单个方法层面进行抽象的重构要容易数倍。

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