代码重构 refactoring

代码重构技能指南,提供系统化、小步迭代的代码重构方法论。核心内容包括重构时机判断、安全保护措施、分步重构技术、验证流程及反模式规避。适用于软件开发人员提升代码质量,关键词:代码重构、重构方法、代码异味、提取函数、重命名、卫语句、特征测试、重构安全、小步提交。

测试 0 次安装 0 次浏览 更新于 3/2/2026

name: refactoring description: 通过小步迭代进行系统化重构。当用户提到“重构”、“清理”、“重组”、“提取”、“重命名”、“简化”或识别到代码异味时使用。强制执行“一次变更 → 测试 → 提交”的循环。用于结构改进,而非样式/格式化(请使用 /lint)。不用于添加新功能或修复错误。 allowed-tools: ‘*’

重构

在不改变行为的前提下改进代码结构。一次一小步。

铁律: 一次重构 → 测试 → 提交。绝不批量更改。

何时使用

按顺序回答。在第一个匹配项处停止:

  1. 用户说“重构”、“清理”、“重组”? → 使用此技能
  2. 用户要求“提取”、“重命名”、“简化”? → 使用此技能
  3. 识别到代码异味? → 使用此技能
  4. 用户想要添加功能或修复错误? → 跳过(使用 tdd-enforcer)
  5. 用户想要格式化/样式修复? → 跳过(使用 /lint)

代码异味(常见触发点):

  • 重复代码(相同逻辑出现在多个地方)
  • 过长函数(>30行,做太多事)
  • 魔法数字/字符串(未解释的字面量)
  • 深层嵌套(>3层缩进)
  • 死代码(未使用的函数、无法到达的分支)
  • 命名不佳(不清楚某物是做什么的)

阶段 1:评估

这真的是重构吗?

用户意图 操作
“让这个更干净” ✓ 重构
“添加验证” ✗ 新行为 → tdd-enforcer
“修复这个错误” ✗ 错误修复 → tdd-enforcer 或 systematic-debugger
“格式化这段代码” ✗ 样式 → /lint

如果不是重构: 解释并建议正确方法。


阶段 2:保护

代码有测试吗?

覆盖率 操作
测试良好 跳转到阶段 3
部分覆盖 为未测试部分添加特征测试
没有测试 首先添加特征测试

特征测试

在重构前捕获当前行为:

// 特征测试 - 捕获实际行为
it('processOrder 返回当前行为', () => {
  const result = processOrder({ items: [], user: null });
  // 它现在返回什么,就是期望值
  expect(result).toEqual({ status: 'empty', total: 0 });
});

目的: 安全网,而非规范。测试代码“做了什么”,而不是它“应该做什么”。


阶段 3:重构

铁律: 一次只做一个重构。每次更改后运行测试。

重构目录

第 1 层 - 始终安全(不可能改变行为):

异味 重构方法 示例
名称不清晰 重命名 ddiscountAmount
函数过长 提取函数 将 10 行代码提取到 calculateTax()
不必要的变量 内联变量 移除 temp = x; return temp;
代码位置不当 移动函数 validate() 移动到 Validator
// ❌ 之前:名称不清晰
const d = price * 0.2;

// ✅ 之后:重命名
const discountAmount = price * 0.2;

第 2 层 - 有测试则安全(如果存在测试则风险低):

异味 重构方法 示例
重复表达式 提取变量 order.items.length > 0const hasItems = ...
复杂条件判断 分解条件判断 if 分支提取到命名函数中
嵌套条件判断 卫语句 使用提前返回替代深层嵌套
魔法字面量 替换魔法字面量 0.2VIP_DISCOUNT_RATE
未使用代码 移除死代码 删除无法到达的分支
// ❌ 之前:嵌套条件判断
function getDiscount(user) {
  if (user) {
    if (user.isVIP) {
      return 0.2;
    } else {
      return 0.1;
    }
  }
  return 0;
}

// ✅ 之后:卫语句
function getDiscount(user) {
  if (!user) return 0;
  if (user.isVIP) return 0.2;
  return 0.1;
}

第 3 层 - 需要谨慎(风险较高,分解为更小步骤):

异味 重构方法 注意事项
上帝类 提取类 逐步进行,一次移动一个方法
类型检查条件判断 用多态替代 需要类层次结构
参数过多 引入参数对象 改变函数签名
复杂循环 用管道替代循环 确保行为等效

决胜规则: 如果多个重构方法适用,首先选择范围最小的(重命名 < 提取变量 < 提取函数 < 提取类)。


阶段 4:验证

每次重构后:

  1. 运行测试 - 必须通过
  2. 如果测试通过: 提交,提交信息为 refactor: [更改内容]
  3. 如果测试失败: 立即回滚

回滚协议

git checkout -- <已更改文件>

回滚后:

  • 重构步骤太大了吗? → 尝试更小的步骤
  • 是否意外改变了行为? → 重新考虑方法
  • 不要试图“修复”失败的重构

两次尝试失败后

停止。 询问用户:

“我已尝试此重构两次,但测试持续失败。这表明:

  1. 重构步骤太大(需要更小的步骤)
  2. 代码存在隐藏依赖
  3. 测试脆弱

您希望如何继续?”


阶段 5:迭代

需要更多重构吗?
├─ 是 → 返回阶段 3(再做一次重构)
└─ 否 → 完成
    └─ 报告:“重构完成。更改:[摘要]”

边缘情况

部分测试覆盖:

  • 识别哪些函数已测试,哪些未测试
  • 仅为你即将重构的代码添加特征测试
  • 不要试图一口吃成胖子 - 只测试你接触的部分

重构过程中发现错误:

  • 停止重构
  • 记录错误位置
  • 询问用户:“在 X 处发现潜在错误。现在修复(切换到 tdd-enforcer)还是继续重构?”

用户请求大规模重构:

  • 分解为步骤:“我将逐步重构。第一步:[步骤 1]”
  • 在下一步之前完整完成每一步
  • 绝不在一次编辑中批量处理多个重构

反模式

不要
批量处理多个重构 一次重构 → 测试 → 提交
“修复”失败的重构 回滚,然后尝试更小的步骤
在没有测试的情况下重构 首先添加特征测试
在重构过程中改变行为 那是功能/修复,不是重构
跳过提交 每次测试通过后提交

关键要点

  1. 一次只做一个更改 - 绝不批量重构
  2. 重构前先有测试 - 没有安全网 = 不重构
  3. 失败时回滚 - 不要修复,回滚并重试更小的步骤
  4. 每次成功后提交 - refactor: [描述]
  5. 首先处理最小范围 - 重命名 < 提取 < 移动 < 重组