DDD学习笔记 - 实战篇(Ⅰ)

11 | DDD实践:如何用DDD重构中台业务模型?

课程链接:https://time.geekbang.org/column/article/163032

一个传统企业中台建模的案例

传统企业应用分析

以保险行业的互联网电商和传统核心应用来做个对比分析。下面这张图,这两者在业务功能上会有很多相似和差异,这种相似和差异主要体现在四个方面。

DDD学习笔记 - 实战篇(Ⅰ)_第1张图片

1. 核心能力的重复建设。由于销售同质保险产品,二者在核心业务流程和功能上必然相似,因此在核心业务能力上存在功能重叠是不可避免的。传统保险核心应用有报价、投保、核保和出单功能,同样在互联网电商平台也有。这就是核心能力的重复建设。

2. 通用能力的重复建设。传统核心应用的通用平台大而全,通常会比较重。而互联网电商平台离不开这些通用能力的支撑,但为了保持敏捷性,一般会自己建设缩小版的通用功能,比如用户、客户等。这是通用能力的重复建设。

3. 业务职能的分离建设。有一类业务功能,在互联网电商平台中建设了一部分,在传统核心应用中也建设了一部分,二者功能不重叠而且还互补,组合在一起是一个完整的业务职能。比如缴费功能,互联网电商平台主要面向个人客户,于是采用了支付宝和微信支付的方式。而传统核心应用主要是柜台操作,仍在采用移动 POS 机的缴费方式。二者都是缴费,为了保证业务模型的完整性,在构建中台业务模型时,我们可以考虑将这两部分模型重组为一个完整的业务模型。

4. 互联网电商平台和传统核心功能前后完全独立建设。传统核心应用主要面向柜台,不需要互联网电商平台的在线客户、话务、订单和购物车等功能。而互联网电商平台主要面向个人客户,它不需要后端比较重的再保、佣金、打印等功能。在构建中台业务模型时,对这种情况应区别对待,将面向后端业务管理的应用沉淀到后台,将前端能力构建为面向互联网渠道的通用中台,比如订单等。

 

如何避免重复造轮子?

中台是企业级能力复用平台

中台的设计思想与“高内聚、低耦合”的设计原则是高度一致的。高内聚是把相关的业务行为聚集在一起,把不相关的行为放在其它地方,如果要修改某个业务行为,只需要修改一处。中台就是要这样做,按照“高内聚、松耦合”的原则,实现企业级的能力复用!

遇到了重复造轮子的情况,需要站在企业高度,将重复的需要共享的通用能力、核心能力沉淀到中台,将分离的业务能力重组为完整的业务板块,构建可复用的中台业务模型。前端个性能力归前端,后端管理能力归后台。建立前、中、后台边界清晰,融合协作的企业级可复用的业务模型。

如何构建中台业务模型?

可以用 DDD 领域建模的方法来构建中台业务模型。有两种建模策略:自顶向下和自底向上的策略。

1. 自顶向下的策略

这种策略是先做顶层设计,从最高领域逐级分解为中台,分别建立领域模型,根据业务属性分为通用中台或核心中台。领域建模过程主要基于业务现状,暂时不考虑系统现状。自顶向下的策略适用于全新的应用系统建设,或旧系统推倒重建的情况。

由于这种策略不必受限于现有系统,可以用 DDD 领域逐级分解的领域建模方法。从下面这张图我们可以看出它的主要步骤:第一步是将领域分解为子域,子域可以分为核心域、通用域和支撑域;第二步是对子域建模,划分领域边界,建立领域模型和限界上下文;第三步则是根据限界上下文进行微服务设计。

DDD学习笔记 - 实战篇(Ⅰ)_第2张图片

2. 自底向上的策略

这种策略是基于业务和系统现状完成领域建模。首先分别完成系统所在业务域的领域建模;然后对齐业务域,找出具有同类或相似业务功能的领域模型,对比分析领域模型的差异,重组领域对象,重构领域模型。这个过程会沉淀公共和复用的业务能力,会将分散的业务模型整合。自底向上策略适用于遗留系统业务模型的演进式重构。

以互联网电商和传统核心应用的几个典型业务域为例,采用自底向上的策略来构建中台业务模型,主要分为这样三个步骤。

第一步:锁定系统所在业务域,构建领域模型。

锁定系统所在的业务域,采用事件风暴,找出领域对象,构建聚合,划分限界上下文,建立领域模型。下面这张图,选取了传统核心应用的用户、客户、传统收付和承保四个业务域以及互联网电商业务域,共计五个业务域来完成领域建模。

DDD学习笔记 - 实战篇(Ⅰ)_第3张图片

可以看到传统核心共构建了八个领域模型。其中用户域构建了用户认证和权限两个领域模型,客户域构建了个人和团体两个领域模型,传统收付构建了 POS 刷卡领域模型,承保域构建了定报价、投保和保单管理三个领域模型。

互联网电商构建了报价、投保、订单、客户、用户认证和移动收付六个领域模型。

在这些领域模型的清单里,可以看到二者之间有很多名称相似的领域模型。深入分析后会发现,这些名称相似的领域模型存在业务能力重复,或者业务职能分散(比如移动支付和传统支付)的问题。那在构建中台业务模型时,就需要重点关注它们,将这些不同领域模型中重复的业务能力沉淀到中台业务模型中,将分散的领域模型整合到统一的中台业务模型中,对外提供统一的共享的中台服务。

第二步:对齐业务域,构建中台业务模型。

下面这张图,可以看到右侧的传统核心领域模型明显多于左侧的互联网电商,可以得出一个初步的结论:传统核心面向企业内大部分应用,大而全,领域模型相对完备,而互联网电商面向单一渠道,领域模型相对单一。

DDD学习笔记 - 实战篇(Ⅰ)_第4张图片

这个结论也指明了一个方向:首先可以将传统核心的领域模型作为主领域模型,将互联网电商领域模型作为辅助模型来构建中台业务模型。然后再将互联网电商中重复的能力沉淀到传统核心的领域模型中,只保留自己的个性能力,比如订单。中台业务建模时,既要关注领域模型的完备性,也要关注不同渠道敏捷响应市场的要求。

有了上述这样一个思路,就可以开始构建中台业务模型了。从互联网电商和传统核心的领域模型中,归纳并分离出能覆盖两个域的所有业务子域。通过分析,找到了用户、客户、承保、收付和订单五个业务域,它们是可以用于领域模型对比分析的基准域。

下面以客户为例,客户中台业务模型的构建过程。

互联网电商客户主要面向个人客户,除了有个人客户信息管理功能外,基于营销目的它还有客户积分功能,因此它的领域模型有个人和积分两个聚合。

而传统核心客户除了支持个人客户外,还有单位和组织机构等团体客户,它有个人和团体两个领域模型。其中个人领域模型中除了个人客户信息管理功能外,还有个人客户的评级、重复客户的归并和客户的统一视图等功能,因此它的领域模型有个人、视图、评级和归并四个聚合。

构建多业务域的中台业务模型的过程,就是找出同一业务域内所有同类业务的领域模型,对比分析域内领域模型和聚合的差异和共同点,打破原有的模型,完成新的中台业务模型重组或归并的过程。

将互联网电商和传统核心的领域模型分解后,找到了五个与个人客户领域相关的聚合,包括:个人、积分、评级、归并和视图。这五个聚合原来分别分散在互联网电商和传统核心的领域模型中,需要打破原有的领域模型,进行功能沉淀和聚合的重组,重新找出这些聚合的限界上下文,重构领域模型。

最终个人客户的领域模型重构为:个人、归并和视图三个聚合重构为个人领域模型(客户信息管理),评级和积分两个聚合重构为评级积分领域模型(面向个人客户)。到这里就完成了个人客户领域模型的构建了。

还有团队客户领域模型!其实团体客户很简单。由于它只在传统核心中出现,将它在传统核心中的领域模型直接拿过来用就行了。

至此就完成了客户中台业务模型的构建了,客户中台构建了个人、团体和评级积分三个领域模型。

通过客户中台业务模型的构建,你是否 get 到构建中台业务模型的要点了呢?总结成一句话就是:“分域建模型,找准基准域,划定上下文,聚合重归类。”

其它业务域其实也是一样的过程,不一一讲述。可以对照下面这张图,这就是其它业务域重构后的中台业务模型。

DDD学习笔记 - 实战篇(Ⅰ)_第5张图片

第三步:中台归类,根据领域模型设计微服务。

完成中台业务建模后,就有了下面这张图。可以看到总共构建了多少个中台,中台下面有哪些领域模型,哪些中台是通用中台,哪些中台是核心中台,中台的基本信息等等,都一目了然。根据中台下的领域模型就可以设计微服务了。

DDD学习笔记 - 实战篇(Ⅰ)_第6张图片

 

重构过程中的领域对象

上面主要是从聚合的角度来描述中台业务模型的重组,是相对高阶的业务模块的重构。业务模型重构和聚合重组,往往会带来领域对象和业务行为的变化。下面了解一下,在领域模型重组过程中,发生在更底层的领域对象的活动。

还是以客户为例来讲述。由于对象过多,只选取部分领域对象和业务行为。传统核心客户领域模型重构之前,包含个人、团体和评级三个聚合,每个聚合内部都有自己的聚合根、实体、方法和领域服务等。

DDD学习笔记 - 实战篇(Ⅰ)_第7张图片

互联网电商客户领域模型重构前包含个人和积分两个聚合,每个聚合包含了自己的领域对象、方法和领域服务等。

DDD学习笔记 - 实战篇(Ⅰ)_第8张图片

传统核心和互联网电商客户领域模型重构成客户中台后,建立了个人、团体和评级积分三个领域模型。其中个人领域模型有个人聚合,团体领域模型有团体聚合,评级积分领域模型有评级和积分两个聚合。这些领域模型的领域对象来自原来的领域模型,但积分评级是重组后的领域模型,它们原来的聚合会带着各自的领域对象,加入到新的领域模型中。

这里还要注意:部分领域对象可能会根据新的业务要求,从原来的聚合中分离,重组到其它聚合。新领域模型的领域对象,比如实体、领域服务等,在重组后可能还会根据新的业务场景和需求进行代码重构。

DDD学习笔记 - 实战篇(Ⅰ)_第9张图片

 

12 | 领域建模:如何用事件风暴构建领域模型?

课程链接:https://time.geekbang.org/column/article/163032

采用 DDD 方法建立的领域模型,可以清晰地划分微服务的逻辑边界和物理边界。可以说,在 DDD 的实践中,好的领域模型直接关乎微服务的设计水平。因此,DDD 的战略设计是比战术设计更为重要的。

该采用什么样的方法,才能从错综复杂的业务领域中分析并构建领域模型呢?

事件风暴。

事件风暴是一项团队活动,领域专家与项目团队通过头脑风暴的形式,罗列出领域中所有的领域事件,整合之后形成最终的领域事件集合,然后对每一个事件,标注出导致该事件的命令,再为每一个事件标注出命令发起方的角色。命令可以是用户发起,也可以是第三方系统调用或者定时器触发等,最后对事件进行分类,整理出实体、聚合、聚合根以及限界上下文。事件风暴正是 DDD 战略设计中经常使用的一种方法,它可以快速分析和分解复杂的业务领域,完成领域建模。

事件风暴需要准备些什么?

1. 事件风暴的参与者

事件风暴采用工作坊的方式,将项目团队和领域专家聚集在一起,通过可视化、高互动的方式一步一步将领域模型设计出来。领域专家是事件风暴中必不可少的核心参与者。谁来担任领域专家?领域专家就是对业务或问题域有深刻见解的主题专家,他们非常了解业务和系统是怎么做的,同时也深刻理解为什么要这样设计。可以从业务人员、需求分析人员、产品经理或者在这个领域有多年经验的开发人员里,按照这个标准去选择合适的人选。

除了领域专家,事件风暴的其他参与者可以是 DDD 专家、架构师、产品经理、项目经理、开发人员和测试人员等项目团队成员。领域建模是统一团队语言的过程,因此项目团队应尽早地参与到领域建模中,这样才能高效建立起团队的通用语言。到了微服务建设时,领域模型也更容易和系统架构保持一致。

2. 事件风暴要准备的材料

事件风暴参与者会将自己的想法和意见写在即时贴上,并将贴纸贴在墙上的合适位置,称这个过程是“刷墙”。所以即时贴和水笔是必备材料,另外还可以准备一些胶带或者磁扣,以便贴纸随时能更换位置。有点像敏捷开发。

在这个过程中,要用不同颜色的贴纸区分领域行为。如下图,我们可以用蓝色表示命令,用绿色表示实体,橙色表示领域事件,黄色表示补充信息等。补充信息主要用来说明注意事项,比如外部依赖等。颜色并不固定,这只是我的习惯,团队内统一才是重点。

 DDD学习笔记 - 实战篇(Ⅰ)_第10张图片DDD学习笔记 - 实战篇(Ⅰ)_第11张图片

3. 事件风暴的场地

只需要一堵足够长的墙和足够大的空间就可以了。墙是用来贴纸的,大空间可以让人四处走动,方便合作。撤掉会议桌和椅子的事件风暴,参与者们的效率更高。事件风暴的发明者曾经建议要准备八米长的墙,这样设计就不会受到空间的限制了。

4. 事件风暴分析的关注点

在领域建模的过程中,需要重点关注这类业务的语言和行为。比如某些业务动作或行为(事件)是否会触发下一个业务动作,这个动作(事件)的输入和输出是什么?是谁(实体)发出的什么动作(命令),触发了这个动作(事件)…可以从这些暗藏的词汇中,分析出领域模型中的事件、命令和实体等领域对象。

如何用事件风暴构建领域模型?

领域建模的过程主要包括产品愿景、业务场景分析、领域建模和微服务拆分与设计这几个重要阶段。以用户中台为例,介绍一下如何用事件风暴构建领域模型。

1. 产品愿景

产品愿景的主要目的是对产品顶层价值的设计,使产品目标用户、核心价值、差异化竞争点等信息达成一致,避免产品偏离方向。

产品愿景的参与角色:领域专家、业务需求方、产品经理、项目经理和开发经理。

在建模之前,项目团队要思考这样两点:用户中台到底能够做什么?它的业务范围、目标用户、核心价值和愿景,与其它同类产品的差异和优势在哪里?

这个过程也是明确用户中台建设方向和统一团队思想的过程。参与者要对每一个点(下图最左侧列的内容)发表意见,用水笔写在贴纸上,贴在黄色贴纸的位置。这个过程会让参与者充分发表意见,最后会将发散的意见统一为通用语言,建立如下图的产品愿景墙。

DDD学习笔记 - 实战篇(Ⅰ)_第12张图片

2. 业务场景分析

场景分析是从用户视角出发的,根据业务流程或用户旅程,采用用例和场景分析,探索领域中的典型场景,找出领域事件、实体和命令等领域对象,支撑领域建模。事件风暴参与者要尽可能地遍历所有业务细节,充分发表意见,不要遗漏业务要点。

场景分析的参与角色:领域专家、产品经理、需求分析人员、架构师、项目经理、开发经理和测试经理。

用户中台有三个典型的业务场景:第一个是系统和岗位设置,设置系统中岗位的菜单权限;第二个是用户权限配置,为用户建立账户和密码,设置用户岗位;第三个是用户登录系统和权限校验,生成用户登录和操作日志。

可以按照业务流程,一步一步搜寻用户业务流程中的关键领域事件,比如岗位已创建,用户已创建等事件。再找出什么行为会引起这些领域事件,这些行为可能是一个或若干个命令组合在一起产生的,比如创建用户时,第一个命令是从公司 HR 系统中获取用户信息,第二个命令是根据 HR 的员工信息在用户中台创建用户,创建完用户后就会产生用户已创建的领域事件。当然这个领域事件可能会触发下一步的操作,比如发布到邮件系统通知用户已创建,但也可能到此就结束了,需要根据具体情况来分析是否还有下一步的操作。

场景分析时会产生很多的命令和领域事件。用蓝色来表示命令,用橙色表示领域事件,用黄色表示补充信息,比如用户信息数据来源于 HR 系统的说明。

DDD学习笔记 - 实战篇(Ⅰ)_第13张图片

3. 领域建模

领域建模时,会根据场景分析过程中产生的领域对象,比如命令、事件等之间关系,找出产生命令的实体,分析实体之间的依赖关系组成聚合,为聚合划定限界上下文,建立领域模型以及模型之间的依赖。领域模型利用限界上下文向上可以指导微服务设计,通过聚合向下可以指导聚合根、实体和值对象的设计。

领域建模的参与角色:领域专家、产品经理、需求分析人员、架构师、项目经理、开发经理和测试经理。

可以分为三步。第一步:从命令和事件中提取产生这些行为的实体。用绿色贴纸表示实体。通过分析用户中台的命令和事件等行为数据,提取了产生这些行为的用户、账户、认证票据、系统、菜单、岗位和用户日志七个实体。

DDD学习笔记 - 实战篇(Ⅰ)_第14张图片

第二步:根据聚合根的管理性质从七个实体中找出聚合根,比如,用户管理用户相关实体以及值对象,系统可以管理与系统相关的菜单等实体等,可以找出用户和系统等聚合根。然后根据业务依赖和业务内聚原则,将聚合根以及它关联的实体和值对象组合为聚合,比如系统和菜单实体可以组合为“系统功能”聚合。按照上述方法,用户中台就有了系统功能、岗位、用户信息、用户日志、账户和认证票据六个聚合。

第三步:划定限界上下文,根据上下文语义将聚合归类。根据用户域的上下文语境,用户基本信息和用户日志信息这两个聚合共同构成用户信息域,分别管理用户基本信息、用户登录和操作日志。认证票据和账户这两个聚合共同构成认证域,分别实现不同方式的登录和认证。系统功能和岗位这两个聚合共同构成权限域,分别实现系统和菜单管理以及系统的岗位配置。根据业务边界,我们可以将用户中台划分为三个限界上下文:用户信息、认证和权限。

DDD学习笔记 - 实战篇(Ⅰ)_第15张图片

到这里就完成了用户中台领域模型的构建了。领域建模的过程中产生的领域对象实在太多,可以借助表格来记录。

DDD学习笔记 - 实战篇(Ⅰ)_第16张图片

4. 微服务拆分与设计

原则上一个领域模型就可以设计为一个微服务,但由于领域建模时只考虑了业务因素,没有考虑微服务落地时的技术、团队以及运行环境等非业务因素,因此在微服务拆分与设计时,不能简单地将领域模型作为拆分微服务的唯一标准,它只能作为微服务拆分的一个重要依据。

微服务的设计还需要考虑服务的粒度、分层、边界划分、依赖关系和集成关系。除了考虑业务职责单一外,还需要考虑将敏态与稳态业务的分离、非功能性需求(如弹性伸缩要求、安全性等要求)、团队组织和沟通效率、软件包大小以及技术异构等非业务因素。

微服务设计建议参与的角色:领域专家、产品经理、需求分析人员、架构师、项目经理、开发经理和测试经理。

用户中台微服务设计如果不考虑非业务因素,完全可以按照领域模型与微服务一对一的关系来设计,将用户中台设计为:用户、认证和权限三个微服务。但如果用户日志数据量巨大,大到需要采用大数据技术来实现,这时用户信息聚合与用户日志聚合就会有技术异构。虽然在领域建模时,将他们放在一个了领域模型内,但如果考虑技术异构,这两个聚合就不适合放到同一个微服务里了。可以以聚合作为拆分单位,将用户基本信息管理和用户日志管理拆分为两个技术异构的微服务,分别用不同的技术来实现。

 

================================================================================================

 

13 | 代码模型(上):如何用DDD设计微服务代码模型?

课程链接:https://time.geekbang.org/column/article/165248

 

微服务落地时首先要确定的就是微服务的代码结构。

只有建立了标准的微服务代码模型和代码规范后,才可以将领域对象所对应的代码对象放在合适的软件包的目录结构中。标准的代码模型可以让项目团队成员更好地理解代码,根据代码规范实现团队协作;让微服务各层的逻辑互不干扰、分工协作、各据其位、各司其职,避免不必要的代码混淆。还可以在微服务架构演进时,轻松完成代码重构。

 

DDD 分层架构与微服务代码模型

参考 DDD 分层架构模型来设计微服务代码模型

DDD学习笔记 - 实战篇(Ⅰ)_第17张图片

回顾一下DDD 分层架构模型:

  • 用户接口层:面向前端提供服务适配,面向资源层提供资源适配。这一层聚集了接口适配相关的功能。
  • 应用层职责:实现服务组合和编排,适应业务流程快速变化的需求。这一层聚集了应用服务和事件相关的功能。
  • 领域层:实现领域的核心业务逻辑。这一层聚集了领域模型的聚合、聚合根、实体、值对象、领域服务和事件等领域对象,以及它们组合所形成的业务能力。
  • 基础层:贯穿所有层,为各层提供基础资源服务。这一层聚集了各种底层资源相关的服务和能力。

业务逻辑从领域层、应用层到用户接口层逐层封装和协作,对外提供灵活的服务,既实现了各层的分工,又实现了各层的协作。因此,毋庸置疑,DDD 分层架构模型就是设计微服务代码模型的最佳依据。

 

微服务代码模型

DDD 并没有给出标准的代码模型,不同的人会有不同理解。下面这个微服务代码模型主要考虑的是微服务的边界、分层以及架构演进。

 

微服务一级目录结构

微服务一级目录是按照 DDD 分层架构的分层职责来定义的。下面这张图中可以看到,在代码模型里分别为用户接口层、应用层、领域层和基础层,建立了 interfaces、application、domain 和 infrastructure 四个一级代码目录。其职能形态如下:

DDD学习笔记 - 实战篇(Ⅰ)_第18张图片

  • Interfaces(用户接口层):它主要存放用户接口层与前端交互、展现数据相关的代码。前端应用通过这一层的接口,向应用服务获取展现所需的数据。这一层主要用来处理用户发送的 Restful 请求,解析用户输入的配置文件,并将数据传递给 Application 层。数据的组装、数据传输格式以及 Facade 接口等代码都会放在这一层目录里。
  • Application(应用层):它主要存放应用层服务组合和编排相关的代码。应用服务向下基于微服务内的领域服务或外部微服务的应用服务完成服务的编排和组合,向上为用户接口层提供各种应用数据展现支持服务。应用服务和事件等代码会放在这一层目录里。
  • Domain(领域层):它主要存放领域层核心业务逻辑相关的代码。领域层可以包含多个聚合代码包,它们共同实现领域模型的核心业务逻辑。聚合以及聚合内的实体、方法、领域服务和事件等代码会放在这一层目录里。
  • Infrastructure(基础层):它主要存放基础资源服务相关的代码,为其它各层提供的通用技术能力、三方软件包、数据库服务、配置和基础资源服务的代码都会放在这一层目录里。

 

各层目录结构

1. 用户接口层

Interfaces 的代码目录结构有:assembler、dto 和 façade 三类。

DDD学习笔记 - 实战篇(Ⅰ)_第19张图片

  • Assembler:实现 DTO 与领域对象之间的相互转换和数据交换。一般来说 Assembler 与 DTO 总是一同出现。
  • Dto:它是数据传输的载体,内部不存在任何业务逻辑,可以通过 DTO 把内部的领域对象与外界隔离。
  • Facade:提供较粗粒度的调用接口,将用户请求委派给一个或多个应用服务进行处理。

2. 应用层

Application 的代码目录结构有:event 和 service。

DDD学习笔记 - 实战篇(Ⅰ)_第20张图片

  • Event(事件):这层目录主要存放事件相关的代码。它包括两个子目录:publish 和 subscribe。前者主要存放事件发布相关代码,后者主要存放事件订阅相关代码(事件处理相关的核心业务逻辑在领域层实现)。这里提示一下:虽然应用层和领域层都可以进行事件的发布和处理,但为了实现事件的统一管理,建议将微服务内所有事件的发布和订阅的处理都统一放到应用层,事件相关的核心业务逻辑实现放在领域层。通过应用层调用领域层服务,来实现完整的事件发布和订阅处理流程。
  • Service(应用服务):这层的服务是应用服务。应用服务会对多个领域服务或外部应用服务进行封装、编排和组合,对外提供粗粒度的服务。应用服务主要实现服务组合和编排,是一段独立的业务逻辑。可以将所有应用服务放在一个应用服务类里,也可以把一个应用服务设计为一个应用服务类,以防应用服务类代码量过大。

3. 领域层

Domain 是由一个或多个聚合包构成,共同实现领域模型的核心业务逻辑。聚合内的代码模型是标准和统一的,包括:entity、event、repository 和 service 四个子目录。

DDD学习笔记 - 实战篇(Ⅰ)_第21张图片

  • Aggregate(聚合):它是聚合软件包的根目录,可以根据实际项目的聚合名称命名,比如权限聚合。在聚合内定义聚合根、实体和值对象以及领域服务之间的关系和边界。聚合内实现高内聚的业务逻辑,它的代码可以独立拆分为微服务。以聚合为单位的代码放在一个包里的主要目的是为了业务内聚,而更大的目的是为了以后微服务之间聚合的重组。聚合之间清晰的代码边界,可以轻松地实现以聚合为单位的微服务重组,在微服务架构演进中有着很重要的作用。
  • Entity(实体):它存放聚合根、实体、值对象以及工厂模式(Factory)相关代码。实体类采用充血模型,同一实体相关的业务逻辑都在实体类代码中实现。跨实体的业务逻辑代码在领域服务中实现。
  • Event(事件):它存放事件实体以及与事件活动相关的业务逻辑代码。
  • Service(领域服务):它存放领域服务代码。一个领域服务是多个实体组合出来的一段业务逻辑。可以将聚合内所有领域服务都放在一个领域服务类中,也可以把每一个领域服务设计为一个类。如果领域服务内的业务逻辑相对复杂,建议将一个领域服务设计为一个领域服务类,避免由于所有领域服务代码都放在一个领域服务类中,而出现代码臃肿的问题。领域服务封装多个实体或方法后向上层提供应用服务调用。
  • Repository(仓储):它存放所在聚合的查询或持久化领域对象的代码,通常包括仓储接口和仓储实现方法。为了方便聚合的拆分和组合,设定了一个原则:一个聚合对应一个仓储。

特别说明:按照 DDD 分层架构,仓储实现本应该属于基础层代码,但为了在微服务架构演进时,保证代码拆分和重组的便利性,把聚合仓储实现的代码放到了聚合包内。这样,如果需求或者设计发生变化导致聚合需要拆分或重组时,就可以将包括核心业务逻辑和仓储代码的聚合包整体迁移,轻松实现微服务架构演进。

4. 基础层

Infrastructure 的代码目录结构有:config 和 util 两个子目录。

DDD学习笔记 - 实战篇(Ⅰ)_第22张图片

  • Config:主要存放配置相关代码。
  • Util:主要存放平台、开发框架、消息、数据库、缓存、文件、总线、网关、第三方类库、通用算法等基础代码,可以为不同的资源类别建立不同的子目录。

 

代码模型总目录结构

在完成一级和二级代码模型设计后,就可以看到下图这样的微服务代码模型的总目录结构了。

DDD学习笔记 - 实战篇(Ⅰ)_第23张图片

强调两点内容:

第一点:聚合之间的代码边界一定要清晰。聚合之间的服务调用和数据关联应该是尽可能的松耦合和低关联,聚合之间的服务调用应该通过上层的应用层组合实现调用,原则上不允许聚合之间直接调用领域服务。这种松耦合的代码关联,在以后业务发展和需求变更时,可以很方便地实现业务功能和聚合代码的重组,在微服务架构演进中将会起到非常重要的作用。

第二点:一定要有代码分层的概念。写代码时一定要搞清楚代码的职责,将它放在职责对应的代码目录内。应用层代码主要完成服务组合和编排,以及聚合之间的协作,它是很薄的一层,不应该有核心领域逻辑代码。领域层是业务的核心,领域模型的核心逻辑代码一定要在领域层实现。如果将核心领域逻辑代码放到应用层,基于 DDD 分层架构模型的微服务慢慢就会演变成传统的三层架构模型了。

 

 

 

 

 

 

 

你可能感兴趣的:(架构,DDD,领域驱动设计)