重构函数-Replace Temp with Query以查询取代临时变量四
1.以查询取代临时变量
1.1.使用场景
你的程序以一个临时变量(temp)保存某一表达式的运算结果。
1.2.为什么用查询取代临时变量
临时变量会增加函数的长度
它们是暂时的,而且只能在所属函数内使用。由于临时变量只有在所属函数内才可见,所以它们会驱使你写出更长的函数,因为只有这样你才能访问到想要访问的临时变量扩展临时变量生命周期
把临时变量替换为一个查询函数(query method),那么同一个class中的所有函数都将可以获得这份信息。这将带给你极大帮助,使你能够为这个编写更清晰的代码降低提炼函数重构手法难度
Replace Temp with Query往往是你运用提炼函数
之前必不可少的一个步骤。局部变量会使代码难以被提炼,所以你应该尽可能把它们替换为查询函数
1.3.如何用
- 找出只被赋值一次的临时变量。
- 如果某个临时变量被赋值超过一次,考虑使用
Split Temporary Variable剖解临时变量
将它分割成多个变量。 - 将该临时变量声明为final,这可确保该临时变量的确只被赋值一次。
- 编译。
- 将「对该临时变量赋值」之语句的等号右侧部分提炼到一个独立函数中。首先将函数声明为private。
- 日后你可能会发现有更多class需要使用 它,彼时你可轻易放松对它的保护。
- 确保提炼出来的函数无任何连带影响(副作用),也就是说该函数并不修改任何对象内容。如果它有连带影响,就对它进行
Separate Query from Modifier将查询函数和修改函数分离
。 - 编译,测试。
1.4.查询函数替代临时变量示例
下面是一个临时变量的示例代码,通过几个步骤我们使用查询函数替代临时变量
重构手法替换掉临时变量。
double getPrice() {
int basePrice = _quantity * _itemPrice;
double discountFactor;
if (basePrice > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
我们希望将示例中两个临时变量都替换掉,但是我们不能一次都替换,要循序渐进。所以我们先替换basePrice
尽管这里的代码十分清楚,我还是先把临时变量声明为final,检查他们是否的确只被赋值一次.
这样一来,如果有任何问题,编译器就会警告我。之所以先做这件事,因为如果临时变量不只被赋值一次,我就不该进行该项重构。
double getPrice() {
//将临时变量申明为常量,测试它是否只赋值一次。
final int basePrice = _quantity * _itemPrice;
final double discountFactor;
if (basePrice > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
接下来我开始替换临时变量,每次一个。首先我把赋值(basePrice)动作的右侧表达式提炼出来:
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;
}
编译并测试,如果没有问题就开始使用Replace Temp with Query
。
首先把临时变量basePrice的第一个引用点替换掉:
double getPrice() {
final int basePrice = basePrice();
final double discountFactor;
// 替换掉basePrice变量第一个引用点,替换为新的函数
if (basePrice() > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
return basePrice * discountFactor;
}
编译,测试。然后替换下一个引用点,直到所有的引用点都替换掉。
然后把basePrice
临时变量的声明式一并摘除
double getPrice() {
// 去掉了basePrice临时变量
final double discountFactor;
//临时变量替换为函数
if (basePrice() > 1000) discountFactor = 0.95;
else discountFactor = 0.98;
//临时变量替换为函数
return basePrice() * discountFactor;
}
搞定basePrice之后,我再以类似办法提炼出一个discountFactor()
double getPrice() {
final double discountFactor = discountFactor();
return basePrice() * discountFactor;
}
//创建一个新函数
private double discountFactor() {
//复用了basePrice临时变量提炼的函数
if (basePrice() > 1000) return 0.95;
else return 0.98;
}
你看,如果我没有把临时变量basePrice替换为一个查询式,将多么难以提炼discountFactor()
最终,getPrice()变成了这样
double getPrice() {
return basePrice() * discountFactor();
}