关于 ddd-refactor
一种面向现有代码的 DDD 重构指导方法,先识别代码异味和目标模式,再规划保持行为不变的小步修改。适用于已确定重构方向的开发者。
主要功能
- 01将代码异味对应到目标模式
- 02规划保持行为的小步重构
- 03提供常见 DDD 改造步骤
- 04建议逐步测试并提交
适用场景
- 01将贫血模型改为行为实体
- 02把基本类型封装为值对象
- 03拆分过大的聚合
- 04逐步建立限界上下文
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-refactor安装后在 Claude Code 中输入/ddd-refactor确认已加载。
详细介绍
一句话总结
规划一系列面向 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 章)。