两顶帽子重构法

#设计 #最佳实践 #重构

总结
  • 重构和加功能必须严格分开,不能同时进行
  • 第一顶帽子:只调整结构,不改行为,测试全部通过
  • 第二顶帽子:在整理好的结构上加新功能
  • 小步提交,重构 commit 和功能 commit 分开

1. 先说结论

两顶帽子来自 Martin Fowler 的《重构》,核心就一句话:重构和加功能不能同时进行,必须严格分开。

两顶帽子分别是:


2. 为什么要分开?

边重构边加功能是最常见的坑:

分开之后,每个阶段目标单一,出问题好定位,也好回退。


3. 怎么做?

3.1 第一顶帽子:整理结构

只做这些事:

硬性要求:改完之后所有测试必须通过,外部行为不能变。

// 重构前:支付逻辑写死
public class OrderService {
    public void pay(Order order) {
        alipayClient.pay(order);
    }
}

// 重构后:抽出策略接口,解耦支付方式
public interface PaymentStrategy {
    void pay(Order order);
}

public class AlipayStrategy implements PaymentStrategy {
    public void pay(Order order) { alipayClient.pay(order); }
}

public class OrderService {
    private PaymentStrategy paymentStrategy;
    public void pay(Order order) { paymentStrategy.pay(order); }
}

3.2 第二顶帽子:加新功能

结构整理好了,加功能就很简单:

// 直接实现新的策略,不动核心代码
public class WechatPayStrategy implements PaymentStrategy {
    public void pay(Order order) { wechatPayClient.pay(order); }
}

4. 实践建议

小步提交:重构的 commit 和功能的 commit 分开,PR 也分开,方便 review 和回退。
先有测试再重构:没有测试覆盖就不敢动,先补测试再戴第一顶帽子。测试不是必须 TDD,但重构前得有基本的覆盖。
别过度重构:第一顶帽子只服务于当前要加的功能,不要为了"以后可能用到"去做大规模改造。