第二部分 DDD基本原理——领域和子域:有效分解问题域
一、领域基本概念
领域是用来确定范围的,范围即边界。在研究和解决业务问题时,DDD会按照一定的规则对业务领域进行细分,当领域细分到一定程度后,DDD会将问题范围限定在特定边界内,在整个边界内建立领域模型,进而用代码实现该领域模型,解决相应的业务问题。领域可进一步划分为子领域。把划分出来的多个子领域称为子域,每个子域对应一个更小的问题域或更小的业务范围。
二、领域的分解过程
DDD是一种处理高度复杂领域的设计思想,它采用分而治之的策略,从而降低业务领域和技术实现的复杂度。DDD的研究方法与自然科学的研究方法类似,即分治策略。当人民在自然科学研究中遇到复杂问题时,通常做法是将问题一步一步细分,再针对细分出来的问题域,逐个深入研究,探索和建立所有子域的知识体系。当所有问题子域完成研究时,我们就建立了全部领域的完整知识体系。
三、子域的分类和属性
在领域不断划分的过程中,领域会被细分为不同的子域,根据子域自身的重要性和功能属性将它们划分为三类子域,分别是:核心子域、通用子域和支撑子域。
- 在企业内决定产品或企业核心竞争力的功能子域是核心子域,它是让企业业务和商业模式成功的关键核心能力,是企业在面对竞争对手时所拥有的核心竞争力。
- 没有太多个性化的诉求,同时会被多个子域重复使用的通用功能子域是通用子域。
- 还有一种功能子域是企业必须的,但它既不是决定产品或企业核心竞争力的功能,也不是被其他子域复用的通用功能,称为支撑子域。
战略方向和商业模式的不同最终会导致核心子域划分结果的不同。在企业业务领域不断细分、构建领域建模和完成微服务建设时,需要结合企业战略方向和商业模式来确定建设重点。首先找到核心子域,并将重点资源和资金投入核心子域建设上。对核心子域的建设,最好要有绝对的掌控能力和自主研发能力。
四、小结
DDD领域划分的核心思想是将问题逐级细分,采用分而治之的策略,将复杂问题简单化,从而降低业务理解和系统实现的复杂度。业务领域的子域划分其实是一种比较粗的领域边界的划分阶段,它不考虑子域内的领域对象以及对象之间的关系和层次结构。子域的划分往往可以按照业务流程或功能模块的边界进行粗分,其目的是为了逐步缩小业务边界,让你能够在一个相对较小的空间内,比较舒适地用事件风暴来梳理业务场景,构建领域模型。
划分核心子域、支持子域和通用子域的主要目的是:通过领域划分,区分不同子域在企业内的不同功能属性和重要性,使企业可对不同子域采取不同的资源投入和建设策略。从关注度和资源投入来看,支持子域和通用子域基本上是同一个层级的,区分度并不大。
第二部分 DDD基本原理——限界上下文:定义领域边界的利器
一、什么是通用语言
在事件风暴过程中,通过团队交流达成共识的,能够简单、清晰、准确地描述业务含义和规则的语言就是通用语言。通用语言往往跟领域中的名词术语和用例场景相关。通用语言中的名词一般可以给领域对象命名,如商品、订单等,它们对应领域模型中的实体对象。而动词则表示一个动作或领域事件,如商品已下单、订单支付等,它们对应领域模型中心的领域事件或命令。通用语言贯穿DDD的整个设计过程,它通过将领域模型映射到代码模型,可将这些名词术语直接反映到代码中。基于它,就能够开发出可读性更好的代码,将业务需求准确转化为代码落地。
从时间风暴开始,提取领域对象到建立领域模型以及微服务代码落地的完整过程如下:
- 在事件风暴过程中,领域专家会和团队设计、开发人员一起通过用户旅程分析货真场景分析
- 提取业务领域中的所有领域对象
- 将这些对象进行聚合,并划定业务边界,然后建立领域模型
- 在领域模型建设过程中,给这些领域对象统一命名,这个过程会形成项目团队统一的通用业务术语
- 建立了通用语言的领域模型会作为微服务设计的输入,而微服务的代码来源于领域模型,代码模型的代码对象会跟领域模型中的领域对象一一映射。
DDD分析和设计过程中的每一个环节,都需要保证限界上下文内通用语言的统一和正确传递。在代码模型设计的时候要建立领域对象和代码对象的意义映射,次那个人保证业务模型和系统模型一致,实现业务语言与代码语言的统一。
二、什么是限界上下文
“限界”是指具体的领域边界,“上下文”则是业务语义所在的上下文环境。通过限定领域的上下文边界,项目团队就可在这个特定的业务边界内用无歧义的通用语言进行交流了。限界上下文就是在限定的上下文环境内,用来封装通用语言和领域对象,保证领域内的一些术语、领域对象等有一个确切的含义,没有语义二义性的一个业务边界。
定义限界上下文时通常会考虑领域业务职责单一这个因素。在确定了领域的职责边界后,会将所有与实现该领域职能相关的对象都放在同一个限界上下文边界内,而将所有与该领域智能无关的对象都排除在上下文边界之外。限界上下文就是这样一个强制边界,它可以保证领域职责的单一性和领域模型的纯洁性。
三、限界上下文和微服务的关系
领域可拆分为多个子领域。一个领域相当于一个问题域,领域拆分为子域的过程就是大问题拆分为小问题的过程。子域还可以根据需要进一步拆分为子子域,拆分到一定程度后,有些子子域的领域边界就可能变成限界上下文边界了。子域可能包含多个限界上下文,每个领域模型都有它对应的限界上下文,团队在限界上下文内用通用语言交流。领域内所有限界上下文的领域模型构成了整个业务领域的领域模型。
限界上下文是微服务拆分过程中可参考的业务领域边界。虽然限界上下文理论上可作为微服务的拆分边界,但实际落地时,微服务的拆分还需要结合企业的实际情况,考虑其他非业务因素的限制条件。但要注意:“不宜过度拆分微服务”,这样会增加集成和运维成本。
四、限界上下文与子域的关系
在DDD中包括问题域和解决方案域两个不同的维度。问题域主要从业务视角来考虑,完成从领域到子域的分解,而解决方案域则主要从技术实现的角度,通过划分限界上下文和采用DDD战术设计完成微服务的拆分和落地。“子域”和“限界上下文”这两个概念分别从不同的视角,构建起了DDD处理业务复杂度的根基。
从实践角度将业务领域的分解拆分为两个阶段:
- 从领域到子域的粗粒度的分解和从子域到限界上下文的技术实现级的分解
- 根据子域属性划分为核心子域、通用子域和支撑子域。当领域分解到足够下后,就可以在这些子域内开展事件风暴,划分限界上下文完成领域建模了。
如果领域足够小的话,就没必要进行从领域到子域的分解和属性归类了,可直接开展事件风暴,直接划分限界上下文,完成领域建模。按照这种分解上市,如果子域和限界上下文边界刚好一致,那就是一对一关系,而如果在一个子域内还可划分为多个限界上下文,那最终得到的就是一对多的映射关系。
限界上下文本质上就是子域,只不过它会更多地考虑对象的语义边界和技术实现细节。限界上下文的划分体现的是一种更为详细的设计过程,这个过程划分了业务的上下文语义边界,完成了领域模型,明确了领域对象以及领域对象之间的依赖关系等。
五、小结
通用语言是项目团队内部交流的统一语言,而通用语言在语义上下文环境则是由限界上线文来限定的,这个边界可确保通用语言无二义性。领域专家和项目团队的主要工作,就是在业务领域到系统域的映射和系统落地。限界上下文确定了微服务拆分和设计边界,是微服务拆分和设计的主要依据。