1.2.1 领域驱动设计基础
本节将从几个常见问题出发,讨论DDD的基础知识。
1.领域驱动设计基本问题
关于DDD,我们首先需要回答如下3个问题。
(1)什么是DDD?
总体来说,DDD提供的是一套开展业务建模和软件设计的方法论。和其他方法论的不同之处在于,DDD强调开发人员与业务领域专家高效协作,从而共同交付业务价值。从架构设计上说,DDD认为良好的系统架构应该是技术架构和业务领域相互融合的结果,不能脱离业务领域设计技术架构。需要注意的是,DDD不是设计准则或者规范,也不是架构设计的“脚手架”。事实上,关于如何实现DDD,业界并没有给出统一的标准,这也是需要系统化学习DDD的原因。
(2)为什么需要DDD?
学习DDD的根本原因在于软件复杂度,关于软件复杂度的表现形式和关注点,请参考1.1节。读者可以充分扩散思维,想象一下日常开发中的痛点。针对软件复杂度,我们的思路是清晰划分软件的关注点,并通过拆分和建模在一定程度上降低系统复杂性。而DDD正是为了降低软件复杂度而诞生的软件设计方法。
(3)为什么DDD难学?
很多读者反馈DDD非常难掌握。实际上这并不代表DDD本身的学习难度也是如此,困难更多体现在学习方法和思维上。图1-19展示了DDD学习的表象与真相。
图1-19 DDD学习的表象和真相
诚然,DDD是一种比较复杂的建模方式,其中包含一系列相对晦涩难懂的核心概念,包括限界上下文、聚合、实体、值对象等。但这些概念并不是虚无缥缈的,而是依托于严谨的逻辑分析思维,包括拆分、边界、交互、集成和架构等。普通开发人员之所以觉得DDD概念多、不易理解,正是因为缺少这些逻辑分析思维。而DDD的创始人Eric Vans之所以能够提出DDD,也是因为他自身就是一名优秀的架构师,具备强大的逻辑分析思维能力,能够将这一能力与业务抽象、系统建模整合起来。原则上,如果读者拥有足够丰富的逻辑分析思维,也可以创建一种系统建模方法论并做到自圆其说。
2.问题空间和解空间
领域(Domain)本质上是对现实世界问题的一种统称,是一种业务开展的方式,用以体现一个组织所做的事情,以及其中所包含的一切业务范围和所进行的活动。例如,电商系统包含商品、订单、库存和物流等业务概念,而医疗健康系统则关注挂号、就诊、用药、健康报告等业务场景。领域概念的提出不仅从业务的角度体现了系统的功能和价值,而且从技术的角度为人们提供了设计思想。
我们以一个业务场景为例进行讨论。试想一下日常生活中的生病就医场景。为了完成一次就医过程,用户需要完成预约挂号、向医生述说身体症状、做各种检查并获取报告、根据检查结果进行用药等步骤。如果将这些步骤抽象为一个问题空间(Problem Space),那就是就诊。如果我们设计一个针对这一场景的系统,所有的环节都是为了更好地帮助用户就诊,这是对真实世界的一种表现。
那么,如何针对就诊这个问题空间提供对应的解决方案呢?这就需要引入解空间(Solution Space)的概念。解空间代表的是一种逻辑世界,通过设计语言和设计模型来解决真实世界中的问题。图1-20展示了问题空间和解空间之间的映射关系。
图1-20 问题空间和解空间的映射关系
那么问题又来了,我们应该如何设计解空间呢?这需要对系统进行建模,从而得到能够指导系统开发的业务模型(Business Model)。系统建模是一个复杂的话题,围绕这一话题,业界也形成了不同的建模方法,而DDD同样在系统建模领域占有重要地位。接下来,我们来看一下在DDD中业务模型的组成结构,图1-21展示了从解空间到业务模型的表现形式。
图1-21 从解空间到业务模型的表现形式
在图1-21中,我们通过7个问题对业务模型进行了分析。接下来,我们将围绕这7个问题展开介绍。
● 业务描述。业务模型需要通过简洁而通用的语言进行描述,从而确保与模型相关的所有人都能够对模型所代表的业务场景和需求达成统一认识。
● 业务拆分。业务场景的复杂度决定了业务模型中功能组件的数量和关联关系,我们需要通过拆分的方式明确各个功能组件之间的边界。
● 业务对象。在一个业务场景中,势必存在一组业务对象,这些业务对象通过一定的交互关系构成具体的业务场景。
● 业务规则。在一个业务模型中,内部的核心逻辑通过一系列的业务规则来进行展现,业务规则代表着具体领域下的业务价值。
● 业务状态。每个业务场景都拥有状态,这些状态构成了业务处理的流程和顺序,也是业务建模的重点对象。
● 业务数据。所有业务模型都会产生数据,而且业务规则和业务状态的设计很大程度上围绕业务数据的处理过程而展开,我们需要将核心业务数据持久化保存。
● 业务外观。对于一个业务模型,需要和客户端、其他业务模块及第三方外部系统进行集成。这就需要开放一定的交互入口,我们将这部分入口称为业务外观(Facade)。
DDD针对业务模型的以上7个问题给出了对应的设计方法。在此之前,我们先对DDD的设计维度进行分析。
3.战略设计和战术设计
DDD有两个主要的设计维度——战略设计和战术设计。
● 战略设计。战略设计关注如何设计领域模型,以及如何对领域模型进行划分,其目的在于清楚界分不同的系统与业务关注点。战略设计是一个面向业务、具备较高层次的设计维度,侧重于业务领域的梳理,以及考虑如何将业务领域和技术架构整合的问题。
● 战术设计。战术设计关注技术实现,从技术的层面指导开发人员实施领域驱动设计,关注在领域模型的基础上采用特定的技术工具来开发系统。显然,战术设计体现了技术架构的设计和展现方式。
战略设计和战术设计的整合为开发人员提供了一套通用的建模语言和术语,并展示了基于领域驱动的架构设计方法和实现DDD的各项关键技术,如图1-22所示。
图1-22 DDD中的战略设计和战术设计
接下来我们将结合业务模型及DDD的两大维度展开讨论。