double basePrice = _quantity * _itemPrice;
if(basePrice > 1000)
return basePrice * 0.95;
else
return basePrice * 0.98;
==>
if(basePrice() > 1000)
return basePrice() * 0.95;
else
return basePrice() * 0.98;
double basePrice() {
return _quantity * _itemPrice;
}
动机
临时变量的问题在于:它们是暂时的,而且只能在所属函数内使用.由于临时变量只有在所属函数内才可见,所以它们会驱使你写出更长的函数,因为只有这样你才能访问到想要访问的临时变量.如果把临时变量替换为一个查询式(query method),那么同一个class中的所有函数都将可以获得这份信息.这将带给你极大帮助,使你能够为这个class编写更清晰的代码.
Replace Temp with Query(120)往往是你运用Extract Method(110)之前必不可少的一个步骤.局部变量会使代码难以被提炼,所以你应该尽可能把它们替换为查询式.
这个重构手法较为直率的情况就是:临时变量只被赋值一次,或者赋值给临时变量的表达式不受其他条件影响.其他情况比较棘手,但也有可能发生.你可能需要先运用Split Temporary Variable(128)或Separate Query from Modifier(279)使情况变得简单一些,然后再替换临时变量.如果你想替换的临时变量是用来收集结果的(例如循环中的累加值),你就需要将某些程序逻辑(例如循环)拷贝到查询式(query method)去.
作法:
1. 找出只被赋值一次的临时变量
如果某个临时变量被赋值超过一次,考虑使用Split Temporay Variable(128)将它分割成多个变量.
2. 将该临时变量声明为final.
3. 编译.这可确保该临时变量的确只被赋值一次.
4. 将[对临时变量赋值]之语句的等号右侧部分提炼到一个独立函数中
首先将函数声明为private.日后你可能会发现有更多class需要使用它,彼时你可轻易放松对它的保护.
确保提炼出来的函数无任何连带影响(副作用),也就是说该函数并不修改任何对象内容.如果它有连带影响,就对它进行Separate Query from Modifier(279).
5 编译,测试
6 在该临时变量身上实施Inline Temp(119).
double getPrice() {
int basePrice = _quantity * _itemPrice;
double discountFactor;
if(basePrice > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
首先我把赋值(assignment)动作的右侧表达式提炼出来:
double getPrice() {
final int basePrice = basePrice();
final double discountFactor;
if(basePrice > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
private int basePrice() {
return _quantity * _itemPrice;
}
编译并测试,然后开始使用Inline Temp
double getPrice() {
final double discountFactor;
if(basePrice() > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice() * discountFactor;
}
private int basePrice() {
return _quantity * _itemPrice;
}
搞定basePrice之后,我再以类似办法提炼出一个discountFactor():
double getPrice() {
final double discountFactor = discountFactor();
return basePrice() * discountFactor;
}
private double discountFactor() {
if(basePrice() > 1000) return 0.95;
else return 0.98;
}
最终,getPrice()变成了这样:
double getPrice() {
return basePrice() * discountFactor();
}