首页/开发/代码质量与评审速查/手法:Replace Temp with Query(以查询取代临时变量)
重构手法62 条

手法:Replace Temp with Query(以查询取代临时变量)

把临时变量替换为查询函数:变量被就地复用会掩盖逻辑、阻碍提炼;函数化后可从任意调用点复用,也便于单测该表达式。

Replace Temp with Query 是什么

把临时变量替换为一个查询函数:局部变量被多处复用会掩盖真实逻辑,也让提炼函数变得困难——函数边界内藏着临时变量时,很难把一段逻辑干净地取出来。函数化之后表达式可以从任意调用点复用,也可以被单独测试。代价是可能重复计算,性能敏感处需要另行评估。

基本信息

场景临时变量跨多个逻辑段使用,需要先赋值再读
收益可提炼、可复用、意图从命名上显露
注意热路径上的重复计算可评估缓存,但要显式管理失效
前提表达式本身无副作用

适用判断

  • 临时变量在函数后半段被另一层逻辑再次使用,读者必须回看赋值处
  • 同一表达式在多个方法里各算一遍
  • 变量名比表达式本身更容易理解,值得提升为方法名
  • 该值需要被测试覆盖,但现在只能通过整段流程间接验证
  • 表达式依赖若干字段,函数化后内部类可以隐藏参数传递

Java 示例

Java 示例
// 之前
void printOwing() {
    double basePrice = quantity * itemPrice;   // 只在这里算一次,却要多处引用
    double discount = Math.max(0, quantity - 500) * itemPrice * 0.05;
    System.out.println(basePrice - discount);
}

// 之后:查询方法承载意图,调用点可以直接读
void printOwing() {
    System.out.println(basePrice() - discount());
}

double basePrice() { return quantity * itemPrice; }
double discount()  { return Math.max(0, quantity - 500) * itemPrice * 0.05; }

三种近似手法对照

手法处理对象适用
Replace Temp with Query函数内的一次性临时值表达式可复用或需要被测试
Replace Derived Variable对象字段中的派生值消除字段同步风险
Extract Variable表达式的一小段仅需要局部可读性提升
查询函数必须是纯的:名字像查询、行为像命令会误导调用方——调用一次就悄悄改了状态,读者无法从名字看出这一点,排查问题时非常费劲。
循环内高频调用纯计算查询时,先度量再决定是否缓存。真正的热点路径需要优化时,优化点应当显式写在注释与测试里,而不是靠一个隐式的缓存字段。

易错点

  • 把副作用表达式放进查询:命名像查询、行为像命令,误导调用方
  • 循环内高频调用纯计算查询:先度量再决定是否缓存,避免凭感觉优化
  • 全部临时变量都改成方法:调用链变长,调试时看不到中间值
  • 查询方法之间互相调用形成环:计算顺序不再清晰,容易写出无限递归

数据来源与参考

  • 《重构》第 2 版 · 第 6 章(Replace Temp with Query)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌