天天看点

DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结

参考资料

  • Domain-Driven Design: Tackling Complexity in the Heart of Software

前言

领域驱动设计是一个传播非常广泛的名词, 笔者对这个概念听闻很早,但是一直也没有提起太大的兴趣去学习, 愿因很简单, 因为它属于一种工程设计思想, 解决的问题不够标准具象, 其内在价值存在争议.

但无奈工作中恰恰就有一个公司内部自建的 “中台化解决方案” 的框架, 号称运用了 DDD 的思想, 虽然笔者不太认同, 但是也要先学习才能有发言权 。

虽然市面上充斥着各种博文,教程都说 Eric Evans 的原书偏概念, 缺乏实现细节. 所谓”取法乎上,得其中“, ”取法乎中, 得其下“ , 为了真正弄清楚DDD 的核心价值到底在哪, 笔者选择了阅读 Eric Evans 的原书, 真正阅读完毕后发现:

  • 事实恰恰相反, DDD 原书非常接地气, 而那些所谓解读 DDD 的博客或者教程才是将 DDD 概念抽象化的罪魁祸首
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结

所以本篇文章旨在将 DDD 原书中的一些核心思想简单地传达出来. 希望可以帮助一些感兴趣的初学者. 笔者会尽可能引用书中的原话来传达自己的观点, 涉及到概念定义的, 会同时引用英文. 避免一些 DDD 的信徒口诛笔伐, 攻击笔者没有真正理解 DDD .

读者也推荐所有有意学习 DDD 的人, 一定要以 Eric Evans 的原书为参考资料进行学习, 避免二手教程的曲解与误导.

  • 常见的误解: 领域驱动设计需要应用充血模型

什么是领域

既然是 “领域驱动设计” , 这6个字里面显然核心是 “领域” , 那第一个要搞清楚的问题就是"领域" 的定义是什么. 既然 Eric Evans 提出的概念, 必然要以原书的内容为准.

Every software program relates to some activity or interest of its user. That subject area to which the user applies the program is the domain of the software. Some domains involve the physical world: The domain of an airline-booking program involves real people getting on real aircraft. Some domains are intangible: The domain of an account- ing program is money and finance. Software domains usually have lit- tle to do with computers, though there are exceptions: The domain of a source-code control system is software development itself.
每个软件程序是为了执行用户的某项活动,或是满足用户的某种需求。这些用户应用软件的问题区域就是软件的领域。一些领域涉及物质世界,例如,机票预订程序的领域中包括飞机乘客在内。有些领域则是无形的,例如,会计程序的金融领域。软件领域一般与计算机关系不大,当然也有例外,例如,源代码控制系统的领域就是软件开发本身

上面这段定义很长, 有点抽象, 但是相信每个读者都能理解, 这里的领域其实说的就是软件应用的 “业务领域”.

  • 有趣的是, 这个概念粗一看很高级, 但是你仔细想一下, “业务” 驱动设计, 这不是一个常识吗…恐怕很难找出一个不被业务驱动的设计吧. 所以这个定义并不是领域驱动设计的核心所在. 我们继续顺着原书挖掘一下
为了创建真正能为用户活动所用的软件,开发团队必须运用一整套与这些活动有关的知识体系。所需知识的广度可能令人望而生畏,庞大而复杂的信息也可能超乎想象。模型正是解决此类 信息超载问题的工具。模型这种知识形式对知识进行了选择性的简化和有意的结构化。适当的模型可以使人理解信息的意义,并专注于问题。
  • 上面这段话清晰地解释了, 由于"业务领域" 的知识太过庞大, 在指导软件设计时, 我们需要对齐进行提炼和精简, 建立一个所谓的模型来指导设计开发. 而 DDD 的真正价值就是在描述该如何建立这个能够指导开发的 “领域模型” , Domain-Driven Design 其实是一种简称, 其真正想表达的是 Domain Model Driven Design, 即领域模型驱动设计

领域模型 – 业务知识的压缩表达

领域模型是书中第二个重要的概念定义, 可以看一下原话.

A domain model is not a particular diagram; it is the idea that the diagram is intended to convey. It is not just the knowledge in a domain expert’s head; it is a rigorously organized and selective abstraction of that knowledge. A diagram can represent and communicate a model, as can carefully written code, as can an English sentence.
领域模型并不是某个模型图,而是这种图所要传达的思想。它绝不单单是领域专家头脑中的知识,而是对这类知识严格的组织且有选择的抽象。图可以表示和传达一种模型,同样,精心书写的代码或文字也能达到同样的目的。

上面这段话其实非常重要, 它强调了领域模型并不拘泥于形式, 重要的是它能够传递经过提炼后的业务知识的抽象与精炼. 它可以是一副图,也可以是一段代码, 甚至可以是一句话.

  • 这是一个很重要的观点, 但很可能许多 DDD 学习者并不会留意,乃至误解为领域模型一定需要是一个标准的建模方式例如 UML 绘制出的复杂方案

理清上面这一点以后, 相信细心读者都会产生疑问, 这不还是玄学吗? 凡事一旦上升到思想高度, 必然千人千面. 但实际不是.

领域模型这个概念强调的是业务知识的提炼与抽象, 可能有一些读者不明白业务知识有什么好抽象的, 主要原因是很多程序员所开发的软件业务领域还不够复杂, 领域知识不够密集, 相信看如下原书中的这个举例, 很多人立刻就能明白, 到底为什么要构建一个 “领域模型” 了

领域建模举例- PCB印制电路板设计软件

相信第一眼看到 PCB 这个概念, 很多程序员是懵逼的, 并不知道硬件电路设计软件要怎么设计, 至少我是懵逼的, 大学的硬件电路知识都快交回给老师了, 唯一残存的一些概念可以支撑自己不对这个 PCB 望而生畏.

  • 这个例子非常精妙地体现了领域知识对于指导软件设计的作用, 如果你对一个领域的知识完全不了解, 你根本不知道从何入手去设计这个软件. 而我们日常所熟悉的电子商城,支付, 社交类软件, 其领域概念非常生活化, 以至于似乎都感知不到领域知识的存在,每个程序员一上手都能展开设计

Eric Evans 也没有硬件知识储备, 所以它需要先和 PCB 专家沟通学习. 这个过程我放几张原书截图, 读者就能直观感受到建模过程, 理解为什么需要领域建模

  • 首先经过多次沟通, 发现有一个术语 net 经常用到, 在这个领域, net 是一种导线,可以连接 PCB 任意数量的原件
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
  • 然后尝试画一个符合软件概念的图例来尝试表达与专家沟通
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
  • 这个例子非常棒的一点在于, 它还恰好反映了术语存在冲突和混淆的情况, 例如 Component 在软硬件中都有其各自的含义, 这导致了沟通障碍, 通过与领域专家持续地讨论与学习后, 程序员可以与领域专家统一术语, 形成 Ubiquitous Language, 进一步细化精确模型
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
  • 进一步讨论, 得知 PCB 专家期望通过软件来计算"电路跳数"
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
  • 继续讨论细化模型
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结
    DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书参考资料前言什么是领域领域模型 – 业务知识的压缩表达领域建模举例- PCB印制电路板设计软件领域建模小结

领域建模小结

从上面这个过程中我们可以看出, 领域建模的核心其实是对业务知识的消化与提炼, 将其转化为可以被软件表达或者模拟的形式. 上面部分截图中的讨论, 其实程序员都会有很切身的体验, 这在与业务人员或者产品经理的沟通中其实很常见. 双方需要对一个概念达成统一 , 用于沟通业务规则如何去实现.

这进一步反映了, 领域驱动设计其实不是什么高深的概念, 绝大多数开发者即使没有专门学习过领域驱动设计, 其实也不可避免地在应用着 DDD. 当然本文至此只是简单介绍了 Eric Evans 所描述的 DDD 的核心思想:

  • 领域建模
  • 通用语言构建

更多具体的关于如何进行领域建模的细节, 也是 DDD 这本书的核心内容所在. 感兴趣的同学可以自行阅读原书, 笔者也会另开文章整理总结. 但是相比这些术层面的内容, 更为重要地是理解 DDD 所要解决的问题.也就是 DDD 被提出来的目的.

否则, 甚至会产生领域驱动设计就是运用"充血模型" 这种错误的理解, 原书其实都单独强调了: 充血模型和贫血模型都可以用于领域驱动设计.

Then there are those aspects of the domain that are more clearly expressed as actions or operations, rather than as objects. Although it is a slight departure from object-oriented modeling tradition, it is often best to express these as SERVICES, rather than forcing responsi- bility for an operation onto some ENTITY or VALUE OBJECT.
领域中还有一些方面适合用动作或操作来表示,这比用对象表示更加清楚。这些方面最好用 SERVICE来表示,而不应把操作的责任强加到ENTITY或VALUE OBJECT上,尽管这样做稍微违背了 面向对象的建模传统。SERVICE是应客户端请求来完成某事。在软件的技术层中有很多SERVICE。 在领域中也可以使用SERVICE,当对软件要做的某项无状态的活动进行建模时,就可以将该活动 作为一项SERVICE。

继续阅读