领域驱动设计DDD|从入门到代码实践
阿里妹导读
在本文中,作者将借鉴《实现领域驱动设计》的做法,介绍领域驱动设计的基本概念的同时,用一个虚拟的公司和一个虚拟的项目,把领域驱动设计进行落地实践。
背景
为什么要写这篇文章
虚拟的业务场景
本文的代码
本文的行文逻辑
DDD是什么
MVC模式
MVC模式仅仅反应了软件层面的架构,它不包含业务语言,无法使用该设计直接和业务对话。
MVC模式天然切割了数据和行为,然后用数据库实现数据,用服务实现行为,容易造成需求的首尾分离。
缺乏明确的边界划分,至少在顶层设计层面没有边界划分的规范要求,更多地是靠技术负责人根据经验进行划分,大规模团队协作容易出现职责不清晰、分工不明确。
DDD定义
通过模型直接反映软件实现的结构。 以模型为基础形成团队的统一语言。 把模型作为精粹的知识,用于传递。
DDD的价值
统一语言:
面向业务建模:
边界清晰的设计方法:
业务领域的知识沉淀:
DDD的基本概念
统一语言
用户(User)是指所有在“智慧课堂”注册过的人。(来自领域模型概念)
订阅的专栏(Subscription)是指用户付费过的专栏。(来自领域模型概念)
用户可以订阅多个专栏。(来自领域模型逻辑)
订阅。(来自限界上下文)
战略设计
领域
子域
核心域
通用域
支撑域
限界上下文
战术设计
实体
失血模型:模型仅仅包含数据的定义和getter/setter方法,业务逻辑和应用逻辑都放到服务层中。这种类在Java中叫POJO。
贫血模型:贫血模型中包含了一些业务逻辑,但不包含依赖持久层的业务逻辑。这部分依赖于持久层的业务逻辑将会放到服务层中。
充血模型:充血模型中包含了所有的业务逻辑,包括依赖于持久层的业务逻辑。
胀血模型:胀血模型就是把和业务逻辑不想关的其他应用逻辑(如授权、事务等)都放到领域模型中。
值对象
聚合和聚合根
工厂
资源库
领域服务
领域事件
领域建模
领域模型:包含领域对象、属性、关系、行为、边界范围等各个方面,用于描述业务的本质,这也是最重要的产出物。
用例图:用于明确系统的功能。
数据模型:描述系统的数据结构和关系,包括实体关系模型、关系数据库模型等。
状态图:用于描述系统各个状态及其转移条件。
活动图:用于描述系统流程中的各个活动及其关系。
序列图:描述系统中各个对象之间的交互过程和消息传递序列。
架构模型:包含系统的物理和逻辑结构,包括组件、模块、接口等。
事件风暴建模
简介
事件风暴语法
行动者(Actors)是系统的使用者。这里使用者是一个相对模糊的概念,可能是现实中的人也可能是别的系统;
命令(Command)是由行动者发起的行为。它代表了某种决定,通常是事件的起因,也称作行动者触发命令(AIC,Actor Initiated Command);
事件(Event)就是我们前文讨论过的事件;
系统(System)指代的是不需要了解细节的三方系统。因为不需要了解细节,所以我们可以将它们看作一个整体;
阅读模型(Read Model)用以支撑决策的信息。通常与界面布局有关;
策略(Policy)是对于事件的响应,通过策略可以触发新的命令,由策略触发的命令,被称作系统触发命令(SIC,System Initiated Command)。
热点问题(HotSpot)是业务痛点,瓶颈,模糊点。如果有争论,可以将双方观点用热点问题的形式记录。
事件风暴操作流程
准备工作
开场介绍
事件风暴的方式沟通业务
第一步:梳理事件(橙色贴纸)
第二步:业务规则(粉色贴纸)
订单已创建的前提条件是专栏可订阅,同时用户未订阅过该专栏。 订单创建后,会导致发起支付。
第三步:行动者(浅黄色贴纸),命令(蓝色贴纸)、阅读模型(绿色贴纸)和系统(紫色贴纸)
第四步:热点问题(红色贴纸)
第五步:故事串讲
第六步:产出架构
事件风暴小结
四色建模法
简介
如果有现金收入,表示承担了义务。拿钱办事,需要收集证据,说明义务履约成功。
如果有现金支出,表明拥有权利。花钱消灾,需要检查对方是否按时履约。
对于没有现金往来的,可以通过目标——实际对比,产生类似履约的约束。所谓目标——实际对比,就是设立一个目标 / 计划,然后追踪实际执行的结果。
四色建模法语法
四色建模法操作流程
Step1: 寻找关键现金往来,构造一个凭证表示它。然后在凭证上罗列关键数据项,主要有发生的时间点、金额等
Step2: 针对每一项关键数据项,寻找它的来源。来源只能有三个:用户输入,由前序凭证提供,或者根据算法计算。我们需要以此为依据去寻找前序凭证
Step3: 回到现金凭证,思考它所对应的权利与责任。这些权利与责任需要哪些凭证证明,并以此为依据,寻找后续凭证
Step4: 无论是何种凭证,必须罗列关键数据项,并保证数据项获取的顺畅
Step5: 如果与现金往来关联不大,那么寻找关键KPI指标,并构造一个验收凭证表示它。其余步骤与现金往来一致
Step6: 在获取了相互关联的凭证流之后(实际就是事件流),我们可以进入模型细化阶段,围绕每个凭证,寻找参与其中的角色
Step7: 思考哪些参与方可能扮演这些角色,并将他们加入模型中
Step8: 通过描述对象,为模型添加补充说明
寻找现金往来和凭证
寻找角色和参与者
获得领域模型
验证业务脊梁以及领域模型的有效性
四色建模法小结
落地实践
方案设计
领域模型
子域划分
限界上下文划分
用例图
状态机
活动图
时序图
ER图
代码实施
应用架构
应用模块分层
基本思想
为了保证核心业务逻辑的稳定,领域层应作为最纯粹、最少对外依赖的层次,只包含业务知识和业务规则,不该过多关心技术细节的实现(如存储、消息等)。
分层以领域层为核心来分层建设。
模块职责
测试套件(testsuite):
主程序(main):
接口门面层(facade):
接口门面实现层(facade-impl):
控制器层(controller):
应用层(application):
事务控制 查询仓储(注意:只能查询仓储,不能写仓储,写仓储是领域层的能力) 领域事件(domain event)的触发和监听 操作日志 安全认证
领域层(domain):
实体(entity) 值对象(value object) 领域服务(domain service) 领域事件(domain event) 仓储(repository)接口定义,读写仓储 依赖的外部服务(anti-corruption layer)的接口定义 工厂(factory)
仓储层(repository):
基础设施层(infrastructure):
工具层(utility):
编码规范
POJO规范【强制】
DO 数据库模型
Model 领域模型
DTO 外部传输对象
Info 内部传输对象
VO 值对象
Query 查询对象
Request 请求对象
Converter 转换器
Bean规范【强制】
Controller 控制器
Facade 门面服务
FacadeImpl 门面服务实现
AppService 应用层服务
DomainService 领域服务
Repository 仓储接口
RepositoryImpl 仓储接口实现
Mapper 数据库查询接口
Client 中间件服务依赖接口
ClientImpl 中间件服务依赖实现
FacadeClient 外部RPC服务依赖接口
FacadeClientImpl 外部RPC服务依赖实现
Configuration 配置
方法命名【建议】
Service/Repository/Client/DAO方法命名规约
获取单个对象的方法用query作前缀。 获取多个对象列表的方法用list作前缀,复数结尾,如:listObjects。 获取多个对象分页的方法用page作前缀,复数结尾,如:pageObjects。 获取统计值的方法用count作前缀。 插入的方法用insert作前缀。 删除的方法用delete作前缀。 修改的方法用update作前缀。
更多编码规范
编码规范多说两句
Saber工具
操作方法
在SaberConfig文件中修改一些配置,主要包括表前缀,包名,jdbc信息等。
在x文件夹下,写一个XXCommand的类,该类包含main函数,可以执行。在该类中指定表名,分页查询字段,枚举映射关系,忽略字段等配置。
运行上面写的XXCommand类,这时候就能在项目下看到自动生成的XXBaseMapper.xml, XXMapper.xml, XXBaseMapper.java, XXMapper.java, XXDO.java 五个文件。
进阶用法
项目演示
后记
直接面向业务进行领域建模,将业务知识沉淀到领域模型中。
业务知识的沉淀不是一蹴而就,应该反复提炼,持续演进;为了让演进提炼的过程高效顺畅,团队使用统一语言来沟通、描述需求和设计方案。
高内聚、低耦合是应对软件复杂度的不二法则。领域、子域、限界上下文、聚合都是为这条宗旨服务的工具。
致谢
参考引用
Eric Evans《领域驱动设计》 Vaughn Vernon《实现领域驱动设计》 徐昊《如何落地业务建模》 Erich Gamma《设计模式:可复用面向对象软件的基础》 EventStorming:https://www.eventstorming.com/ 迄今为止最完整的DDD实践:https://blog.csdn.net/AlibabaTech1024/article/details/125674376 聊一聊,我对DDD的关键理解:https://mp.weixin.qq.com/s/fDU6MuIKs4wu8WDcsHsDzw 事件风暴与领域建模在阿里的实践:https://developer.aliyun.com/live/2877 阿里技术专家详解 DDD 系列 第一讲- Domain Primitive:https://zhuanlan.zhihu.com/p/340911587 限界上下文:冲破微服务设计困局的利器-阿里云开发者社区:https://developer.aliyun.com/article/913758?accounttraceid=d2b6e0e9135d48468535232849a22b2ebcey 复杂度应对之道 - COLA应用架构_cola 扩展点_张建飞(Frank)的博客-CSDN博客:https://blog.csdn.net/significantfrank/article/details/85785565 从壹开始微服务 [ DDD ] 之三 ║ 简单说说:领域、子域、限界上下文 - 老张的哲学 - 博客园:https://www.cnblogs.com/laozhang-is-phi/p/9845573.html 领域驱动设计详解:是什么、为什么、怎么做?:https://zhuanlan.zhihu.com/p/164757995?utm_source=wechat_timeline 领域驱动设计(DDD)-基础思想:https://zhuanlan.zhihu.com/p/109114670 阿里巴巴开发规约:https://developer.aliyun.com/ebook/386
阿里云开发者社区,千万开发者的选择
阿里云开发者社区,百万精品技术内容、千节免费系统课程、丰富的体验场景、活跃的社群活动、行业专家分享交流,欢迎点击【阅读原文】加入我们。
微信扫码关注该文公众号作者