首页/开发/代码质量与评审速查/手法:Extract Variable(提炼变量)
重构手法62 条

手法:Extract Variable(提炼变量)

把复杂表达式的一部分取出为命名变量:让条件与运算表达意图,调试时也便于观察中间结果;配合引入解释性变量进一步可读。

Extract Variable 是什么

把复杂表达式的一部分取出为有名字的变量:条件判断与算术运算因此能表达意图,调试时也便于观察中间结果。命名是关键——名字要说明「这是什么」,而不是复读表达式本身。它与 Extract Function 是一对:差别在于是否需要复用与是否需要跨越作用域。

基本信息

场景长表达式、条件分支中难懂的子表达式
命名用业务含义命名,避免 temp1 式命名
对比Extract Function 适合需要复用或跨作用域的情况
自动化主流 IDE 都支持一键提炼变量,改完立即跑测试

适用判断

  • 条件里出现一长串布尔运算,读一遍记不住
  • 同一子表达式在相邻几行重复出现,容易改漏一处
  • 表达式的含义需要靠注释解释,注释其实就是变量名
  • 调试时需要在中间点观察值,但表达式没有落脚处
  • 算术公式里的每一项都对应业务概念,但代码里只是一串符号

Java 示例

Java 示例
// 之前
if (platform.toUpperCase().indexOf("MAC") > -1 &&
    browser.toUpperCase().indexOf("IE") > -1 &&
    resize > 0) { ... }

// 之后:变量名承担了原本要靠注释解释的含义
boolean isMacOs = platform.toUpperCase().contains("MAC");
boolean isIE = browser.toUpperCase().contains("IE");
boolean wasResized = resize > 0;
if (isMacOs && isIE && wasResized) { ... }

提炼变量还是提炼函数

情况选择理由
表达式只在本函数用一次Extract Variable局部命名足够,成本最低
同一表达式需要在别处复用Extract Function避免复制或跨层访问
表达式很长且含多处判断先变量再函数分两步降低改动风险
表达式带有副作用先分离副作用否则名字会误导调用者
变量命名复读表达式(aPlusB = a + b)没有增加任何信息,只是把行变多。有效的名字是能让读者跳过实现去理解意图的那些,例如 isMacOs 而不是 platformContainsMac。
在很长的函数里不断加变量而不提炼函数,函数长度会继续膨胀。变量和函数都是降低理解成本的手段,配合使用比只挑一种更有效。

易错点

  • 命名复读表达式:变量名没有提供新信息,读者仍然要回头看右侧
  • 只为少打字而提炼:局部变量的作用域被无意扩大,改动影响范围随之变大
  • 在长函数里加变量而不提炼:函数继续膨胀,长度问题被掩盖
  • 提炼后忘记更新重复出现处:同一表达式的新旧两版并存,行为悄然分叉

数据来源与参考

  • 《重构》第 2 版 · 第 6 章(Extract Variable)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌