一文解析 DDD 中台和微服务设计
本文简介
本文来源于 2020 年第四届 DDD 中国峰会主题演讲:《当中台遇上 DDD,如何设计微服务》。DDD 非常强调统一语言,而 DDD、中台与微服务产生于不同的时代,三者分别属于不同的方法体系,而方法论的融合首要在于建立统一语言,那 DDD、中台和微服务的通用语言到底在哪里?如何用 DDD 完成中台和微服务设计实战?DDD 在中台和微服务的整体设计流程是什么样的?随着业务发展,领域模型和微服务会不断变化和演进,如何用最小代价来适应因为业务变化,而带来的领域模型和微服务演进?希望你能在本文找到答案!
作者:欧创新
从事保险领域架构设计工作十余年,热衷于基于 DDD 的中台和微服务架构设计与方法论研究。
1、极客时间《DDD 实战课》专栏作者,主要讲解 DDD 核心知识体系和基于 DDD 的微服务设计实战设计案例。
2、《中台架构与实现:基于 DDD 和微服务》作者,从中台视角讲述如何用 DDD 方法完成中台领域分解、建模和微服务设计。2020 年 10 月在机械工业出版社出版。
1、建立 DDD、中台和微服务的统一语言
1.1 中台回顾
我们先简单回顾一下中台的发展历程,2017 年《企业 IT 架构转型之道:阿里巴巴中台战略思想和架构实战》出版后,中台就受到业界热捧。中台的出现是为了解决以往烟囱式和单体架构的重复开发、数据分散和试错成本高的问题,也是为了提高企业市场响应能力,解决巨型企业由于产品种类繁多、部门林立和沟通困难,而导致的商业模式创新难的问题。
但由于不同行业企业之间存在着巨大的差异,所以阿里的成功经验并太那么容易复制到其他企业。而且由于早期缺少案例、工具和方法论的指引,加之个别企业的翻车案例,很多企业也开始思考,如何结合企业自身特点,才能更好地完成中台数字化转型。近两年来,随着越来越多的成功案例、方法论探索和经验的沉淀和总结,中台慢慢进入成长和稳定期,也从争议逐渐变为事实。
中台在实践过程中被赋予了太多的涵义,比如中台组织架构和中台运营等内容,这些内容会由于企业不同而在落地时出现非常大的差异。今天我们主要从业务视角,来分析中台的领域建模和微服务落地。
从企业架构角度来讲,业务中台属于业务架构的范畴。与普通的项目不同,中台是企业级的,所以首先要从顶层设计开始,做好抽象、标准化和能力复用设计。传统企业在实施中台时,其策略也会与阿里有所不同。
阿里主要集中在通用中台建设,实现企业级能力复用,解决重复造轮子的问题。而传统企业由于产品、业务多样性和多渠道展业的需要,对于企业核心能力需要有更强的灵活性和多渠道复用能力。比如在保险业,意外险可以在传统柜台、航运或汽运站、官网、toC 的 APP 或者融入第三方平台以及旅游网站进行展业销售。所以,传统企业除了建设通用中台,还需要建立核心能力中台,解决不同渠道核心能力重复建设的问题。
核心能力中台主要面向企业核心业务领域,面向不同渠道和客户实现核心能力复用,发挥企业核心竞争力作用。通用能力中台则主要面向可共享的公共业务领域,通过抽象和标准化,面向所有业务板块实现通用能力复用。
中台是一种基于业务能力复用目的而提出的思想或理念,它的技术实现手段可以很多,企业可根据自身技术特点灵活选择,可以采用单体架构也可以采用微服务架构。不能说采用微服务才是中台,而采用单体方式就不是中台。阿里刚开始做中台时,微服务其实也是刚提出没多久,所以阿里早期的中台建设应该也是采用单体架构的方式来实现的。不过,随着云计算和微服务等分布式技术的成熟,微服务已经逐渐成为中台的最佳技术实现。
从整个企业业务域来看,通用能力中台和核心能力中台本质上是企业业务架构中的某一个子业务板块,在中台设计时需要遵循可复用、单一职责和高内聚松耦合原则,完成企业级业务领域的分解和重构。在业务板块划分时,可以根据属性不同而被区分为通用能力中台和核心能力中台。所以,企业业务中台重构的本质上就是:“基于企业级能力复用目的的业务架构重构”。
1.2DDD 如何处理高度复杂领域
DDD 解决复杂问题的过程,体现的是一种“分而治之”的思想。当我们遇到问题时,如果能力大于问题,直接用能力解决就可以了。而如果能力小于问题,那应该怎么办?
一般有两种方法用来解决这类复杂问题:
第一,我们可以提高解决问题的能力,使得能力大于问题的难度,这样问题就可以解决。
第二,采用降低问题难度的方式。将问题的难度降低到自己的能力之下,这样能力就大于问题难度了,所以问题也可以解决。当能力有限时,我们可以拆分问题,一直拆分到能力大于问题为止。这样,问题也自然就解决了!
过去在业务规模不大时,我们一般采用传统集中式架构来解决业务能力的问题,所以那时候单体应用非常流行。而随着大量高频海量互联网业务场景的出现,如果将集中式架构的能力挖掘到极限,仍然不足以解决业务和应用扩展能力问题时,那么我们就可以基于分布式架构将原来的单体应用拆分为多个微服务,进而上云实现应用的弹性伸缩和业务扩展能力。所以当能力有限时,我们可以通过分解问题空间,降低问题复杂度的方式,来解决业务扩展能力的问题。
总之,DDD 和微服务都是处理高度复杂领域的设计思想!
我们来看一下复杂领域知识体系建立的一般方法。当遇到复杂问题时,我们可以按照一定规则不断将问题空间逐级细分,采用分治策略,分别为不同的子域求解,并建立知识体系。然后将各个子域知识体系的解合并,最终建立整个领域的知识体系。
那是否有相应的方法来指导完成问题空间的拆分?
1.3 领域分解及子域属性定义
我们以保险领域为例,大致了解一下 DDD 领域的分解过程。比如,我们可以按照保险关键流程环节或功能聚合,并结合领域经验来完成保险领域细分,将复杂的保险领域拆分为如图所示的若干个子域。
在完成子域细分后,我们会根据子域自身的重要性和功能属性将这些子域划分为三类,分别是:核心子域、通用子域和支撑子域。决定企业核心竞争力的是核心子域,核心子域一般会对应核心产品或关键业务环节,如承保。被多个子域复用的是通用子域,通用子域一般对应某个单一职责的功能聚合,如支付。另外,那些企业必须的,既不是企业核心竞争力,也不会被其他子域复用的子域是支撑子域。
你可能会问:为什么要区分这些子域的属性呢?这是因为当企业资源有限时,我们需要针对不同的子域制定不同的战略资源投入策略,从而可以确保将关键资源投入到核心子域,以此来持续保持企业的核心竞争力。
而在将这些子域映射到中台时,核心子域需要关注不同渠道的适配和复用能力,而通用子域则需要重点关注标准化和抽象化设计,以确保构建出的通用能力模型可以面向企业所有业务板块实现能力复用。
在完成从领域到子域的划分后,我们可以在子域内采用事件风暴,找出限界上下文完成领域建模。然后按照限界上下文边界来拆分微服务,并找出微服务内聚合以及领域对象之间的依赖关系。在不同的层设计服务,进行服务组合和编排,完成微服务的分层和解耦设计。如下图所示。
所以 DDD 问题解决的整体过程就是:从问题空间出发,逐级抽象,层层深入和细化,从业务的宏观到技术的微观整体考虑,最终完成领域建模和微服务落地。
1.4 从业务视角建立 DDD 与中台的统一语言
在了解了中台和 DDD 的问题域分解和建模的过程后,我们就可以从业务视角来建立 DDD 与中台的统一语言了。
一般来说,中台建设会站在企业高度,所以我们将问题空间定位在全企业的业务域。当我们从 DDD 的视角来进行领域分析时,我们会根据核心业务环节或者功能聚合边界以及领域经验等多个维度,完成从领域到子域的细分。并根据企业发展战略来分析,以确定子域到底是通用子域还是核心子域。
而当我们从中台建设视角出发,将不同的业务板块细分为通用中台和核心中台时,从下图中我们就可以发现,中台一般会跟 DDD 的某一个子域对应,所以我们可以认为:“中台本质上就是按照 DDD 方法从企业业务领域细分出来的某个子域”。
在建立了它们的映射关系后,我们就可以统一 DDD 和中台的通用语言了。然后就可以将 DDD 从战略到战术设计方法,应用到中台的完整设计和建设过程中,完成中台的领域分解,找出限界上下文,完成领域建模,并用微服务来完成中台落地。
1.5 小结
我们对 DDD 与中台和微服务的关系做一个小结,如下图所示。
DDD 与中台和微服务的关系是:“中台本质是领域中的某一个子域,需要抽象并标准化,按照单一职责原则建立可复用的领域模型。而微服务则是中台的最佳技术实现。DDD 是一种可以同时指导中台业务建模和微服务设计的方法论,它遵循高内聚低耦合的原则,完成从业务端领域拆分、建模到应用端微服务实现的无缝落地。”
2、如何用 DDD 完成中台和微服务设计
在建立了 DDD 与中台和微服务的统一语言后,我们接下来讨论如何用 DDD 来完成中台和微服务设计。
2.1DDD 核心知识体系
DDD 的知识体系非常庞大,主要包括:战略和战术设计两个关键设计过程。
战略设计从业务视角出发,完成领域到子域的分解,并为子域定义核心子域和通用子域属性。在子域内展开事件风暴,根据上下文语义边界来划分限界上下文,建立通用语言,完成领域建模。
在建立领域模型后,我们将领域模型作为微服务设计的输入完成战术设计。
战术设计从技术视角出发,侧重于对领域模型的技术实现,按照领域模型完成微服务的设计和落地。在战术设计中会有:聚合、聚合根、实体、值对象、领域服务等,我们会建立这些对象的依赖关系,并将领域模型中的领域对象以代码对象的形式映射到微服务中,采用分层架构完成微服务设计和系统落地。
战略设计和战术设计两者协同最终完成中台和微服务设计和落地。
由于内容太多,这里就不展开详细介绍了,你可以参考《中台架构与实现:基于 DDD 和微服务》,里面有详细的案例和代码,也比较通俗易懂。
2.2 中台和微服务整体设计过程
一般来说,对于比较小的领域我们可以直接从事件风暴开始,完成领域建模。而对于企业级中台而言,由于企业领域非常庞大,不适合直接开展事件风暴。所以,我们首先需要做好顶层设计,从划分子域开始,确定好中台的业务边界,然后再开展事件风暴,再划分限界上下文,完成领域建模,所以它是一个自上而下的设计过程。
DDD 整体设计过程主要有以下四个关键阶段:领域分解、领域建模、微服务设计和详细设计及技术实现,如下图所示。
第一个阶段是领域分解。
本阶段主要目标是基于企业业务域完成从领域到子域的分解,完成子域属性定义,确定哪些子域是通用子域,哪些是核心子域?这个过程也是产出通用中台和核心中台的关键过程。
第二个阶段是领域建模。
基于第一阶段产出的核心子域或通用子域,采用事件风暴工作坊等方法,划分限界上下文,完成领域建模。这个过程我们会重点关注业务场景和问题,基本不考虑技术实现方案。在领域建模时,我们还会提取领域对象,确定限界上下文之间的服务依赖,建立领域模型内领域对象之间的依赖关系,比如谁是聚合根?谁是实体?然后根据业务内聚和对象依赖关系构建聚合。
这里需要特别强调一下:一定要重视领域建模,因为领域模型是微服务设计的前提和输入,领域模型的质量会决定微服务设计的质量。
第三个阶段是微服务设计
将第二阶段产出的领域模型作为微服务设计的输入,完成微服务拆分,基于分层架构等技术来完成微服务设计。这个阶段我们会确定微服务之间的上下文服务依赖,进一步细化聚合、实体、值对象依赖关系以及服务的分层和组合关系,完成微服务代码的目录结构设计,建立领域模型与应用代码模型的映射关系。
第四个阶段是微服务详细设计和技术实现
在第三阶段设计的基础上,继续细化并完成微服务详细设计和落地技术实现,这一阶段要重点关注微服务落地过程中的所有实现细节,比如:API 设计和服务规约,数据模型设计,测试和集成以及部署和运维等相关内容。
2.3 领域建模过程
领域建模一般采用事件风暴工作坊方法。我们来了解一下领域建模的几个关键步骤。
第一步,团队成员和领域专家聚集在一个开放的区域,借助墙、白板和贴纸等工具,采用头脑风暴形式,根据业务场景或用户旅程分析,列出所有领域事件,对每一个事件标注出导致该事件的命令,为每一个事件标注出命令的发起方。
第二步,从命令和领域事件中提取产生这些业务行为的对象,即实体或值对象。根据命令来提取服务或实体的方法。这个过程我们可以采用名词和动词分析法,比如根据名词提取实体,根据动词提取命令来设计实体的方法或者服务。
第三步,根据领域对象之间的依赖关系,构建聚合。
首先,从众多实体中根据聚合根的特点找出聚合根,比如:是否有独立的生命周期?是否有全局唯一 ID?是否可以创建或修改其他对象?是否有专门的模块来管理这个实体?然后,根据业务内聚的原则,找出与聚合根关联的所有实体和值对象,构建出“高内聚,低耦合”的聚合。
第四步,划分限界上下文,构建领域模型
将多个聚合归类到同一个上下文语义环境,划定限界上下文边界,建立上下文映射,完成领域模型的构建。
以上就是领域建模的大致过程。领域建模过程是项目团队成员统一语言和建立通用语言的关键过程,所以建议团队成员应尽早参与。
2.4 分层架构及领域模型的核心价值
在完成领域建模后,我们下一步就可以根据领域模型开始微服务设计了。微服务一般会基于分层架构来设计,现在比较流行的分层架构有:DDD 四层架构、六边形架构和洋葱架构。
三种分层架构的核心思想就是将领域模型放在应用的最核心位置,然后通过分层建立外层依赖内层的松耦合依赖关系,从而隔离外部环境的“变”与领域模型的“不变”。
我们在领域模型设计时,一般太不关注前端用例或者界面类需求。领域模型内实体和服务大多是一些相对稳定的原子业务逻辑。但是,前端页面或流程以及技术组件总是在不断的变化,比如大量新技术组件的出现会导致基础设施层技术组件的频繁更新和升级,界面要素和流程会随外部需求和业务场景的需要而频繁做出调整等。这些外部变化会对领域模型的核心逻辑产生比较大的影响。
我们一起来看看如何通过分层来隔离外部变化对领域模型的影响?
分层架构大多是通过前端或后端适配,逐层控制外部变化向领域层传导,从而降低外部变化对领域模型的影响。比如在前端应用中可以消化掉页面逻辑和页面流程类需求;在用户接口层可以完成前端应用接口和数据适配,避免将接口和数据适配类需求传导到应用层;在应用层通过服务组合和编排,可以避免用例或服务组合类需求向领域层传导;在基础设施层通过依赖倒置设计,可以隔离技术组件变化对领域逻辑的影响。
这样由外向里逐层消化和隔离外部变化对领域模型的影响,从而可以最大限度保持领域模型原子性和长期稳定。
一个稳定的领域模型可以给我们带来非常多的好处。
首先,领域模型的构建过程是项目团队通用语言建立的过程,领域模型就是团队的通用语言,它会贯穿项目的所有过程。
其次,领域模型的业务逻辑大多是可复用的原子逻辑,不易受外部变化的影响。将这些核心逻辑沉淀到领域层,让核心逻辑更聚焦,核心代码更内聚。然后在应用层通过应用服务对领域层服务完成组合和编排,可以大量复用领域层的核心业务逻辑代码,从而提升代码复用率。
第三,领域模型的核心代码可交由专门的资深开发人员维护,从而提升代码质量,也能够保证应用关键核心业务逻辑的长期稳定运行。
第四,领域模型内聚合边界清晰,可方便微服务以聚合为单位的功能和代码的拆分和重组,让微服务具有更强的演进能力。
2.5DDD 分层架构与微服务设计
不同分层架构模型,在微服务开发和落地时其代码实现方式就会存在差异,所以建议结合自身技术特点,从上述三种分层架构模型中来选择合适自己的分层架构模型来完成微服务落地。这里,我们选择了经典的 DDD 四层分层架构。
先来简单介绍一下 DDD 分层架构。
DDD 分层架构共包含四层,分别是用户接口层、应用层、领域层和基础设施层。
领域层在分层架构最核心的位置,主要实现领域模型的最核心领域逻辑。领域层包括若干个聚合,每个聚合内有一个聚合根、若干实体和值对象。在微服务设计和开发时,要重点关注聚合之间对象和服务的解耦设计。一般来说聚合之间只通过聚合根 ID 关联,应尽量避免不同聚合领域对象或服务以及数据实体之间产生依赖,以便微服务在架构演进时可以相对轻松地完成聚合的拆分和重组。
为了避免聚合之间产生服务依赖,聚合之间的数据交互一般采用异步化的领域事件驱动方式。另外,你也可以将聚合之间的服务调用上升到应用层,在应用服务中完成不同聚合之间的服务组合和调用。
领域层之上是应用层,它连接用户接口层和领域层,通过应用服务协调领域层多个聚合完成服务的组合和编排,形成粗粒度的组合服务。由于这一层基本不实现领域逻辑,所以它很薄。
再往上一层就是用户接口层。微服务架构通常采用前后端分离设计,一个微服务可能会面对多个不同类型的前端应用。而前端应用由于技术或业务场景差异,对 API 的技术实现或数据可能会存在差异。在用户接口层我们可以根据前端需求封装应用层的应用服务,面向不同前端应用提供接口和数据适配。
基础设施层为其他各层提供通用技术和基础服务。通过依赖倒置设计,封装基础资源服务实现逻辑,实现各层与基础设施层的解耦,降低外部资源和技术组件升级变化对核心业务逻辑的影响。
根据 DDD 分层架构,我们就可以设计微服务代码的目录结构了,如下图所示。
与 DDD 分层架构对应,微服务会有四个一级目录分别对应:用户接口层、应用层、领域层和基础设施层。另外,每一个聚合在领域层代码目录下也有完全隔离的二级目录,用于存放聚合代码。在聚合代码目录设计时,我们需要提前做好聚合代码的隔离,以便在微服务演进时可以相对轻松地完成聚合代码的拆分和重组。
在完成微服务代码目录后,我们就可以建立领域对象与代码对象的映射关系了,这个过程也就建立了领域模型到系统模型的映射关系。
在领域建模时,我们会分析领域中的事件、命令等,这时会产生大量的领域对象,为了方便建立团队的通用语言,我们会将这些领域对象记录到表格中。下面这个表格就是一个领域模型聚合内的所有领域对象。
在微服务设计时,我们会根据领域对象同步设计领域对象对应的代码对象,并在表格中记录它们的映射关系。在微服务代码落地时,我们就可以在对应的代码目录结构中完成代码对象的开发。这样就建立了领域模型与系统模型的映射关系。
如果领域模型中的某些领域对象发生了变化,我们就可以根据对象之间的这种映射关系,很容易地找到领域对象对应的代码对象的位置,同步调整系统模型,实现从领域模型变化到系统模型变化的有效联动。
3、领域模型和微服务的演进
在完成领域建模和微服务设计后,你可能会问花了这么大精力设计出的领域模型是否合理?这个问题可能只有在真正的生产实践中才能找到答案!
当领域模型应用到真实的业务场景后,如果发现领域模型设计不合理,我们就需要根据实际情况不断完成领域模型和微服务的迭代演进,让它们真正能够满足业务的需要。另外,因为企业业务的发展和变化,往往也会导致领域模型变化和微服务架构演进。
领域模型不是一成不变的,所以不要期望一劳永逸的构建出一个恒久不变的领域模型。但我们可以通过提前设计,在变化发生时,依然可以用一种相对轻松的方式,完成领域模型和微服务的演进。
那么,如何以最小的代价来完成领域模型和微服务演进?我们下面根据具体情况来分析。
企业业务的变化对领域模型和微服务架构演进的影响,一般会有两种类型:
第一种是应用之间功能模块级的变化。这类变化通常会影响到微服务之间的功能模块的拆分或重组,所以影响就会比较大。
第二种是应用内方法或者服务级的变化。这类变化对微服务的影响一般都比较小,我们修改实体方法或服务,就可以相对容易地解决。
3.1 功能模块级的演进
对于第一种情况,如果我们在微服务设计时仍然采用传统三层架构模式,这样设计出来的微服务的内部功能和代码的耦合度依然很高,我们得到的实际上是一个一个分布式小单体。当业务发生变化,我们需要对这些小单体进行功能拆分或重组时,就会存在非常大的困难。在进行功能和代码拆分时,由于耦合度过高会有大量的代码重构工作,这也会给生产运营带来非常大的不确定性风险。
我们再来看看采用 DDD 分层架构设计出来的微服务是什么样子的?
我们知道,微服务的边界来源于限界上下文。在限界上下文内会有多个聚合。一个聚合会有若干个领域对象。聚合是领域模型的最小业务单元,它本质上就是一个小的功能模块。由于聚合功能的高内聚,而且可以自包含地独立运行,所以除了按照限界上下文边界拆分的微服务之外,聚合也是领域模型内可进一步独立为微服务部署的最小单元。
不过,在现有分布式架构下,以限界上下文边界来拆分微服务就足以满足业务需要了,我们没必要将微服务拆分得过细(除非对聚合相关的功能有极致的性能要求),这样会运维和集成能力会提出过高的要求。而在 serverless 架构下,当采用基于更细粒度的函数式编程时,会不会以聚合为单位来拆分函数代码单元就不得而知了,这也可以作为我们研究的一个方向。
按照 DDD 方法设计出来的微服务会有两个清晰的边界:第一层是微服务内松耦合的聚合边界,这是一个逻辑边界,它让微服务具有了基于聚合进行二次拆分和功能模块重组的能力;第二层是限界上下文的边界,在微服务落地时,就变成了微服务之间的物理边界。
当我们在领域模型中确定了这两个边界以后,就可以基于这两个边界来定义微服务的代码模型,完成代码开发。在进行聚合代码开发时,我们应该重点关注聚合之间的对象和服务解耦设计,做好聚合之间的代码隔离,在领域层尽量避免聚合之间产生各种形式的依赖。这样,当领域模型发生聚合级功能变化时,就可以随时在微服务之间完成聚合代码重组。因为领域模型内部和外部都有清晰的边界,所以当发生功能模块级变化时,微服务就可以快速平稳的完成功能和代码重组,完成架构演进。
而如果采用 DDD 设计,我们只要定义好了聚合这个逻辑边界,做好了架构的分层,其实也不一定要拆分出太多的微服务,即使采用分层架构将所有聚合放在一个单体中也未尝不可。有了聚合这层边界和聚合之间的解耦设计,未来需要将单体应用拆分或重组出新应用时,也不是一件难事。这个过程不会花太多的时间,也不需要改动太多的代码。
领域模型和微服务功能模块级的架构演进,一般会基于聚合这个最小的业务功能单元。我们可以根据业务发展和变化,将聚合独立为微服务,也可以在不同的领域模型和微服务之间完成聚合的功能重组,从而完成领域模型和微服务架构演进。
我们来看一下下面这个例子,看看它们到底是以什么样的方式来完成微服务架构演进的。在最早的原始模型中有两个微服务,其中每个微服务有三个聚合。
当应用上线一段时间后,随着业务发展,我们突然发现微服务 1 内聚合 a 的功能变成了海量高频业务。这时聚合 a 就会拖累整个微服务 1,并且因为聚合 a 面临性能瓶颈,在微服务 1 进行弹性扩缩时,也会造成资源浪费。这时,我们就可以将聚合 a 从微服务 1 中整体拆分,独立为一个新微服务 3。这样,微服务 3 就拥有了独立的资源和运行环境,在资源配置方面也可以更加有针对性的投入到微服务 3 了,可以随时满足高频访问的性能要求了。
或者在运行一段时间后,我们发现在领域建模时错误地将聚合 d 放到了微服务 2 里,或者随着业务发展聚合 d 更适合放在微服务 1 里。由于领域模型的不合适,可能会导致微服务之间出现频繁调用,进而导致微服务之间出现紧耦合关系。这时,我们就可以对领域模型做出调整,将聚合 d 从微服务 2 整体迁移到微服务 1 里。
由于我们在微服务设计时,已经做好了聚合之间的解耦,同时聚合代码也在目录结构上进行了隔离。所以,有了聚合这个逻辑边界,我们就不需要花太多的时间,也不需太多的代码调整,就可以相对轻松地完成领域模型和微服务的演进。
经过两轮领域模型演进,我们发现最早的两个微服务最终演进成为三个微服务,同时聚合 a 已经独立拆分为新的微服务,聚合 d 也在不同微服务之间完成了重组。由于我们在微服务设计时,已经提前做好了聚合之间的解耦设计,聚合间的代码也进行了目录隔离。所以当业务出现变化时,我们依然可以非常轻松地完成领域模型和微服务的同步演进。
3.2 服务级的演进
我们再来看一下微服务内的服务演进。
领域层的服务大多是原子服务,我们在进行服务设计时并不会考虑太多的前端用例需求,我们也无法预测到它会被多少个前端应用调用,会组合成什么样的应用服务。
而随着前端应用接入越来越多,这时你会发现有些领域服务在应用层被频繁的组合和编排,如上图所示领域服务 b 和领域服务 c。这时,你就需要注意了,我们可以进行服务演进了。
我们可以将同一个聚合中,那些被频繁组合和编排的多个领域服务(领域服务 b 和领域服务 c)的逻辑,封装成一个新的领域服务(领域服务 b+c)。当新接入前端应用时,它们就不需要在应用层组合和编排领域服务 b 和领域服务 c 了,而是直接调用领域服务 b+c。这样,既减少了领域层服务的数量,同时减轻了应用服务组合和编排的复杂度。
最后你会发现,随着这种类型的服务演进,领域模型会越来越精炼,同时微服务也越来越能适应外部需求变化了。
4、总结
DDD 博大精深,其实还有很多内容。比如,在中台建设时:微前端设计、领域事件驱动模型以及单元化的设计思想等内容,无法在这里一一展开。你可以参考《中台架构与实现:基于 DDD 和微服务》,里面有非常详细的介绍。
DDD 很好,但也不是万能的“银弹” !只有将中台和 DDD 视作一种设计思想和方法,适配最新的技术发展方向,吸收它的精髓,与时俱进。并结合企业文化和团队技术特点,有所取舍,灵活运用才是王道!
评论 (1 条评论)