用途
本技能用于把已有代码逐步重构、迁移到领域驱动设计(DDD)方向。它适用于:用户已经认为某段现有代码是个问题、大致知道想往哪个方向重构,或者正在把遗留模块迁移到 DDD 模型。
不适用的情况:用户只想评审代码、还没准备重构(应改用 ddd-review);用户要从零开始建立新的领域模型(应改用 ddd-design)。
主要能力
技能提供通用的重构模式:说出坏味道、说出目标形态、写出保持行为不变的小步骤、每步之间运行测试、每步之后提交。
常见重构及其步骤序列:
- 贫血模型 → 行为实体:(1) 选一个当前由服务执行的操作。(2) 把它移到实体上,保持相同签名。(3) 让服务委托给新的实体方法。(4) 当服务调用是唯一调用者时,内联该服务调用。对每个操作重复。
- 基本类型偏执 → 值对象:(1) 引入新的值对象类型,带私有构造函数和校验工厂。(2) 在边界(输入解析处)添加单一转换点。(3) 一次替换一个用法,从最深层开始。(4) 不再允许该基本类型出现在公共 API 上。参见 ddd-value-object。
- 上帝聚合 → 多个聚合:(1) 列出当前包含的实体。(2) 对每一对实体问“它们必须在同一事务中变化吗?”——按回答“是”的分组。(3) 确定每组的根。(4) 用 ID 引用替换跨组对象引用。(5) 把跨组一致性移到事件上。参见 ddd-aggregate。
- 泄漏的仓储 → 领域仓储接口:(1) 定义领域层接口,方法用通用语言命名。(2) 在基础设施层实现它,包装现有持久化。(3) 一次切换一个调用者。(4) 从领域层删除泄漏的类型。参见 ddd-repository。
- 大泥球 → 首个限界上下文:(1) 选最痛的接缝。(2) 在纸上画出预期边界。(3) 在接缝处引入防腐层。(4) 一次一个类型地把代码移过接缝。接缝的模式参见 ddd-context-mapping。
使用方式与决策原则
- 绝不把重构提交与功能提交合并,二者应分别评审、分别回滚。
- 每一步都必须保持行为完全一致。测试套件是安全带;如果不存在,先编写特征测试。
- 每步之后停下来,运行测试并提交。
- 大爆炸式重写会失去用户信任,且几乎总会扩大范围。宁可做十个小重构,也不做一个大重构。
反模式
- 没有增量里程碑的大爆炸式重写。
- 没有测试网就重构。
- 把类改名“听起来像 DDD”,却不改变其结构或职责。
- 在同一次变更中既重构又添加功能。
相关主题
- ddd-anti-patterns:驱动每次重构的坏味道。
- ddd-aggregate、ddd-value-object、ddd-bounded-context、ddd-repository:目标形态。
- ddd-deeper-insight:明显重构完成后该做什么。
限制与未提供信息
资料未提供该技能的收费、价格、平台支持范围、具体安装命令、调用示例或效果数据,这些内容暂未提供。参考书目为 Evans《Domain-Driven Design》(2003) 第三部分(第 8–13 章)。