Introduce Explaining Variable(引入解释性变量)

if((platform.toUpperCase().indexOf("MAC") > -1) &&
   (brower.toUpperCase().indexOf("IE") > -1) &&
   wasInitialized() && resize > 0)
{
   //do something
}
==>
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;

if(isMacOs && isIEBrowser && wasInitialized() && wasResized) {
   //do something
}

动机:

表达式有可能非常复杂而难以阅读.这种情况下,临时变量可以帮助你将表达式分解为比较容易管理的形式.

在条件逻辑(conditional logic)中,Introduce Explaining Variable(124)特别有价值:你可以用这项重构将每个条件子句提炼出来,以一个良好命名的临时变量来解释对应条件子句的意义.使用这项重构的另一种情况是,在较长算法中,可以运用临时变量来解释每一步运算的意义.

Introduce Explaining Variable(124)是一个很常见的重构手法,但我得承认,我并不常用它.我几乎总是尽量使用Extract Method(110)来解释一段代码的意义.毕竟临时变量只在它所处的那个函数中才有意义,局限性较大,函数则可以对象的整个生命中都有用,并且可被其他对象使用.但有时候,当局部变量使Extract Method(110)难以进行时,我就使用Introduce Explaining Variable(124).

作法

1 声明一个final 临时变量,将待分解之复杂表达式中的一部分动作的运算结果赋值给它.

2 将表达式中的[运算结果]这一部分,替换为上述临时变量.

如果被替换的这一部分在代码中重复出现,你可以每次一个,逐一替换.

3 编译,测试

4 重复上述过程,处理表达式的其他部分

 

double price() {
   //price is base price - quantity discount + shipping
   return _quantity * _itemPrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * _itemPrice * 0.1, 100.0);
}

 

首先我发现,底价(base price)等于数量(quantity)乘以单价(item price).于是我把这一部分计算的结果放进一个临时变量中:

double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   return basePrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(basePrice * 0.1, 100.0);
}

 

然后,我将批发折扣(quantity discount)的计算提炼出来,将结果赋予临时变量quantityDiscount:

 

double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   final double quantityDiscount = Math.max(0, _quantity - 500) *
                                                      _itemPrice * 0.05;
   return basePrice - quantityDiscount  +
      Math.min(basePrice * 0.1, 100.0);
}

最后,我再把运费(shipping)计算提炼出来,将运算结果赋予临时变量shipping.同时我还可以删掉代码中的注释,因为现在代码已经可以完美表达自己的意义了:
double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   final double quantityDiscount = Math.max(0, _quantity - 500) *
                                                      _itemPrice * 0.05;
   final double shipping = Math.min(basePrice * 0.1, 100.0);
   return basePrice - quantityDiscount  + shipping;
}

 

运用Extract Method处理上述范例

double price() {
   //price is base price - quantity discount + shipping
   return _quantity * _itemPrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * _itemPrice * 0.1, 100.0);
}
这次我把底价计算提炼到一个独立函数中:
double price() {
   //price is base price - quantity discount + shipping
   return basePrice() -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(basePrice() * 0.1, 100.0);
}
private double basePrice() {
   return _quantity * _itemPrice;
}
我继续我的提炼,每次提炼出一个新函数.最后得到下列代码:
double price() {
   //price is base price - quantity discount + shipping
   return basePrice() - quantityDiscount() + shipping();     
}
private double quantityDiscount() {
   Math.max(0, _quantity - 500) * _itemPrice * 0.05;
}
private double shipping() {
   Math.min(basePrice() * 0.1, 100.0);
}
private double basePrice() {
   return _quantity * _itemPrice;
}

我比较喜欢使用Extract Method(110),因为同一对象中的任何部分,都可以根据自己的需要去取用这些提炼出来的函数.一开始我会这些新函数声明为private;如果其他对象也需要它们,我可以轻易释放这些函数的访问限制.我还发现,Extract Method(110)的工作量通常并不必Introduce Explaining Variable(124)来得大.

那么,应该在什么时候使用Introduce Explaining Variable(124)呢?答案是:在Extract Method(110)需要花费更大工作量时.如果我要处理的是一个拥有大量局部变量的算法,那么使用Extract Method(110)绝非易事.这种情况下我会使用Introduce Explaining Variable(124)帮助我清理代码,然后再考虑下一步该怎么办.搞清楚代码逻辑之后,我总是可以运用Replace Temp with Query(120)把被我引入的那些解释性临时变量去掉.况且,如果我最终使用Replace Method with Method Object(135),那么被我引入的那些解释性临时变量也有其价值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值