0
引子
蔺相如
司马相如
名相如
实不相如
TDD
DDD
名DD
实亦DD
TDD和DDD虽然都叫XDD,那也只是名字有部分重复而已,一个来自xp实践,一个来自架构设计,除了都是技术实践外,风马牛不相及啊,放在一起谈会不会是关公战秦琼啊?
1
TDD VS DDD
其实还真不是,它俩之间还真是有内在的联系。
TDD
TDD顾名思义,是指测试用例驱动设计实现,测试用例从某种意义上来说,是代表需求的,用例的开发过程分为:
需求场景化(拆分为场景,拆分方式一般为
按类型拆分
按工作流拆分
按simple-》complex拆分
场景实例化(找出符合场景的定义域里面的某一组或多组状态集合)
场景代码化(定义出接口并对接口进行编排,接口中使用实例化场景中的状态集合)三个步骤来设计并驱动出用例,通过用例驱动出接口
接口原型
接口事前条件
接口事后条件
并对接口进行编排和调用;
然后通过接口驱动出代码实现,并用红绿蓝中的红绿原则来判断用例的代码实现是否正确,通过baby step的反复重构使得代码架构和代码风格达到简单设计和clean code的程度,从而代码变得像海水一样湛蓝湛蓝的。
湛蓝的代码满足以下的原则:
消除重复
分离关注点
缩小依赖范围
向稳定的方向依赖。
DDD
DDD顾名思义,指的是领域驱动设计,通过领域建模的方式把系统分为问题域和解决方案域,并在问题域进行统一语言设计和子域划分;在解决方案域中划分BC&BCMAP,然后划分DDD核心六要素,并把六要素合理分布到分层架构中,参见下图:
两者之间是有结合点的,主要结合点如下:
TDD对需求拆分的时候,可以驱动出DDD的BC和聚合的划分
TDD场景代码化中接口设计和对接口编排调用时,可以驱动出DDD分层架构Application层中App接口+Domain层中的service接口+Domain层中的仓储接口
重构时实现仓储接口抽象+仓储隔离+代码元素移植到分层架构各个层中。
下面以一个实例来分享下TDD对DDD的驱动过程:
2
一个实例
产品需求:
从零开始,驱动架构
首先选择可以影响架构的关键需求,便于驱动出架构,这里选择两个需求:
1、用户注册
货主注册
骑手注册
2、货单撮合
货主发货
骑手抢单
这两个需求也涵盖了用户和订单这两个聚合。
分步骤实施采用TDD方式开发(以java代码演示,重点展示测试用例和代码分层架构,实现代码略;其他编程语言可以参照实现)
步骤一
编写并跑通货主注册用例
类&文件
步骤二
隔离用户仓储依赖,生成仓储依赖注入点
步骤三
生成分层架构
纵向分层目录结构
test/main
application
domain
infrastructure
层内横向目录结构
增加用户模块
增加公共库模块
步骤四
补充骑手注册用例并实现跑通
补充判断用户类别用例
添加用户类别
跑通判断用户类别用例
步骤五
补充和实现骑手接收到代抢货单用例
步骤六
增加订单创建存储获取用例
实现订单仓储
实现订单创建存储获取用例
增加订单模块
步骤七
抽象订单仓储接口
注入点增加订单仓储注入,隔离订单仓储直接依赖
分离用户仓储接口中存储接口和消息处理接口
步骤八
抽象存储仓储接口
上移存储实现
用户的持久化和货单持久化逻辑完全一致,只不过持久化的数据类型不一致而已,这里通过模板进行抽象,对于不支持模板的语言可以通过组合+委托实现。
步骤九
补充抢单用例
完善骑手状态
完善订单状态
通过以上九步TDD step把整个系统的DDD架构驱动出来了。
(如果需要完整参考代码,可以和我私下联系。)
3
效果
这种方法驱动出来的代码架构天然就是clean architecture的架构,相关架构依赖情况如下(DSM(Design structure matrix),右上角如果有值,则为违规依赖,数值越大,违规越多。):
分层架构和Domain目录之间的依赖关系
Domain层中类之间的依赖关系
目录之间依赖关系(上层可以依赖下层,下层不可以依赖上层)
DDD代码架构规则
综上,使用TDD驱动出来的代码架构层次清晰,代码元素高内聚低耦合,目录、类、文件、接口、都出现在期望出现的位置;上层依赖下层,下层不依赖上层,没有反向依赖;同一层中没有直接依赖(通过上层实现调度和协作 );易于维护、易于理解,使得系统在很长的时间内都变得很容易变更。
4
小结
通过TDD用例设计+重构,把DDD核心设计要素和理念融合进来,实现两者的无缝有机融合。跟传统的DDD相比,TDD先把用例写出来,代码快速实现,然后重构的思路可以让软件人员看着已经存在的设计和代码一步步重构,即知识显式表达。相当于在草稿纸上不停的演算,耳听为虚眼见为实,极大降低了DDD设计的抽象性和复杂度,是DDD设计一个重要的脚手架和加速器。
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/213226.html