Add Chinese (Simplified) translations for all documentation, organized under a dedicated zh/ directory that mirrors the English folder structure. Co-authored-by: tanqingkuang <tanqingkuang@users.noreply.github.com> Translations originally contributed by @tanqingkuang in #45. Restructured from *-CN.md suffix pattern into zh/ directory to prevent the EPUB builder (scripts/build_epub.py collect_folder_files) from picking up Chinese files via glob("*.md") inside module folders.
427 lines
11 KiB
Markdown
427 lines
11 KiB
Markdown
---
|
||
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 方法论、分阶段流程和用户确认点
|