Skip to content

07 领域建模原理:DDD领域建模和传统方法有什么区别?

你好,我是钟敬。

前面几节课,我们一起完成了行为需求和领域建模,重点在于实践。但是,如果仅停留在实践层面,不去了解背后的原理,我们就会知其然而不知其所以然,最终还是不能很好地进行实践。

所以,在对领域建模有了一定的感性认识以后,今天我们上升到理论层面,一起来理解模型驱动设计的本质含义。然后再来深入探讨“统一语言”,以及它和领域建模的关系。

什么是领域模型?

在讨论什么是领域模型之前,咱们先说说什么是模型。

先来看几个例子。比如说你去买房,售楼处都会有一个沙盘模型,这样你就可以看到楼的外观、朝向、周边环境等等。

但是如果要盖这个楼盘,靠沙盘模型就不行了,需要有一套详细的建筑图纸,图纸也是模型。为了对大楼进行设计,还要进行各种计算,计算用的公式也是模型,称为数学模型。另外,小孩玩的玩具车、玩具枪什么的,也是模型。事实上,现代生产和生活中,充满着各种各样的模型。

从这些例子里,咱们可以发现模型的几个共同特点。

首先, 模型是以解决特定问题为目的的。例如沙盘模型是为了卖房,而建筑图纸是为了盖楼。没有目的就谈不上模型。

第二, 模型都是对现实世界或人们思维中的事物进行的模拟。例如沙盘模型和建筑图纸都是对建筑物的模拟,而玩具车是对真车的模拟。

第三, 模型总是提取了被模拟事物中的部分信息,而忽略掉了其他大部分信息。例如,沙盘模型提取了楼盘的外观信息,但是忽略了内部结构和建筑材料信息。而建筑图纸反映了内部结构信息,但忽略了外观信息。到底提取哪些信息,忽略哪些信息,取决于模型的目的。

第四, 模型可以有多种表现形式,例如图纸、影像、公式以及电脑中的文件等等。具体采用哪种形式,取决于要解决的问题和当前的技术水平。

最后,模型是一种 人造物,大自然本身是不存在模型的。

软件开发是一个建模过程

说到这儿,不知道你发现了没有?其实计算机软件也是一种模型。这是因为,计算机软件也是为了满足业务需求,对现实世界的事物和逻辑进行的模拟。所以,我们开发计算机软件的过程也是一个建模过程。

软件本质上是运行在机器上的一串二进制流,我们姑且称之为“机器模型”。我画了一张图,表示了现实世界和机器模型之间的关系。

我们看到,在机器模型和丰富多彩的现实世界之间存在着巨大的鸿沟,所以,用二进制直接为现实世界建模是非常困难的,这也是软件开发如此困难的原因之一。

那么,如何克服这一障碍呢?打个比方,假如我们想爬到房顶上去,太高了上不去怎么办,那就搬个梯子,一步一步地爬上去。

软件开发的道理是一样的。可以把由现实世界到机器模型的过程分成几步,一步一步地走。传统软件工程中,从现实世界到机器模型的过程,一般是这样的:

第一步是捕获行为需求,研究为了满足业务需求需要有怎样的流程和功能,可以用传统的用例分析来做,也可以用咱们这里的事件风暴。

第二步是分析,在行为需求的基础上,对现实世界中领域知识或者说业务概念进行分析和提炼,形成分析模型。尽管分析模型反映的仍然是业务概念,然而是经过抽象得来的,更加严谨、精练和一致,因此比行为需求更加接近实现。

第三步是设计,在分析模型的基础上,增加技术关注点,进行架构设计、详细设计、数据库设计等,形成设计模型。设计模型介于分析模型和代码之间。

第四步是编写代码。代码经过编译后,就成为了运行在机器上的“机器模型”了。

其实,第二步中的分析,就是对领域知识的抽象和提炼的过程,所以分析模型也可以称为领域模型,这个过程也可以叫做领域建模。

但是,很多伙伴在开发软件时,并没有经过领域建模这一步,而是直接进行设计和编码。如果是简单系统的话还可以,如果是复杂系统,就会出现很多问题了。

DDD领域模型与传统方法的不同之处

看到这儿你可能会问了,既然传统软件工程也有领域模型,那DDD的领域模型与传统的方法又有什么不同呢?

这两者之间有一个重要区别: DDD强调领域模型要兼顾业务和技术两个视角。

在传统软件工程里,建立分析模型强调完全从业务领域出发,不考虑技术视角。然后,才会把分析模型交给技术专家,转化为设计模型。两者的关系如下图:

这种方法虽然在理论上是完备的,但实践中常常会有问题。由于在分析阶段没有从技术视角考虑,那么在转化为设计模型的时候,就可能发现有些分析模型很难实现,需要通过复杂的转换,才能适应软件开发的要求,因此两种模型之间就产生了比较大的差距。

所以,在之后的开发过程中,开发人员往往只是聚焦于设计模型,而将分析模型束之高阁。时间久了,分析模型与系统实现之间的差异越来越大,也就失去了存在的意义。最终,技术实现与业务越来越远,软件系统也就难以真实反映业务需求了。

但是,DDD的领域模型则是 业务视角(原来的分析模型)和技术视角(原来的设计模型)的交集。 它反映了业务人员和技术人员的共识。

尽管技术人员仍然要为领域模型增加实现细节,形成设计模型,但设计模型必须严格遵循领域模型。对领域模型的修改,必须由业务和技术双方达成一致。这样,就避免了传统软件工程中分析模型和设计模型相互割裂的风险,如下图:

为了表达DDD的侧重点,我们把传统的软件开发过程修改为下面这样:

在这个图中,我们直接用领域建模代替了原来的分析步骤。同时,把原来的设计和编码合并成了模型的实现,这是因为,从敏捷的角度来看,设计和编码常常会融合在一起。

模型驱动设计

围绕领域模型进行开发的方法,在DDD中称为 模型驱动设计(Model-Driven Design),是DDD的核心模式之一。这个模式可以概括为两点:

  • 领域模型要和业务需求一致;
  • 系统实现要和领域模型一致。

领域模型要和业务需求一致

首先我们来看看领域模型和业务需求一致。

DDD非常重视对业务需求中领域知识的消化。虽然我们从事件风暴就开始消化了,但领域建模才是消化知识的核心。在这个过程中,事件风暴里遗留的不清晰的部分会得到解决,并且还会发现新的知识。

事实上,事件风暴和领域建模有一个重要的区别:事件风暴仅仅追求“形似”,也就是说 业务是怎样运作的,事件风暴就怎样反映

而领域模型不仅要和需求“形似”,更要“神似”。也就是说, 领域模型不仅要对业务进行直观模拟,更要经过提炼,形成浓缩的知识

什么意思呢?这里主要是指两点,

第一点,是通过抽象思维得到更“深刻”的模型。 比如说,我们从企业、开发中心等概念中抽象出组织和组织类别,从人事人员、销售人员中抽象出岗位等等。这使模型中的知识不再停留在业务的表面,而是深入到业务的本质,有利于开发出更加灵活简洁的系统。

第二点,是通过深入思考得到更“丰富”的模型。 比如说,我们通过分析“取员工上级”的操作,识别出了员工和组织之间关于组织负责人的关联。另外,作为领域知识的一部分,我们还补充了更多的业务规则,这些都使模型更加丰富。蕴含丰富知识的领域模型,可以让我们在开发的时候不容易遗漏重要的领域概念和规则。

另外,领域模型和业务相一致,必须通过业务人员和技术人员的协作才能完成。业务人员的参与,能为领域模型带来专业的领域知识,而技术人员可以为领域模型带来更高的抽象性和严谨性。

而且,技术视角的加入还为领域模型的选择提供了参考。前面我们说过,模型是一种人造物。既然是人造的,就会带入主观因素,对于同一业务,可能会构建出不同形式的领域模型,这些模型可能都“对”,关键在于哪一个“更好”。这时候,技术人员从技术视角出发,往往可以发现,有些模型更容易进行技术实现。所以,尽管领域模型中都是业务概念,却可以通过技术视角选出更恰当的模型。

系统实现和领域模型一致

模型驱动设计的第二个要点是系统实现和领域模型一致。

如果修改了领域模型,那么系统实现必然也要修改;反之,如果系统实现发生了变化,也很有可能导致模型的变化。

这背后还隐含了一个推论: 领域模型中的每个元素,都应该通过某种方式在系统实现中有所体现。反过来说,如果发现领域模型中的某个元素不需要落实到实现里,那么就应该在领域模型里删除这个元素。这也是技术人员参与到领域建模中的一个原因。

根据领域模型进行系统实现的具体技术,我们在会后面的课程中介绍。

领域模型和业务需求一致、系统实现和领域模型一致,最终结果就是系统实现和业务需求总是一致的,避免了系统实现和业务需求差距越来越大,这个老大难问题。

领域模型与统一语言

除了模型驱动设计以外,DDD中的另一个核心模式是统一语言(Ubiquitous Language)。

统一语言包含了两个层面的含义:一是业务和技术人员之间的语言是统一的,二是开发团队内部各角色之间的语言是统一的。最终结果就是每一行代码都能对应到统一语言,从而与业务保持一致。你可能已经发现了, 统一语言和领域模型的目的是一致的

统一语言的概念其实很容易理解,难点在于怎么真正在实践中贯彻。

要在实践里真正贯彻“统一语言”的理念,我们可以从统一语言的“物质基础”和“实际应用”这两个方面来考虑。领域模型、和词汇表(glossary)和业务规则表等文档性的制品,就是统一语言的“物质基础”。而业务和技术人员在开发过程中的沟通协作,就是统一语言的应用。

这两方面缺一不可。要用好统一语言,首先要建好领域模型、词汇表和业务规则表。没有这些,就无法对语言进行规范化和持久化。

另一方面,在所有的协作过程中,每当我们说到领域知识的词汇,都要看一下在领域模型中是否有所反映、大家对同一概念的理解是否一致、已经废弃的词汇是否还在使用等等。

如果发现语言与模型不一致,就要及时纠正,让两者恢复一致。编写代码的时候,也要使代码中的各种命名与模型和词汇表保持一致。在前面的课程里,咱们在建模中模拟了你我两人的对话过程,就是希望你能够体会到语言在沟通中的应用。

在领域建模的过程中,我们也强调了,实体、关联等元素翻译成自然语言应该怎么说。事实上,好的模型中的任何元素,都应该可以和自然语言进行顺畅地双向转换。

总结

这节课的主要内容就讲完了。我们来总结一下。

今天我们首先介绍了模型的概念,然后说明了软件开发也是一个建模过程。为了跨越现实世界和机器模型之间的鸿沟,人们采用了“分步走”的方式。其中,在传统软件工程中的 分析 步骤产生的 分析模型,也叫做 领域模型

但是,DDD的领域模型与传统软件工程有一个重要的区别,就是,DDD强调领域模型要兼顾 业务和技术两个视角,而不像传统方法那样,只关注业务视角。

所以,我们可以说:DDD的领域模型是为了满足业务需求,对领域知识进行提炼和抽象的产物,反映了业务和技术人员的共同视角。一方面,它能够全面和深刻地反映领域知识,另一方面又能方便地转化为技术实现。

DDD的核心模式之一: 模型驱动设计 就是围绕领域模型展开的。它有两个要点:领域模型和业务需求要保持一致;系统实现和领域模型也要保持一致。最终的结果就是系统实现和业务需求保持一致。

除此之外,DDD还有另一个核心模式: 统一语言。要用好统一语言,一方面要建立好领域模型、词汇表等“物质基础”,另一方面要在沟通协作的过程中,不断保持模型、语言和系统实现的一致性。

这节课理论比较多,可能比较抽象,希望你在实践中不断体会。

思考题

1.在你的实际项目中,有没有遇到过业务和技术理解不一致的情况,造成了什么后果?

2.在你的实际项目中,有没有做过类似领域建模的事情,是否能够坚持下来?

好,今天的课程结束了,有什么问题欢迎在评论区留言,下节课,我们开始过渡到模型的实现,讲一下怎样根据领域模型进行数据库设计。