一个临时变量保存某一个表达式的运算结果.将这个表达式提炼到一个独立函数中,将这个临时变量的所有引用点替换为对新函数的调用.此后新函数就可以被其他函数调用
示例:
修改前:
$basePrice = $this->quantity * $this->itemPrice;
if ($basePrice > 1000) {
return $basePrice * 0.95;
} else {
return $basePrice * 0.98;
}
修改后:
/**
* 计算价格
*/
public function basePrice() {
return $this->quantity * $this->itemPrice;
}
if (basePrice() > 1000) {
return $basePrice * 0.95;
} else {
return $basePrice * 0.98;
}
动机
- 临时变量的问题在于:它们是暂时的.而且只能在所属函数内使用.由于临时变量只能在所属函数内可见.他们会驱使你写出更长的函数.因为只有这样你才能访问到需要的临时变量.如果吧临时变量替换为一个查询,那么同一个类中的所有函数都将可以获得这份信息.
- Replace Temp With Query往往是你运用Extract Method之前必不可少的一个步骤.局部变量会使代码变得难以提炼,所有你应该尽可能把它们替换成查询式.
做法
- 找出只被赋值一次的临时变量.如果一个临时变量被赋值超过一次则应该考虑使用Split Temporary Variable将它分割成多个变量
- 确保该临时变量只被赋值一次
- 将对该临时变量赋值的语句等号右侧部分提炼到一个独立函数中.
- 首先将函数声明为private,日后更多类需要使用它时,那时放松对它的保护也很容易.
- 去报提炼出来的函数没有任何副作用,也就是说该函数并不修改任何对象内容.如果他有副作用,就对它进行Separate Query From Modifler.
- 在该变量身上实时Inline Temp;
通常情况下,我们常常使用临时变量保存循环中的累加信息.在这种情况下.这个恶循环都一个被提炼为一个独立函数,这也是原本的函数少几行循环逻辑,有时你可能在一个循环中累加好几个值,这种情况你应该针对每个累加值重复一遍循环,这样就可以将所有的临时变量都替换为查询.当然,循环应该简单.
运用此写法,你可能会担心性能问题.和其他性能问题一样.我们现在不管他,因为它可能根本不会造成任何影响.若是性能真的除了问题,你也可以在优化时期解决他.如果性能实在糟糕,要把临时变量放回去也是很容易的.
实例
首先从一个简单的函数开始:
/**
* 获取价格
*/
public function getPrice() {
$basePrice = $this->quantity * itemPrice;
$discounterFactor = 0;
if ($basePrice > 1000) {
$discounterFactor = 0.95;
} else {
$discounterFactor = 0.95;
}
return $basePirce * $discounterFactor;
}
我希望把两个临时变量都替换掉.当然每次一个.如果临时变量不止被赋值一次,就不应该进行这项重构.
接下来开始替换变量,每次一个,首先我把赋值动作的右侧表达式提炼出来
/**
* 获取价格
*/
public function getPrice() {
$basePrice = $this->basePrice();
$discounterFactor = 0;
if ($basePrice > 1000) {
$discounterFactor = 0.95;
} else {
$discounterFactor = 0.95;
}
return $basePirce * $discounterFactor;
}
/**
* 获取基础价格
* @return float
*/
private function basePrice() {
return $this->quantity * $this->itemPrice;
}
接着使用Inline Temp.首先把临时变量basePrice的第一个引用点替换掉:
/**
* 获取价格
*/
public function getPrice() {
$discounterFactor = 0;
if ( $this->basePrice() > 1000) {
$discounterFactor = 0.95;
} else {
$discounterFactor = 0.95;
}
return $basePirce() * $discounterFactor;
}
搞定basePrice之后,我再以类似办法提炼出discountFactor():
/**
* 获取基础价格
* @return float
*/
private function basePrice() {
return $this->quantity * $this->itemPrice;
}
/**
* 获取折扣率
* @return float
*/
private function discountFactor() {
if ($this->basePrice() > 1000) {
return 0.95;
} else {
retrun 0.98;
}
}
最终getPrice变成了这样:
/**
* 获取价格
*/
public function getPrice() {
return $this->basePrice() * $this->discounterFactor();
}
网友评论