引用自:【微服务】基于DDD的商城系统实战(一)-- 领域分解 - 修行编程,沉淀技术,记录生活 - JinTang's Zone
前言
DDD早在2003年就诞生了,网上已经有非常多的资料,所以在这里不做过多的介绍。
学习DDD之后,对我整个程序开发视野有了新的理解,然后我迫不及待地想要亲身实践一下,基于DDD从0到1设计开发一套系统,以此来总结知识和检验学习成果,我希望能够把这一个过程记录下来,为公司业务侧对DDD文化的推广上尽一份力 ,我非常希望有更多的同学加入到DDD的队列中。
我们都知道DDD里面充斥着大量晦涩难懂的概念,还没到理解其中的设计思想就拜读完毕了,但DDD强调的是理论结合实践,没有经过实践,永远只能飘在半空无法抓住。所以我认为学习DDD不能局限于概念掌握,而是应该更多地通过实战去融汇贯通其中的设计原则和实践方法。
如果在文中遇到不懂的概念,不要着急,相信我,继续学习和实践中你会慢慢清晰起来。
DDD 的分治思想
DDD 是处理高度复杂领域的设计思想,其解决复杂问题的过程,体现了”分而治之”的思想。
当我们面对高度复杂的问题时,我们有两种办法解决:
- 提高解决问题的能力,能力大于问题的难度,问题也就解决了。
- 采用降低问题难度的方式,把问题拆分,降低问题难度到能力之下,问题也就解决了。
此处引出「问题空间」和「问题空间解」两个概念,我们来看一下复杂领域知识体系建立的一般方法:
复杂的领域就是一个问题空间,那么我们在拆分问题,也是划分领域的过程。
DDD 指导我们把复杂领域划分成为若干个子域,我们还会根据子域自身的重要性和功能属性将这些子域划分为三类,分别是:「核心子域」、「通用子域」和「支撑子域」
核心子域:决定企业核心竞争力的是核心子域,核心子域一般会对应核心产品或关键业务环节。
通用子域:被多个子域复用的是通用子域,通用子域一般对应某个单一职责的功能聚合。
支撑子域:那些企业必须的,既不是企业核心竞争力,也不会被其他子域复用的子域是支撑子域。
如果还没明白,后面会通过一个例子来举例说明。
DDD 从领域建模到微服务设计
DDD 具有庞大的核心知识体系,而关键要把握的是两个设计过程:「战略设计」和「战术设计」
战略设计:从业务视角出发,完成领域到子域的分解,并为子域定义核心子域和通用子域属性。在子域内展开事件风暴,根据上下文语义边界来划分限界上下文,建立通用语言,完成领域建模。
在建立领域模型后,我们将领域模型作为微服务设计的输入完成战术设计。
战术设计:从技术视角出发,侧重于对领域模型的技术实现,按照领域模型完成微服务的设计和落地。在战术设计中会有:聚合、聚合根、实体、值对象、领域服务等,我们会建立这些对象的依赖关系,并将领域模型中的领域对象以代码对象的形式映射到微服务中,采用分层架构完成微服务设计和系统落地。
战略设计和战术设计两者协同最终完成领域建模和微服务设计和落地。
再来看看DDD、领域模型与微服务的关系
领域模型是经过抽象并标准化的、可复用的,其设计遵循单一职责的原则,而微服务则是领域模型的技术实现。DDD 是一种可以同时指导领域建模和微服务设计的方法论,它遵循高内聚低耦合的原则,完成从业务端领域拆分、建模到应用端微服务实现的无缝落地。
DDD 整体设计过程
当我们的领域是比较小,无需在划分子域,那么我们可以直接进行领域建模,但是如果庞大的业务领域,必须先通过领域分解,大问题分解小问题嘛。
所以,我们首先需要做好顶层设计,从划分子域开始,再针对子域开展事件风暴,再划分限界上下文,完成领域建模,所以它是一个自上而下的设计过程。
DDD 整体设计过程主要有以下四个关键阶段:领域分解、领域建模、微服务设计和详细设计及技术实现
阶段一:领域分解
主要目标是基于企业业务域完成从领域到子域的分解,完成子域属性定义,确定哪些子域是通用子域,哪些是核心子域?这个过程也是产出通用子域、支撑子域和核心子域的关键过程。
阶段二:领域建模
基于第一阶段产出的核心子域或通用子域,采用事件风暴工作坊等方法,划分限界上下文,完成领域建模。这个过程我们会重点关注业务场景和问题,基本不考虑技术实现方案。在领域建模时,我们还会提取领域对象,确定限界上下文之间的服务依赖,建立领域模型内领域对象之间的依赖关系,比如谁是聚合根?谁是实体?然后根据业务内聚和对象依赖关系构建聚合。这里需要特别强调一下:一定要重视领域建模,因为领域模型是微服务设计的前提和输入,领域模型的质量会决定微服务设计的质量。
阶段三:微服务设计
将第二阶段产出的领域模型作为微服务设计的输入,完成微服务拆分,基于分层架构等技术来完成微服务设计。这个阶段我们会确定微服务之间的上下文服务依赖,进一步细化聚合、实体、值对象依赖关系以及服务的分层和组合关系,完成微服务代码的目录结构设计,建立领域模型与应用代码模型的映射关系。
阶段四:微服务详细设计和技术实现
在第三阶段设计的基础上,继续细化并完成微服务详细设计和落地技术实现,这一阶段要重点关注微服务落地过程中的所有实现细节,比如:API 设计和服务规约,数据模型设计,测试和集成以及部署和运维等相关内容。
领域分解实例
接下来,我们就开始第一个阶段:领域分解。
领域分解就是对问题拆分的过程,那么在问题空间中,我们可以通过回答以下三个问题:
- 这个战略核心域的名字是什么,它的目标是什么?
- 这个战略核心域中包含哪些概念?
- 这个核心域的支撑子域和通用子域是什么?
问题一: 这个战略核心域的名字是什么,它的目标是什么?
首先,商城系统嘛,目标是卖更多的商品,获取更多的利润,所以我们找到销售核心域。
问题二:这个战略核心域中包含哪些概念?
先根据销售核心域的理解,想一下上下文。根据经验,我想到的:销售就是购买,购买就是加入购物车,购物车中进行结算后,形成订单。按照这样的思路,是否能想到更多的上下文呢?于是有了下图:
细想一下,销售考虑的是怎么把商品卖出去,如果会员一旦选好了并且下单成功了,那么销售的工作就结束了,那么订单上下文不应该在销售核心子域内,所以我把它拿出去。
问题三:这个核心域的支撑子域和通用子域是什么?
销售是为了怎么把商品卖出去,第一个想到的可能是做促销,打折之类的,所以我想到一个售价上下文,负责销售价格。我们发现用户-购买,才会形成订单,我们发现订单上下文作为用户上下文和购物车上下文的下游,分别被用户子域销售核心域复用,我们知道通用域是会被复用的,那么订单子域就是一个通用子域。不被复用也不是核心的支付子域,就是一个支撑子域。
按照这样的思路,我们得到:商品子域(支撑)、用户子域(支撑)、支付子域(支撑)、订单子域(通用)、物流子域(通用)。
总结一下
本文为你分享了DDD是如何解决高度复杂问题的分治思想,介绍了从领域模型到微服务设计的两个设计过程,DDD 整体设计过程的四个关键阶段。
阐述过程中,引出了问题空间、领域,子域,核心子域,通用子域,支撑子域,限界上下文,战略设计,战术设计等概念。
最后通过一个”商城系统”的实例,描述了领域分解的的分析过程。相信到到此,你对那些晦涩难懂的概念已经渐渐清晰了。有看官发现有很多概念没有提到,先不要着急,后序的文章会一一道来。
思考题
如果我们的商品子域依然庞大,我们能力无法解决,我们应该再次进行领域分解,那么聚焦商品子域,又该如何进行领域分解呢?
我正在学习DDD,经验有限,对DDD 的理解难免会有不足之处,欢迎探讨指正。