将这段代码放进一个独立函数中,并合理命名该函数名称
示例:
修改前:
public function printOwing($amount) {
$this->printBanner();
print("name: {$this->name}");
print("amount:{$amount}");
}
修改后:
public function printOwing ($amount) {
$this->printBanner();
$this->printDetail($amount);
}
public function printDetail ($amount) {
print("name: {$this->name}");
print("amount:{$amount}");
}
- 动机
- 函数粒度小,提升被复用几率
- 顶层函数读起来像一系列的注释
- 函数的复写更容易些
- 做法
- 创建一个新函数,根据其做什么而不是以它怎么做来命名
- 从源函数复制提炼出的代码 到新建的目标函数中
- 检查是否有仅用于被提炼代码段的临时变量,如果有的话需要在目标函数中声明为临时变量
- 检查被提炼代码段,看看是否有任何局部变量被其改变.如果一个临时变量的值被修改了,看看是否可以将被提炼代码段处理为一个查询,并将结果赋值给相关变量.如果很难这样做或者被修改的变量不止一个,则你就不仅仅需要将这段代码原封不动的提炼出来.你可能需要使用Split Temporary Variavle(分离临时变量),然后在尝试提炼.也可以使用Replace Temp With Query(查询代替临时变量)将临时变量消灭掉
- 将被提炼代码段中需要读取的局部变量,当做参数传给目标函数
- 在源函数中, 将被提炼代码段替换为对目标函数的调用
实例1:含有简单的变量
局部变量最简单的情况:被提炼的代码段只是读取这些变量的值,并不修改他们.这种情况下我们可以简单的将它们当做参数传给新建的函数
修改前:
/**
* 打印欠款
* @param $orders
*/
public function printOwing() {
$outStanding = 0.0;
// print banner
print_r("**************************");
echo "<br>";
print_r("******Customer Owes*******");
echo "<br>";
print_r("**************************");
foreach ($this->orders as $order) {
$outStanding += $order->getAmount();
}
// printDetail
print("name: {$this->name}");
echo "<br>";
print("amount: {$outStanding}");
}
修改后
/**
* 打印欠款
* @param $orders
*/
public function printOwing() {
$outStanding = 0.0;
$this->printBanner();
foreach ($this->orders as $order) {
$outStanding += $order->getAmount();
}
$this->printDetail($outStanding);
}
/**
* 打印banner
*/
public function printBanner() {
print_r("**************************");
echo "<br>";
print_r("******Customer Owes*******");
echo "<br>";
print_r("**************************");
}
/**
* 打印详情
* @param $outStanding
*/
public function printDetail($outStanding) {
print("name: {$this->name}");
echo "<br>";
print("amount: {$outStanding}");
}
实例2:对局部变量再赋值
如果被提炼代码段对局部变量赋值了,问题就变得复杂了.这里只讨论临时变量的问题.如果你发现源函数的参数被赋值,应该马上使用Remove Assignments to Parameters.
被赋值的临时变量分为两种情况:
- 这个变量只在被提炼代码中使用,可以将这个临时变量的声明移到被提炼代码中.然后一起提炼出去.
- 被提炼代码之外的代码也使用了这个变量,这又分为两种情况:
- 如果这个变量在被提炼代码段之后未被使用, 直接在目标函数中修改它就可以了.
- 如果被提炼代码段之后的代码还使用了这个变量, 需要让目标函数返回改变量改变后的值
在上次代码的基础上将计算代码提炼出来:
/**
* 打印欠款
* @param $orders
*/
public function printOwing() {
$this->printBanner();
$outStanding = $this->getOutStanding();
$this->printDetail($outStanding);
}
/**
* 打印banner
*/
public function printBanner() {
print_r("**************************");
echo "<br>";
print_r("******Customer Owes*******");
echo "<br>";
print_r("**************************");
}
/**
* 打印详情
* @param $outStanding
*/
public function printDetail($outStanding) {
print("name: {$this->name}");
echo "<br>";
print("amount: {$outStanding}");
}
/**
* 计算
* @param $orders
* @return float
*/
public function getOutStanding() {
$result = 0.0;
foreach ($this->orders as $order) {
$result += $order->getAmount();
}
return $result;
}
本例中$result只在被提炼代码中被初始化为明确初值,所以只在新函数中对它初始化,如果代码还对这个变量做了其他处理.就必须将它的值作为参数传给目标函数,对于这种变化,最初的代码可能是这样的
/**
* 打印欠款
* @param $orders
*/
public function printOwing($perviousAmount) {
$outStanding = $perviousAmount * 1.5;
$this->printBanner();
foreach ($this->orders as $order) {
$outStanding += $order->getAmount();
}
$this->printDetail($outStanding);
}
被提炼后的代码可能是这样的:
/**
* 打印欠款
* @param $orders
*/
public function printOwing($previousAmount) {
$this->printBanner();
$outStanding = $this->getOutStanding($perviousAmount * 1.5);
$this->printDetail($outStanding);
}
/**
* 计算
* @param $orders
* @return float
*/
public function getOutStanding($outStanding ) {
$result = $outStanding;
foreach ($this->orders as $order) {
$result += $order->getAmount();
}
return $result;
}
这时候, 你可能会问: "如果需要返回的变量不止一个怎么办?", 最通常的选择是挑选另一块代码来提炼.如果你的语言支持多值返回,可以使用他们带回多个回传值









网友评论