5Working Effectively with Legacy Code

安全重构

重构策略

安全重构重构时机代码嗅探渐进改进

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第5章:安全重构(Safe Refactoring)

一、导读

1.1 本章学习目标

第5章讲解如何在遗留代码中安全地重构。

本章的核心学习目标包括:

  • 掌握安全重构的原则
  • 理解重构的时机和策略
  • 学会使用渐进式改进
  • 理解代码嗅探在重构中的作用

1.2 为什么本章如此重要

重构遗留代码是危险的——没有测试的保护,任何修改都可能引入 bug。本章教你如何在风险可控的前提下逐步改善代码质量。

1.3 核心问题引导

什么情况下应该重构遗留代码?

如何在没有测试的情况下安全重构?

重构的优先级如何确定?

渐进式改进和大规模重写各有什么优缺点?


二、核心概念详解

2.1 重构原则

安全重构原则:
1. 先添加测试,再重构
2. 小步前进:每次只做一个小改动
3. 频繁运行测试:确认每步都安全
4. 保持功能不变:重构不是添加功能
5. 回退能力:如果出错能快速恢复

2.2 重构时机

应该重构的信号:
- 需要添加新功能但代码难以修改
- 修复 bug 时发现代码结构混乱
- 代码审查中发现重复代码
- 性能问题需要优化

不应该重构的情况:
- 代码即将被废弃
- 没有测试且无法添加测试
- 时间紧迫且风险太高

2.3 渐进式改进

java
// 策略1:童子军规则
// "让营地比你发现时更干净"
// 每次修改代码时,顺手改善一小部分

// 策略2:绞杀者模式
// 逐步用新代码替换旧代码
public class OrderService {
    private LegacyOrderProcessor legacy;
    private NewOrderProcessor modern;
    
    public void process(Order order) {
        if (canHandleModern(order)) {
            modern.process(order);    // 新路径
        } else {
            legacy.process(order);    // 旧路径
        }
    }
}

// 策略3:分支抽象
// 将变化点抽象出来
public class PriceCalculator {
    public double calculate(Order order) {
        double base = calculateBase(order);
        double discount = calculateDiscount(order);    // 抽象点
        return base - discount;
    }
}

2.4 代码嗅探

遗留代码中的危险信号:
1. 超长方法(>50行)
2. 超大类(>500行)
3. 深层嵌套(>3层 if/for)
4. 重复代码
5. 魔法数字
6. 过长的参数列表
7. 全局变量
8. 硬编码的依赖

三、实战案例

3.1 案例一:渐进式重构超长方法

java
// 遗留代码:500 行的 processOrder 方法
public void processOrder(Order order) {
    // 验证
    // 计算价格
    // 检查库存
    // 创建支付
    // 发送通知
    // 更新统计
    // ...
}

// 第一步:提取注释标记的段落
public void processOrder(Order order) {
    // === 验证 ===
    validateOrder(order);
    
    // === 计算价格 ===
    double price = calculatePrice(order);
    
    // === 检查库存 ===
    checkInventory(order);
    
    // === 创建支付 ===
    Payment payment = createPayment(order, price);
    
    // === 发送通知 ===
    sendNotification(order, payment);
    
    // === 更新统计 ===
    updateStatistics(order);
}

// 第二步:逐步提取为独立方法
// 每提取一个方法就运行测试

四、本章小结

重构原则:先测试、小步前进、频繁验证。

重构时机:需要修改、修复 bug、代码审查。

渐进改进:童子军规则、绞杀者模式、分支抽象。

代码嗅探:识别需要重构的危险信号。


五、思考与练习

制定一个遗留系统的渐进式重构计划。

绞杀者模式在什么场景下最有效?

如何在团队中推广安全重构的实践?


5/7安全重构
0%