接手遗留项目重构策略
场景
接手一个 2-3 年没有维护的旧项目,技术栈老旧(jQuery/Vue 2/Webpack 3),代码混乱,没有测试。如何制定重构策略?
重构方法论
1. 评估现状
## 项目健康度评估
### 代码质量
- [ ] 代码行数 / 文件数量
- [ ] TypeScript 使用情况
- [ ] 测试覆盖率
- [ ] ESLint 报错数量
- [ ] 重复代码比例
- [ ] 依赖版本过期数量
### 构建工具
- [ ] 构建工具及版本
- [ ] 构建时间 / 产物大小
- [ ] 是否支持 Tree Shaking
### 风险评估
- [ ] 核心贡献者是否还在?
- [ ] 有没有文档?
- [ ] 有没有线上监控?
2. 渐进式重构原则
核心原则
绞杀者模式(Strangler Fig Pattern):用新代码逐步替换旧代码,而不是推倒重写。
3. 具体步骤
第一阶段:基础设施(1-2 周)
step1: 补全工程化基础
// 1. 添加 ESLint + Prettier(先宽松,后收紧)
// 2. 添加 Husky + lint-staged(只检查新改动文件)
// 3. 添加 TypeScript(allowJs: true,渐进迁移)
// 4. 补全 CI/CD 流水线
// 5. 接入错误监控(Sentry)
第二阶段:依赖升级(2-4 周)
# 检查过期依赖
npx npm-check-updates
# 分批升级:先补丁版 → 次版 → 主版
npx npm-check-updates --target patch -u
npx npm-check-updates --target minor -u
# 主版本升级需逐个评估
第三阶段:模块化重构(持续)
每次改动遵循 Boy Scout Rule
// 改 Bug 或加功能时,顺手改善周边代码:
// 1. 将触及的 JS 文件改为 TS
// 2. 提取可复用函数
// 3. 加上类型注解
// 4. 补上单元测试
4. 风险控制
| 策略 | 做法 |
|---|---|
| 小步提交 | 每次改动不超过 300 行,便于 Code Review |
| 特性开关 | 新旧逻辑并存时用 Feature Flag 切换 |
| 灰度发布 | 先对内部用户灰度,验证后再全量 |
| 回归测试 | 核心流程补 E2E 测试,防止重构引入 bug |
| 对比验证 | 新旧页面并行一段时间,对比数据 |
常见面试问题
Q1: 遇到一个烂项目,你会选择重构还是重写?
答案:
优先重构,除非满足以下所有条件才考虑重写:
- 旧代码已经无法理解和修改
- 框架已无人维护(如 AngularJS)
- 新需求与旧架构完全不兼容
- 有充足的时间和人力
重写的风险:
- 低估了旧系统的复杂度("冰山效应")
- 业务不能停,新旧并行开发成本翻倍
- 重写完可能又积累新的技术债
Q2: 如何在不影响业务迭代的情况下重构?
答案:
- 渐进式:每次需求开发时顺带重构涉及的模块(Boy Scout Rule)
- 预留时间:争取每个迭代 20% 的时间做技术改进
- 优先级排序:先重构变更频率最高、bug 最多的模块
- 自动化保障:关键路径补测试,确保重构不引入 bug