目录
领域驱动实践总结三:具体应用设计分析
一、应用项目的基本背景
二、针对项目进行领域驱动的战略设计阶段
(一)事件风暴确定产品愿景
(二)事件风暴进行业务场景分析
场景分析一:请假 用户:请假人
场景分析二:审批 用户:审批人
场景分析三:人员组织关系 详细的分析过程以及考勤的场景分析就不描述了
(三)事件风暴进行领域建模
第一步:找出领域实体和值对象等领域对象
第二步:找出聚合根,根据实体、值对象与聚合根的依赖关系,建立聚合
第三步:根据业务及语义边界等因素,定义限界上下文
(四)事件风暴进行微服务的拆分
三、针对项目进行领域驱动的战术设计阶段
(一)分析微服务领域对象
1.具体服务的识别和设计
2.聚合中的对象分析
3.微服务内的对象清单
(二)设计微服务代码结构
1.应用层代码结构
2.领域层代码结构
(三)后续的工作:详细设计 + 代码开发和测试
1. 详细设计
2. 代码开发和测试
四、具体代码参考
参考书籍、文献和资料
领域驱动设计DDD是一种设计思想,它可以同时指导中台业务建模和微服务设计(中台本质是业务模型,微服务是业务模型的系统落地),领域驱动设计强调领域模型和微服务设计的一体性,先有领域模型然后才有微服务,而不是脱离领域模型来谈微服务设计。
微服务拆分困境产生的根本原因:不知道业务或者微服务的边界到底在什么地方。
DDD 核心思想:通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业务模型与代码模型的一致性。
对于领域驱动设计的学习做的总结主要写三篇博客,主要包括三部分:基本理论总结与分析、架构分析与代码设计、具体应用设计分析,主要参考的资料为极客时间的欧创新架构师的《DDD》实战,其他参考书籍在文章下方的参考书籍中。
本次主要总结DDD具体应用设计分析:
项目的目标是实现在线请假和考勤管理。功能描述如下:
备注:本想以大视频业务系统为背景自己弄一个的,但是时间太紧,暂时还是以欧创新架构师提供的案例做总结和分析理解,后期有时间会自己出一个关于视频系统的。
战略设计采用的方法是事件风暴,包括:产品愿景、场景分析、领域建模和微服务拆分等几个主要过程。
战略设计是根据用户旅程分析,找出领域对象和聚合根,对实体和值对象进行聚类组成聚合,划分限界上下文,建立领域模型的过程。
战略设计阶段建议参与人员:领域专家、业务需求方、产品经理、架构师、项目经理、开发经理和测试经理。
产品愿景是对产品顶层价值设计,对产品目标用户、核心价值、差异化竞争点等信息达成一致,避免产品偏离方向。
事件风暴时,所有参与者针对每一个要点,在贴纸上写出自己的意见,贴到白板上。
事件风暴主持者会对每个贴纸,讨论并对发散的意见进行收敛和统一,形成下面的产品愿景图。其实,也就是让所有人确定统一的大方向统一语言,我们究竟在干什么,目的和意义是什么等的基本问题。
产品愿景分析对于初创系统明确系统建设重点,统一团队建设目标和建立通用语言是很有价值的。
针对本项目,最后确定的产品愿景图整理成一段文字就是:
为了满足内外部人员,他们的在线请假、自动考勤统计和外部人员管理的需求,我们建设这个在线请假考勤系统,它是一个在线请假平台,可以自动考勤统计。它可以同时支持内外网请假,同时管理内外部人员请假和定期考勤分析,而不像 HR 系统,只管理内部人员,且只能内网使用。我们的产品内外网皆可使用,可实现内外部人员无差异管理。
达到的目的与意义:
通过产品愿景分析,项目团队统一了系统名称——在线请假考勤系统,明确了项目目标和关键功能,与竞品(HR)的关键差异以及自己的优势和核心竞争力等。
场景分析是从用户视角出发,探索业务领域中的典型场景,产出领域中需要支撑的场景分类、用例操作以及不同子域之间的依赖关系,用以支撑领域建模。
项目团队成员一起用事件风暴分析请假和考勤的用户旅程。
根据不同角色的旅程和场景分析,尽可能全面地梳理从前端操作到后端业务逻辑发生的所有操作、命令、领域事件以及外部依赖关系等信息。
以请假和人员场景作为示例------------
备注:完成审批后,产生请假审批已通过领域事件。后续有两个进一步的业务操作:发送请假审批已通过的通知,通知邮件系统告知请假人;将请假数据发送到考勤以便核销。
领域建模是通过对业务和问题域进行分析,建立领域模型。
向上通过限界上下文指导微服务边界设计,向下通过聚合指导实体对象设计。
领域建模是一个收敛的过程,分三步:
根据场景分析,分析并找出发起或产生这些命令或领域事件的实体和值对象,将与实体或值对象有关的命令和事件聚集到实体。
根据场景分析,分析并找出发起或产生这些命令或领域事件的实体和值对象,将与实体或值对象有关的命令和事件聚集到实体。
(注意表达中的名词和动词等,名词往往是实体、值对象等,动词往往对应着命令的相关行为)
定义聚合前,先找出聚合根。
从上面的实体中,我们可以找出“请假单”和“人员”两个聚合根。然后找出与聚合根紧密依赖的实体和值对象。我们发现审批意见、审批规则和请假单紧密关联,组织关系和人员紧密关联。
找出这些实体的关系后,我们发现还有刷卡明细、考勤明细和考勤统计,这几个实体没有聚合根。这种情形在领域建模时你会经常遇到,对于这类场景我们需要分情况特殊处理:
经过分析,我们建立了请假、人员组织关系和考勤三个聚合。其中请假聚合有请假单、审批意见实体和审批规则等值对象。人员组织关系聚合有人员和组织关系等实体。考勤聚合有刷卡明细、考勤明细和考勤统计等实体。
由于人员组织关系聚合与请假聚合,共同完成请假的业务功能,两者在请假的限界上下文内。
考勤聚合则单独构成考勤统计限界上下文。
因此我们为业务划分请假和考勤统计两个限界上下文,建立请假和考勤两个领域模型。
理论上一个限界上下文就可以设计为一个微服务,但还需要综合考虑多种外部因素,比如:职责单一性、敏态与稳态业务分离、非功能性需求(如弹性伸缩、版本发布频率和安全等要求)、软件包大小、团队沟通效率和技术异构等非业务要素。
在这个项目,我们划分微服务主要考虑职责单一性原则。
因此根据限界上下文就可以拆分为请假和考勤两个微服务。其中请假微服务包含人员组织关系和请假两个聚合,考勤微服务包含考勤聚合。
战术设计是根据领域模型进行微服务设计的过程。这个阶段主要梳理微服务内的领域对象,梳理领域对象之间的关系,确定它们在代码模型和分层架构中的位置,建立领域模型与微服务模型的映射关系,以及服务之间的依赖关系。
战术设计阶段建议参与人员:领域专家、产品经理、架构师、项目经理、开发经理和测试经理等。战术设计包括以下阶段:
在事件风暴基础上,我们进一步细化领域对象以及它们的关系,补充事件风暴可能遗漏的业务和技术细节:
事件风暴的命令是外部的一些操作和业务行为,也是微服务对外提供的能力。它往往与微服务的应用服务或者领域服务对应。我们可以将命令作为服务识别和设计的起点。
具体步骤如下:
以提交审批这个动作为例,来说明服务的识别和设计。提交审批的大体流程是:
通过分析,我们需要在应用层和领域层设计以下服务和方法。
在请假单聚合中,聚合根是请假单。
请假聚合有以下实体:审批意见(记录审批人、审批状态和审批意见)和请假事件实体。
再来分析一下请假单聚合的值对象。
请假单聚合将包含以下值对象:请假人、人员类型、请假类型、下一审批人、审批状态和审批规则。
-----------------------------------------------------------------------------------------------------------------------------------------------------
人员组织关系聚合中,我们可以建立人员之间的组织关系,通过组织关系类型找到上级审批领导。
它的聚合根是人员,实体有组织关系(包括组织关系类型和上级审批领导),其中组织关系类型(如项目经理、处长、总经理等)是值对象。上级审批领导来源于人员聚合根,可设计为值对象。人员组织关系聚合将包含以下值对象:组织关系类型、上级审批领导。
在确定各领域对象的属性后,我们就可以设计各领域对象在代码模型中的代码对象(包括代码对象的包名、类名和方法名),建立领域对象与代码对象的一一映射关系了。
根据这种映射关系,相关人员可快速定位到业务逻辑所在的代码位置。
根据 DDD 的代码模型和各领域对象所在的包、类和方法,可以定义出请假微服务的代码结构,设计代码对象。
应用层包括:应用服务、DTO 以及事件发布相关代码。
在 LeaveApplicationService 类内实现与聚合相关的应用服务,在 LoginApplicationService 封装外部微服务认证和权限的应用服务。
(提醒一下:如果应用服务逻辑复杂的话,一个应用服务就可以构建一个类,这样可以避免一个类的代码过于庞大,不利于维护。)
领域层包括一个或多个聚合的实体类、事件实体类、领域服务以及工厂、仓储相关代码。
一个聚合对应一个聚合代码目录,聚合之间在代码上完全隔离,聚合之间通过应用层协调。
请假微服务领域层包含请假和人员两个聚合。人员和请假代码都放在各自的聚合所在目录结构的代码包中。
如果随着业务发展,人员相关功能需要从请假微服务中拆分出来,我们只需将人员聚合代码包稍加改造,独立部署,即可快速发布为人员微服务。
在完成领域模型和微服务设计后,我们还需要对微服务进行详细的设计。
主要设计以下内容:实体属性、数据库表和字段、实体与数据库表映射、服务参数规约及功能实现等。
开发人员只需要按照详细的设计文档和功能要求,找到业务功能对应的代码位置,完成代码开发就可以了。
代码开发完成后,开发人员要编写单元测试用例,基于挡板模拟依赖对象完成服务测试。
本次的总结都是按照极客时间课程《DDD实战》欧创新架构师的举例项目来进行的,相关代码可以克隆其代码:
https://github.com/ouchuangxin/leave-sample.git
后期在其基础上会有补充,以及对于视频系统的项目分析,后续博客中公布。
1.极客时间课程《DDD实战》,欧创新,2019.
2.郑天民. 微服务设计原理与架构. 北京:人民邮电出版社,2018.