Claude-howto code-refactor
基于 Martin Fowler 方法论的系统化代码重构 skill。适用于用户请求重构代码、改进代码结构、减少技术债、清理旧代码、消除 code smell 或提升可维护性时。这个 skill 采用分阶段、带研究与计划的安全增量实施方式。
git clone https://github.com/luongnv89/claude-howto
T=$(mktemp -d) && git clone --depth=1 https://github.com/luongnv89/claude-howto "$T" && mkdir -p ~/.claude/skills && cp -r "$T/zh/03-skills/refactor" ~/.claude/skills/luongnv89-claude-howto-code-refactor-f77d09 && rm -rf "$T"
zh/03-skills/refactor/SKILL.md代码重构 Skill
这是一个基于 Martin Fowler《Refactoring: Improving the Design of Existing Code》(第 2 版)的系统化代码重构方法。这个 skill 强调安全、渐进的修改,并由测试提供保障。
“重构是在不改变软件外部行为的前提下,改进其内部结构的过程。” — Martin Fowler
核心原则
- 保持行为不变:外部行为必须保持一致
- 小步前进:每次只做很小、可测试的改动
- 测试驱动:测试是安全网
- 持续进行:重构是长期过程,不是一次性任务
- 协作确认:每个阶段都需要用户确认
工作流程总览
阶段 1:研究与分析 ↓ 阶段 2:测试覆盖评估 ↓ 阶段 3:识别代码异味 ↓ 阶段 4:创建重构计划 ↓ 阶段 5:增量实施 ↓ 阶段 6:评审与迭代
阶段 1:研究与分析
目标
- 理解代码库结构和用途
- 确定重构范围
- 收集业务需求背景
先向用户确认的问题
开始前先确认:
- 范围:哪些文件 / 模块 / 函数需要重构?
- 目标:你想解决什么问题?(可读性、性能、可维护性)
- 约束:有哪些区域不能改?
- 时间压力:这是否阻塞了其他工作?
- 测试状态:是否已有测试?是否通过?
行动
- 阅读并理解目标代码
- 识别依赖和集成点
- 记录当前架构
- 标记已有技术债迹象(TODO、FIXME)
输出
向用户汇报:
- 代码结构总结
- 识别出的问题区域
- 初步建议
- 请求继续执行的批准
阶段 2:测试覆盖评估
为什么测试重要
“没有测试的重构,就像没有安全带就开车。” — Martin Fowler
测试是安全重构的关键前提。没有测试,很容易引入 bug。
评估步骤
-
检查现有测试
# 查找测试文件 find . -name "*test*" -o -name "*spec*" | head -20 -
运行现有测试
# JavaScript / TypeScript npm test # Python pytest -v # Java mvn test -
检查覆盖率(如果可用)
# JavaScript npm run test:coverage # Python pytest --cov=.
决策点:询问用户
如果测试存在且通过:
- 进入阶段 3
如果测试缺失或不完整: 给出选项:
- 先写测试(推荐)
- 在重构过程中逐步补测试
- 不写测试直接继续(有风险,需要用户确认)
如果测试失败:
- 停止。先修复失败测试再重构
- 问用户:是否先修测试?
测试编写建议(如需要)
对每个要重构的函数,测试应覆盖:
- 正常路径
- 边界情况(空输入、null、边界值)
- 错误场景(非法输入、异常)
使用“红-绿-重构”循环:
- 写失败测试(红)
- 让它通过(绿)
- 再重构
阶段 3:识别代码异味
什么是代码异味?
代码深层问题的表面症状。它们不一定是 bug,但说明代码设计可能有问题。
常见异味清单
完整目录见 references/code-smells.md。
快速参考
| 异味 | 迹象 | 影响 |
|---|---|---|
| 长函数 | 函数超过 30-50 行 | 难以理解、测试和维护 |
| 重复代码 | 多处出现相同逻辑 | 修复需要改多处 |
| 大类 | 类承担了太多职责 | 违反单一职责原则 |
| Feature Envy | 一个方法更多依赖别的类的数据 | 封装性差 |
| 基础类型沉迷 | 过度使用基础类型而不是对象 | 缺少领域概念 |
| 长参数列表 | 方法参数超过 4 个 | 调用困难 |
| 数据泥团 | 一组数据总是一起出现 | 缺少抽象 |
| switch 语句 | 复杂的 switch / if-else 链 | 难以扩展 |
| 臆想泛化 | “以防未来需要”提前设计 | 不必要的复杂度 |
| 死代码 | 未使用的代码 | 造成困惑和维护负担 |
分析步骤
-
自动分析(如果有脚本)
python scripts/detect-smells.py <file> -
人工审查
- 系统地走读代码
- 记录每个异味的位置和严重性
- 按影响分类(Critical / High / Medium / Low)
-
优先级排序 优先关注会:
- 阻塞当前开发的异味
- 导致 bug 或混淆的异味
- 影响最常变更代码路径的异味
输出:异味报告
向用户呈现:
- 识别出的异味及位置
- 每项的严重性评估
- 建议的优先级顺序
- 请求用户确认优先级
阶段 4:创建重构计划
选择重构方式
针对每个异味,从目录中选择合适的重构手法。
完整列表见 references/refactoring-catalog.md。
异味到重构的映射
| 代码异味 | 推荐重构 |
|---|---|
| 长函数 | Extract Method、Replace Temp with Query |
| 重复代码 | Extract Method、Pull Up Method、Form Template Method |
| 大类 | Extract Class、Extract Subclass |
| Feature Envy | Move Method、Move Field |
| 基础类型沉迷 | Replace Primitive with Object、Replace Type Code with Class |
| 长参数列表 | Introduce Parameter Object、Preserve Whole Object |
| 数据泥团 | Extract Class、Introduce Parameter Object |
| switch 语句 | Replace Conditional with Polymorphism |
| 臆想泛化 | Collapse Hierarchy、Inline Class、Remove Dead Code |
| 死代码 | Remove Dead Code |
计划结构
使用 templates/refactoring-plan.md 里的模板。
每项重构都要写明:
- Target:将修改哪些代码
- Smell:解决什么问题
- Refactoring:采用哪种手法
- Steps:详细微步骤
- Risks:可能出什么问题
- Rollback:如何回退
分阶段方法
关键:重构必须分阶段推进。
阶段 A:快速收益(低风险,高价值)
- 重命名变量以提升清晰度
- 提取明显重复的代码
- 删除死代码
阶段 B:结构改进(中风险)
- 从长函数中提取方法
- 引入参数对象
- 把方法移动到更合适的类
阶段 C:架构改动(高风险)
- 用多态替代条件分支
- 提取类
- 引入设计模式
决策点:把计划展示给用户
在开始实施前:
- 展示完整重构计划
- 解释每个阶段及其风险
- 获得每个阶段的明确批准
- 询问:“是否继续执行阶段 A?”
阶段 5:增量实施
黄金法则
“修改 → 测试 → 通过?→ 提交 → 下一步”
实施节奏
对每一步重构:
-
预检查
- 测试通过(绿色)
- 代码能编译
-
只做一个小改动
- 按目录中的具体操作进行
- 保持改动最小化
-
验证
- 立刻运行测试
- 检查编译错误
-
如果测试通过(绿色)
- 用描述清晰的提交信息提交
- 继续下一步
-
如果测试失败(红色)
- 立刻停止
- 撤销改动
- 分析原因
- 如有疑问,询问用户
提交策略
每次提交都应当:
- 原子性:只包含一个逻辑改动
- 可回滚:容易撤销
- 描述清楚:提交信息明确
示例提交信息:
refactor: 从 processOrder() 中提取 calculateTotal() refactor: 将 'x' 重命名为 'customerCount' 以提升清晰度 refactor: 删除未使用的 validateOldFormat() 方法
进度汇报
每个子阶段完成后,向用户汇报:
- 做了哪些改动
- 测试是否仍通过
- 遇到了什么问题
- 询问:“继续下一批吗?”
阶段 6:评审与迭代
重构后检查清单
- 所有测试通过
- 没有新的警告 / 错误
- 代码编译成功
- 行为没有变化(手动验证)
- 必要时已更新文档
- 提交历史干净
指标对比
重构前后运行复杂度分析:
python scripts/analyze-complexity.py <file>
展示改进:
- 代码行数变化
- 圈复杂度变化
- 可维护性指标变化
用户评审
向用户展示最终结果:
- 所有变更摘要
- 重构前后代码对比
- 指标改善情况
- 剩余技术债
- 询问:“你对这些改动满意吗?”
下一步
和用户讨论:
- 还要处理哪些异味?
- 是否安排下一次重构?
- 是否把类似修改应用到其他地方?
重要指南
何时暂停并询问
遇到以下情况时,务必暂停并和用户确认:
- 不确定业务逻辑
- 改动可能影响外部 API
- 测试覆盖不足
- 需要做重大的架构决策
- 风险上升
- 遇到意外复杂性
安全规则
- 没有测试不要重构(除非用户明确确认风险)
- 不要做大改动,拆成小步
- 每次改动后都不要跳过测试
- 测试失败就不要继续,先修复或回滚
- 不要臆测,不确定就问
不要做什么
- 不要把重构和新功能混在一起
- 不要在生产事故期间做重构
- 不要重构你看不懂的代码
- 不要过度设计,保持简单
- 不要一次性重构所有内容
快速上手示例
场景:长函数 + 重复逻辑
重构前:
function processOrder(order) { // 150 行代码,包含: // - 重复验证逻辑 // - 内联计算 // - 多种职责混杂 }
重构步骤:
- 确认测试存在,覆盖
processOrder() - 提取 验证逻辑为
validateOrder() - 测试 - 应该通过
- 提取 计算逻辑为
calculateOrderTotal() - 测试 - 应该通过
- 提取 通知逻辑为
notifyCustomer() - 测试 - 应该通过
- 评审 -
现在只负责串联 3 个清晰函数processOrder()
重构后:
function processOrder(order) { validateOrder(order); const total = calculateOrderTotal(order); notifyCustomer(order, total); return { order, total }; }
参考资料
脚本
- 分析代码复杂度指标scripts/analyze-complexity.py
- 自动检测 code smellscripts/detect-smells.py
版本历史
- v1.0.0 (2025-01-15):首次发布,包含 Fowler 方法论、分阶段流程和用户确认点