# Refactoring

> 大规模重构的结构化流程：影响分析→安全网搭建→分步重构→回归验证。 适用于涉及多文件、架构调整、模块解耦、接口重新设计等非平凡重构。 本 skill 是流程 skill（调度型），复用 task-execute 管理进度、task-finish 做收尾、 dependency-map 做影响分析、writing 写方案。 触发词：重构、解耦、架构调整、模块拆分、接口重新设计、refactor。 触发场景：用户明确说要重构、task-start 判定为重构类任务、代码审查后决定重构。 小范围重命名或局部调整不需要本 skill，直接动手即可。

- Skill: `312362115/refactoring` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 312362115/refactoring`
- Raw SKILL.md: https://api.skillmd.com/api/skills/312362115/refactoring/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: 312362115 (https://skillmd.com/u/312362115)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/312362115/refactoring

---


# 大规模重构（Refactoring）

> 重构最大的风险不是改错，而是改了不知道影响了什么。
> 本 skill 的核心：先建安全网，再动刀子，每一步都有回退点。

---

## 第一步：判断是否需要本 skill

```
收到重构请求
  │
  ├─ 改动 ≤2 个文件，不涉及公共接口？
  │   └─ 直接动手，不需要本 skill
  │
  ├─ 改动 3-5 个文件，局部重构？
  │   └─ 走简化流程：第二步（快速版）→ 第四步 → 第五步
  │
  └─ 涉及公共接口 / 跨模块 / 架构调整 / 数据结构变更？
      └─ 走完整流程：第二步 → 第三步 → 第四步 → 第五步 → 第六步
```

**判断信号**：

| 信号 | 走完整流程 |
|------|-----------|
| 改公共函数/类的签名 | 是 |
| 拆分或合并模块 | 是 |
| 改数据模型/数据库 schema | 是 |
| 改目录结构 | 是 |
| 改导入路径被多处引用 | 是 |
| 纯内部实现优化，接口不变 | 否，简化流程 |

---

## 第二步：影响分析

> 动手之前，先搞清楚"改这里会动到哪里"。

### 2.1 确定重构范围

- **重构目标**：要改什么？改完应该是什么样？（用 `AskUserQuestion` 和用户对齐）
- **触发原因**：为什么要重构？（技术债 / 性能 / 可维护性 / 新需求倒逼）
- **不改什么**：明确哪些相关代码这次不动（防止 scope 膨胀）

### 2.2 依赖关系梳理

对要重构的模块，梳理上下游依赖：

```
被谁调用（上游）→ [重构目标] → 调用了谁（下游）
```

**具体操作**：
1. **Grep 搜索**：搜索要重构的函数名/类名/模块路径，找到所有引用位置
2. **导入分析**：检查 `import`/`require` 关系，画出依赖图
3. **数据流追踪**：如果涉及数据结构变更，追踪数据从哪来、到哪去

### 2.3 影响面评估

列出影响清单：

```markdown
## 影响分析

### 直接影响（必须改）
- `src/services/auth.ts` — 调用了要重构的函数
- `src/api/user.ts` — 引用了要修改的类型

### 间接影响（需要验证）
- `src/pages/login.tsx` — 依赖 auth 服务，接口不变则不受影响
- `tests/auth.test.ts` — 测试用例需要同步更新

### 不受影响（确认安全）
- `src/utils/format.ts` — 无依赖关系
```

**快速版**（局部重构）：只做 Grep 搜索确认引用范围，不需要完整的影响清单文档。

---

## 第三步：安全网搭建

> 没有安全网的重构是赌博。安全网 = 测试 + 回退能力。

### 3.1 确认现有测试覆盖

检查要重构的模块是否有测试：

```bash
# 找到相关测试文件
grep -r "重构目标函数名/模块名" tests/ __tests__/ *.test.* *.spec.*
```

| 现有测试情况 | 策略 |
|-------------|------|
| 有测试且覆盖核心路径 | 先跑通现有测试，确认 baseline 全绿 |
| 有测试但覆盖不足 | 补充关键路径测试后再开始重构 |
| 没有测试 | **必须先补测试**，至少覆盖核心路径和边界情况 |

### 3.2 补充缺失测试

对于没有测试或覆盖不足的情况：
- 不需要追求 100% 覆盖率
- 重点覆盖：**要改的函数的核心输入输出**、**公共接口的契约**、**边界情况**
- 测试应该验证行为（输入→输出），不验证实现细节
- 把测试用例记录到 `docs/tests/<模块名>-refactor.md`

### 3.3 创建回退点

```bash
# 在重构开始前创建一个明确的 commit 或 branch
git checkout -b refactor/<模块名>
git commit -m "chore: 重构前基线 — 测试全绿"
```

确保随时可以 `git diff refactor/<模块名>` 看到所有改动，出问题能快速回退。

---

## 第四步：分步重构

> 大象要一口一口吃。每一步都是可验证的、可回退的。

### 4.1 制定重构计划

将重构拆分为**独立的、可验证的小步骤**，每步完成后测试应该通过：

```markdown
## 重构计划

- [ ] Step 1: <描述> — 预期：测试全绿，行为不变
- [ ] Step 2: <描述> — 预期：测试全绿，行为不变
- [ ] Step 3: <描述> — 预期：测试全绿，新接口生效
- [ ] Step 4: 清理旧代码 — 预期：测试全绿，无废弃代码
```

**拆分原则**：
- 每步只做一件事（改结构不改逻辑 / 改逻辑不改结构）
- 每步改完都能编译通过、测试通过
- 步骤间尽量不互相依赖
- 危险操作（删代码、改数据结构）放后面，确认安全了再做

### 4.2 常用重构策略

| 场景 | 推荐策略 |
|------|---------|
| 改公共接口签名 | **先新后删**：新接口 → 迁移调用方 → 删旧接口 |
| 拆分大文件/大函数 | **提取 → 内联引用 → 验证 → 删旧** |
| 改目录结构 | **先移文件 → 修导入 → 验证 → 提交**（单独一步，不混逻辑改动） |
| 替换依赖/框架 | **适配器模式**：新旧共存 → 逐步迁移 → 移除旧依赖 |
| 改数据模型 | **双写过渡**：新旧字段并存 → 迁移读写逻辑 → 清理旧字段 |

### 4.3 执行纪律

每完成一个步骤：

1. **跑测试**：确认现有测试全部通过
2. **跑 lint**：确认没有引入格式问题
3. **快速 review**：看一眼 diff，确认只改了该改的
4. **提交**：每步一个 commit，message 说清楚做了什么

```bash
git commit -m "refactor(auth): step 1 — 提取 token 验证为独立函数"
```

**如果某一步测试挂了**：
- 先看是不是测试本身需要更新（因为接口变了）
- 如果是意料之外的挂掉 → 停下来分析，不要硬继续
- 实在搞不清 → 回退到上一步的 commit，重新想策略

---

## 第五步：回归验证

> 重构的目标是"行为不变，结构更好"。验证行为是否真的没变。

### 5.1 运行全量测试

```bash
# 项目测试
npm test  # 或 pytest

# 如果有 e2e 测试
npm run test:e2e
```

### 5.2 人工验证核心路径

测试不能覆盖一切。对于以下场景，手动验证：

- 页面渲染是否正常（前端重构）
- API 响应是否符合预期（后端重构）
- 关键业务流程走通（端到端）

### 5.3 对比验证

```bash
# 对比重构前后的 git diff，确认改动范围符合预期
git diff refactor/<模块名>..HEAD --stat
```

检查：
- 没有混入不相关的改动
- 没有遗留 debug 代码
- 没有遗留注释掉的旧代码

---

## 第六步：收尾

### 6.1 清理

- 删除废弃的旧代码（不是注释掉，是删掉）
- 更新相关文档（如果重构改了目录结构、接口、配置等）
- 更新 `docs/tests/` 中的测试用例（重构过程中新增的测试要沉淀）

### 6.2 交给 task-finish 进行 CR 自检

重构完成后，交给 task-finish 执行深度自检：
- 改动范围是否符合重构目标？
- 有无混入不相关变更？
- 有无遗留调试代码？

### 6.3 复盘沉淀（由 task-manager 触发）

重构完成后，当用户将需求标 done 时，由 task-manager 触发复盘。重构类任务建议做完整复盘，记录到 `docs/decisions/`：
- 重构的动机和目标达成了吗？
- 哪些步骤顺利？哪些卡住了？
- 影响分析是否准确？遗漏了什么？
- 下次类似重构有什么经验可复用？

---

## 与其他 skill 的衔接

```
task-start
  │ 判定为重构任务
  ↓
refactoring（本 skill）
  │
  ├─ 第二步 ← dependency-map（影响分析，如果有的话）
  ├─ 第二步 ← writing（写重构方案，大型重构时）
  ├─ 第四步 ← task-execute（跨会话进度管理）
  ├─ 第五步 ← perf-profiling（性能相关重构时对比前后）
  │
  ├─ 收尾 → task-finish（CR 自检）
  └─ 需求标 done → task-manager → 触发复盘
```

---

## 反模式清单

| 反模式 | 后果 | 正确做法 |
|--------|------|---------|
| 没有安全网就开始改 | 改完不知道哪里坏了 | 先确认测试覆盖，再动手 |
| 一次改太多 | 出问题无法定位 | 小步提交，每步可验证 |
| 重构时顺手加功能 | scope 膨胀，风险叠加 | 重构和功能开发分开做 |
| 改结构的同时改逻辑 | 无法区分是结构改动还是逻辑改动引起的问题 | 一步只做一件事 |
| 注释掉旧代码不删 | 代码越来越脏 | 确认不用了就删 |
| 跳过回归测试 | 上线后才发现问题 | 每步跑测试，最后全量回归 |
| 不记录影响面 | 下次改同样的地方又不知道影响谁 | 影响分析写下来 |

