《领域驱动设计精简版》读书笔记(1)——何为领域驱动设计

基本概念

为了创造一个好软件,你必须知道这个软件究竟是什么。在你充分了解金融业务是什么之前,你是做不出一个好的银行业系统的,你必须理解银行业的领域。让软件和领域和谐相处的最佳方式是让软件成为领域的映射,软件需要具现领域里重要的核心概念和元素,并精确实现它们之间的关系。软件需要对领域进行建模。一幅图能够描绘和传达一个模型,同样,经过精心编写的代码和一段英语句子都能达到这个目的。

模型是软件设计中最基础的部分。我们需要它,是因为能够用它来处理复杂问题。我们对领域的所有的思考过程被汇总到这个模型中。这样甚好,但它必须要超越我们的头脑,如果它止步不前,其实并不会有多大的作用,不是吗?我们需要就这个模型跟领域专家进行交流,跟资深的设计人员进行交流,跟开发人员进行交流。模型是软件的根本,但我们需要找到一些方法来表现它,让它和其他事物交流。在这个过程中我们并不是孤立的,所以我们需要彼此共享知识和信息,而且我们需要把它做得更好、更精确、更完整,没有二义性。要做到这点有多种方式。常见的一种方式是将模型图形化:图、用例、画和图片等。另一种方式是写,我们会写下我们对领域的愿景。还有一种方式是使用语言,我们能够也应该针对要交流的领域内的特定问题建立一种语言。在以后的章节中我们会详细讲解它们,但主要观点是说,我们需要用模型来交流

软件设计类似于房子的架构和总图相关,代码设计更加细节,类似于在墙上定位一幅油画。要想让一幅油画向左边移动非常简单,而想要拆除房子的一个边却是一个完全不同性质的事情。软件设计方法:

  1. 瀑布设计方法:业务专家提出一堆需求同业务分析人员进行交流,分析人员基于那些需求来创建模型并作为结果传递给开发人员,开发人员根据他们收到的内容开始编码。在这个方法中,知识只有单一的流向。虽然这种方法作为软件设计的一个传统方法,这么多年来已经有了一定级别的成功应用,但它还是有它的缺点和局限。主要问题是业务专家得不到分析人员的反馈信息,分析人员也得不到开发人员的反馈信息。
  2. 敏捷方法:在需求经常变化的情况下,要想预先创建一个覆盖领域所有方面的完整模型确实很困难。需要做出很多的思考,而且开始时常不能看到涉及到的所有的问题,也不能预见设计中某些带有负面影响或错误的部分。尽管敏捷方法的倡导者承认设计决定的重要性,但他们反对预先设计。相反,他们使用大量灵活的实现,通过由业务涉众持续参与的迭代开发和许多重构,开发团队更多地学习到了客户的领域知识,从而能够产出满足客户需要的软件。
    敏捷方法也存在自己的问题和局限:他们提倡简单,但每个人都对“简单”的意义有着自己的观点。同时,缺乏了真实可见的设计原则,由开发人员执行地持续重构会导致代码更难理解或者更难改变。虽然瀑布方法可能会导致过度工程,但对过度工程的担心可能会带来另一种担心:害怕做出深度、彻底的设计。

构建领域知识举例

考虑一个飞机飞行控制系统项目的例子,看领域知识是如何被构建的,在一个给定的时刻,空中四处会有成千上万的飞机。它们会朝着各自的目的地按照自己的路线飞行,很重要的事情是要确保它们不会在空中发生碰撞,为了构建模型我们需要从与空中控制人员的讨论中提取基础知识并进行归纳。控制人员和你自己都认同每一个飞行器有一个起始机场和目的机
场。所以你找到了“飞行器”、“起始机场”和“目的机场”,见下图。
模型1
那么,飞机从某地起飞又在另一地降落。但空中发生了什么?班机会按照什么路线航行?事实上,我们更关心的是它在航行时所发生的事情。控制人员说会给每架飞机指派一个飞行计划,飞行计划会用来描述假定的整个空中旅行。当听到“飞行计划”时,你可能会在你脑海中想到这是一个飞机在空中必须遵守的路径。在后边的讨论中,你会听到一个有趣的词:路线(route)。它能很快引起你的注意,这是个很好的理由。路线包含了飞机航行中的一个重要概念。那就是飞机在飞行时要做的事,它们必须遵照一条路线。很明显飞机的出发点和目标点也就是路线的开始和结束点。所以,不同于将飞行器与出发点和目标点管理,看上去更自然的是将它与“路线”进行关联,然后路线再与适当的出发点和目的地关联。
模型2
跟控制人员交流飞行器需要遵照的路线时,你会发现路线由小的区间段组成,这些区间段按照一定的次序组织起来就会构成从出发点到目的地的一条曲线。这条线被假定穿过预定的方位点。所以,路线可以被考虑成一系列连续的方位点。从这个角度看,你不会再将出发点和目的地看作是路线的结束点,而只是将它们看作那些方位中的两个点。这跟从控制人员的角度来看可能有很大的不同,但这是一个必要的抽象,对后续的工作会产生帮助。根据这些发现产生出来的变化结果如下:
模型2
这副图显示了另外一个元素,事实上路线中需要遵照的每个方位是一个在空间中的一个点,它表现为一个 3 维的点。但当你跟控制人员交谈时,你会发现他并不按这种方式思考。实际上,他将路线看作是飞机航班在地球上的映射。方位只是地球表面上的点,可以由经度和纬度来决定。所以正确的图是:
模型2
实际上发生了什么呢?你和领域专家在交谈,你们在交换知识。你开始问问题,然后他们回应。当他们这样做时,他们从空中交通领域挖掘出基础性的概念。那些概念可能看上去未经雕琢、没有经过组织,但它们却是理解领域的基础。你需要尽可能多地从专家处学习领域知识。通过提出正确的问题,正确地处理得到的信息,你和专家会开始勾勒领域的骨架视图,也就是领域模型。这种骨架视图既不完整也不能保证是正确的,但它却是你需要的开始点,可以尽力判断出领域的基础性概念。

通过与领域专家的交谈,软件设计人员的分析型思维会帮助他挖掘出一些领域中的关键概念,并且帮助构建出可用于将来讨论用的结构,我们将在下一章中看到这种结构。作为软件方面的专家(软件架构师和开发人员)和领域专家,我们会在一起创建领域的模型,这个模型会体现两个专业领域的交汇。这看上去是个很消耗时间的过程,并且确实如此,但是它也应该被这样做,因为软件的最终目的是去解决真实领域中的业务问题,所以它必须和领域完美结合。

通用语言

软件专家和领域专家通力合作开发出一个领域的模型的过程中,沟通是非常重要的,由于软件专家和领域专家都只了解他们特有的专业技能,为克服这种交流方式的不同,在建立模型时,我们必须通过沟通来交换对模型和模型中涉及到的元素的想法,应该如何连接它们,哪些是有关的,哪些不是,软件专家只有正确理解领域专家的思路,才有机会获得项目的成功。所以通用语言的重要性不言而喻,领域驱动设计的一个核心的原则是使用一种基于模型的语言。因为模型是软件满足领域的共同点,它很适合作为这种通用语言的构造基础。

通用语言连接起设计中的所有的部分,建立了设计团队良好工作的前提。可能会花费数周乃至数月的时间才能让一个大规模项目的设计成型。团队成员会发现一些初始的概念是不正确的或者不合适宜,或者发现一些需要考虑并放进总体设计中的新的设计元素。没有了通用语言,所有的这一切都是不可能的。我们应该尽可能少地在需求沟通的场景中使用我们自己的行话,应该使用通用语言,因为它能帮助我们更清晰更精确地交流。

我们可以使用文档构建模型,一个明智的沟通模型的方式是创建一些小的图,让每副小图包含模型的一个子集。这些图会包含若干类以及它们之间的关系。这样就很好地包括了所涉及到的概念中一部分。然后我们可以向图中添加文本。文本将解释图所不能表现的行为和约束。每个这样的片断都试图解释领域中的一个重要的方面,类似于一个聚光灯那样只聚焦领域的一个部分。

参考书籍

领域驱动设计精简版