---
name: code-refactor
description: 基于 Martin Fowler 方法论的系统化代码重构 skill。适用于用户请求重构代码、改进代码结构、减少技术债、清理旧代码、消除 code smell 或提升可维护性时。这个 skill 采用分阶段、带研究与计划的安全增量实施方式。
---

# 代码重构 Skill

这是一个基于 Martin Fowler《Refactoring: Improving the Design of Existing Code》（第 2 版）的系统化代码重构方法。这个 skill 强调安全、渐进的修改，并由测试提供保障。

> “重构是在不改变软件外部行为的前提下，改进其内部结构的过程。” — Martin Fowler

## 核心原则

1. **保持行为不变**：外部行为必须保持一致
2. **小步前进**：每次只做很小、可测试的改动
3. **测试驱动**：测试是安全网
4. **持续进行**：重构是长期过程，不是一次性任务
5. **协作确认**：每个阶段都需要用户确认

## 工作流程总览

```
阶段 1：研究与分析
    ↓
阶段 2：测试覆盖评估
    ↓
阶段 3：识别代码异味
    ↓
阶段 4：创建重构计划
    ↓
阶段 5：增量实施
    ↓
阶段 6：评审与迭代
```

---

## 阶段 1：研究与分析

### 目标
- 理解代码库结构和用途
- 确定重构范围
- 收集业务需求背景

### 先向用户确认的问题
开始前先确认：

1. **范围**：哪些文件 / 模块 / 函数需要重构？
2. **目标**：你想解决什么问题？（可读性、性能、可维护性）
3. **约束**：有哪些区域不能改？
4. **时间压力**：这是否阻塞了其他工作？
5. **测试状态**：是否已有测试？是否通过？

### 行动
- [ ] 阅读并理解目标代码
- [ ] 识别依赖和集成点
- [ ] 记录当前架构
- [ ] 标记已有技术债迹象（TODO、FIXME）

### 输出
向用户汇报：
- 代码结构总结
- 识别出的问题区域
- 初步建议
- **请求继续执行的批准**

---

## 阶段 2：测试覆盖评估

### 为什么测试重要
> “没有测试的重构，就像没有安全带就开车。” — Martin Fowler

测试是安全重构的**关键前提**。没有测试，很容易引入 bug。

### 评估步骤

1. **检查现有测试**
   ```bash
   # 查找测试文件
   find . -name "*test*" -o -name "*spec*" | head -20
   ```

2. **运行现有测试**
   ```bash
   # JavaScript / TypeScript
   npm test

   # Python
   pytest -v

   # Java
   mvn test
   ```

3. **检查覆盖率（如果可用）**
   ```bash
   # JavaScript
   npm run test:coverage

   # Python
   pytest --cov=.
   ```

### 决策点：询问用户

**如果测试存在且通过：**
- 进入阶段 3

**如果测试缺失或不完整：**
给出选项：
1. 先写测试（推荐）
2. 在重构过程中逐步补测试
3. 不写测试直接继续（有风险，需要用户确认）

**如果测试失败：**
- 停止。先修复失败测试再重构
- 问用户：是否先修测试？

### 测试编写建议（如需要）

对每个要重构的函数，测试应覆盖：
- 正常路径
- 边界情况（空输入、null、边界值）
- 错误场景（非法输入、异常）

使用“红-绿-重构”循环：
1. 写失败测试（红）
2. 让它通过（绿）
3. 再重构

---

## 阶段 3：识别代码异味

### 什么是代码异味？
代码深层问题的表面症状。它们不一定是 bug，但说明代码设计可能有问题。

### 常见异味清单

完整目录见 [references/code-smells.md](references/code-smells.md)。

#### 快速参考

| 异味 | 迹象 | 影响 |
|-------|------|------|
| **长函数** | 函数超过 30-50 行 | 难以理解、测试和维护 |
| **重复代码** | 多处出现相同逻辑 | 修复需要改多处 |
| **大类** | 类承担了太多职责 | 违反单一职责原则 |
| **Feature Envy** | 一个方法更多依赖别的类的数据 | 封装性差 |
| **基础类型沉迷** | 过度使用基础类型而不是对象 | 缺少领域概念 |
| **长参数列表** | 方法参数超过 4 个 | 调用困难 |
| **数据泥团** | 一组数据总是一起出现 | 缺少抽象 |
| **switch 语句** | 复杂的 switch / if-else 链 | 难以扩展 |
| **臆想泛化** | “以防未来需要”提前设计 | 不必要的复杂度 |
| **死代码** | 未使用的代码 | 造成困惑和维护负担 |

### 分析步骤

1. **自动分析**（如果有脚本）
   ```bash
   python scripts/detect-smells.py <file>
   ```

2. **人工审查**
   - 系统地走读代码
   - 记录每个异味的位置和严重性
   - 按影响分类（Critical / High / Medium / Low）

3. **优先级排序**
   优先关注会：
   - 阻塞当前开发的异味
   - 导致 bug 或混淆的异味
   - 影响最常变更代码路径的异味

### 输出：异味报告

向用户呈现：
- 识别出的异味及位置
- 每项的严重性评估
- 建议的优先级顺序
- **请求用户确认优先级**

---

## 阶段 4：创建重构计划

### 选择重构方式

针对每个异味，从目录中选择合适的重构手法。

完整列表见 [references/refactoring-catalog.md](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](templates/refactoring-plan.md) 里的模板。

每项重构都要写明：
1. **Target**：将修改哪些代码
2. **Smell**：解决什么问题
3. **Refactoring**：采用哪种手法
4. **Steps**：详细微步骤
5. **Risks**：可能出什么问题
6. **Rollback**：如何回退

### 分阶段方法

**关键**：重构必须分阶段推进。

**阶段 A：快速收益**（低风险，高价值）
- 重命名变量以提升清晰度
- 提取明显重复的代码
- 删除死代码

**阶段 B：结构改进**（中风险）
- 从长函数中提取方法
- 引入参数对象
- 把方法移动到更合适的类

**阶段 C：架构改动**（高风险）
- 用多态替代条件分支
- 提取类
- 引入设计模式

### 决策点：把计划展示给用户

在开始实施前：
- 展示完整重构计划
- 解释每个阶段及其风险
- 获得每个阶段的明确批准
- **询问**：“是否继续执行阶段 A？”

---

## 阶段 5：增量实施

### 黄金法则
> “修改 → 测试 → 通过？→ 提交 → 下一步”

### 实施节奏

对每一步重构：

1. **预检查**
   - 测试通过（绿色）
   - 代码能编译

2. **只做一个小改动**
   - 按目录中的具体操作进行
   - 保持改动最小化

3. **验证**
   - 立刻运行测试
   - 检查编译错误

4. **如果测试通过（绿色）**
   - 用描述清晰的提交信息提交
   - 继续下一步

5. **如果测试失败（红色）**
   - 立刻停止
   - 撤销改动
   - 分析原因
   - 如有疑问，询问用户

### 提交策略

每次提交都应当：
- **原子性**：只包含一个逻辑改动
- **可回滚**：容易撤销
- **描述清楚**：提交信息明确

示例提交信息：
```
refactor: 从 processOrder() 中提取 calculateTotal()
refactor: 将 'x' 重命名为 'customerCount' 以提升清晰度
refactor: 删除未使用的 validateOldFormat() 方法
```

### 进度汇报

每个子阶段完成后，向用户汇报：
- 做了哪些改动
- 测试是否仍通过
- 遇到了什么问题
- **询问**：“继续下一批吗？”

---

## 阶段 6：评审与迭代

### 重构后检查清单

- [ ] 所有测试通过
- [ ] 没有新的警告 / 错误
- [ ] 代码编译成功
- [ ] 行为没有变化（手动验证）
- [ ] 必要时已更新文档
- [ ] 提交历史干净

### 指标对比

重构前后运行复杂度分析：
```bash
python scripts/analyze-complexity.py <file>
```

展示改进：
- 代码行数变化
- 圈复杂度变化
- 可维护性指标变化

### 用户评审

向用户展示最终结果：
- 所有变更摘要
- 重构前后代码对比
- 指标改善情况
- 剩余技术债
- **询问**：“你对这些改动满意吗？”

### 下一步

和用户讨论：
- 还要处理哪些异味？
- 是否安排下一次重构？
- 是否把类似修改应用到其他地方？

---

## 重要指南

### 何时暂停并询问

遇到以下情况时，务必暂停并和用户确认：
- 不确定业务逻辑
- 改动可能影响外部 API
- 测试覆盖不足
- 需要做重大的架构决策
- 风险上升
- 遇到意外复杂性

### 安全规则

1. **没有测试不要重构**（除非用户明确确认风险）
2. **不要做大改动**，拆成小步
3. **每次改动后都不要跳过测试**
4. **测试失败就不要继续**，先修复或回滚
5. **不要臆测**，不确定就问

### 不要做什么

- 不要把重构和新功能混在一起
- 不要在生产事故期间做重构
- 不要重构你看不懂的代码
- 不要过度设计，保持简单
- 不要一次性重构所有内容

---

## 快速上手示例

### 场景：长函数 + 重复逻辑

**重构前：**
```javascript
function processOrder(order) {
  // 150 行代码，包含：
  // - 重复验证逻辑
  // - 内联计算
  // - 多种职责混杂
}
```

**重构步骤：**

1. **确认测试存在**，覆盖 `processOrder()`
2. **提取** 验证逻辑为 `validateOrder()`
3. **测试** - 应该通过
4. **提取** 计算逻辑为 `calculateOrderTotal()`
5. **测试** - 应该通过
6. **提取** 通知逻辑为 `notifyCustomer()`
7. **测试** - 应该通过
8. **评审** - `processOrder()` 现在只负责串联 3 个清晰函数

**重构后：**
```javascript
function processOrder(order) {
  validateOrder(order);
  const total = calculateOrderTotal(order);
  notifyCustomer(order, total);
  return { order, total };
}
```

---

## 参考资料

- [代码异味目录](references/code-smells.md) - 代码异味完整清单
- [重构目录](references/refactoring-catalog.md) - 重构手法
- [重构计划模板](templates/refactoring-plan.md) - 计划模板

## 脚本

- `scripts/analyze-complexity.py` - 分析代码复杂度指标
- `scripts/detect-smells.py` - 自动检测 code smell

## 版本历史

- v1.0.0 (2025-01-15)：首次发布，包含 Fowler 方法论、分阶段流程和用户确认点
