读这本书的初衷是想对自己的代码以旁观者的角度进行一番审查,所以选择了这本网上大家都推荐的书籍——《重构 改善既有代码的设计》。这本书上提供了很多重构代码的技巧方法。个人认为重构最直观的感受是“提高代码的阅读效率”,什么意思?就是当接手你代码的同事能够很快的理解这段代码的意思以及编写上的思维角度,就是能够读懂你当时处理数据的逻辑方式。另一方面就是“提高代码的质量”,接手工作的同事在阅读的同时能够搁在心里连连称赞这段代码编写方式,说明你的重构是有效。
一、重新组织函数
1、Extract Method(提炼函数)(P110)
“你有一段代码可以被组织在一起并独立出来”
Extract Method个人感觉是重构代码最常用的一个方法,在code review或者自我检查代码的时候,应该都会用到这个方法。
动机:
过长的函数或者需要注释才能让人理解用途的代码,这个时候就需要考虑将这段代码放进一个独立的函数。
当你发现代码中有大量的注释来解释这段代码的用途的时候,你就需要着手对这段代码进行重构提炼了,这也是新手重构代码的入口。
做法:
(1)创造一个新函数,根据这个函数的意图对它来命名(命名也是重构的一种方法),命名要做到“见名之意”,让别人看到名字就知道这段代码的用途
(2)将提炼出的代码从源函数复制到新建的目标函数中
(3)检查变量(局部变量和源函数参数),当被提炼代码段中需要读取局部变量时,这是就需要将局部变量当作参数传给目标函数;当有临时变量仅作用于被提炼代码段时,在目标函数中将它们声明为临时变量。这部分是整个Extract Method的精髓所在,需要处理好
(4)处理完所有局部变量之后,进行编译
(5)在源函数中,将被提炼断码段替换为对目标函数的调用
(6)编译,测试
提炼函数这种方式,可以直接使用IDE工具中的快捷键,可以很方便的帮你处理第三个步骤中的变量,自动的检测被提炼代码段所需要的一些参数
2、Replace Temp with Query(以查询取代临时变量)
将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数的调用。此后,新函数就可能被其他函数使用。
看到这中重构方式之后,自己也经常在代码中运用这中手段。去掉一些临时变量的运用,简化一些代码。
动机:
临时变量是暂时的,只能在所属函数内使用。由于临时变量只在所属函数内可见,所以会驱使写出更长的函数。如果把临时变量替换为一个查询,那么同一个类中的所有函数都将可以获得这份信息。
这种重构的最简单情况就是:临时变量只被赋值一次,或者赋值给临时变量的表达式不受其他条件影响
做法:
(1)找出只被赋值一次的临时变量
(2)将该临时变量声明为final
(3)编译(确保该临时变量的确只被赋值一次)
(4)将“对该临时变量赋值”的语句的等号右侧部分提炼到一个独立函数中
(5)编译,测试
(6)在该临时变量身上实施Inline Temp(P119)
范例:
示例函数
double getPrice(){
int basePrice=_quantity*_itemPrice;
double discountFactor;
if(basePrice>1000)
discountFactor=0.95;
else
discountFactor=0.98;
return basePrice*discountFactor;
}
声明为final
double getPrice(){
final int basePrice=_quantity*_itemPrice;
final double discountFactor;
if(basePrice>1000)
discountFactor=0.95;
else
discountFactor=0.98;
return basePrice*discountFactor;
}
替换临时变量
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 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;
}
替换其他临时变量,删掉临时变量
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;
}
提炼discountFactor()
double getPrice(){
final double discountFactor=discountFactory();
return basePrice()*discountFactor;
}
private int basePrice(){
return _quantity*_itemPrice;
}
private double discountFactor(){
if(basePrice()>1000)
reurn 0.95;
else
return 0.98;
}
最终重构函数getPrice()
double getPrice(){
return basePrice()*discountFactor();
}
private int basePrice(){
return _quantity*_itemPrice;
}
private double discountFactor(){
if(basePrice()>1000)
reurn 0.95;
else
return 0.98;
}
在实际的开发过程中,如果能一眼就能发现的简单的可替换的临时变量,不妨动手试试!
重构之后,发现代码行数变多了,方法增加了,但是整体看上去,发现逻辑清楚了。