1.1 起点
背景:影片出租商店应用。涉及三个类:电影,出租,顾客。
源码链接:
https://github.com/sigma65535/Refactoring_improving_the_design_of_existing_code/tree/master/Chapter1
UML图:
问题所在:
在Customer中statement()这个函数非常长,大约有50行。而且做了不止一件事情。(swich语句完成折扣计算,result完成结果返回输出)。《clean code》中对函数的要求是:短小,一个函数只做一件事等。
Tip:程序需要添加特性时,原有的代码结构无法方便的扩展,此时需要重构。
1.2 重构的第一步
必须建立良好的测试环境,好的测试是重构的根本。
1.3 分解重构statement()
1.2 重构的第一步
必须建立良好的测试环境,好的测试是重构的根本。
1.3 分解重构statement()
函数中最复杂的是switch这个逻辑泥团,如下图所示:
Eclipse IDE中有强大的重构工具,方便我们进行重构。如下:
处理步骤1:将switch这个函数提取为一个单独的函数;
方法:
在statement()函数下,新方法已经抽离出来。
函数的参数变量thisAmount其实是个常数,可以拿到函数里边来进行处理。(《clean code》 函数的参数越少越好)。
进一步,将thisAmount变量重名为改为result更合理。依然是refactor菜单Rename,
这样方法内的thisAmount会一同变为result,这样可以避免手动修改出错。
2.搬移金额计算代码
getCharge()函数并没有涉及Customer类中的变量,因此放这不合适。在该方法中Rental类有关,因此应将getCharge()搬移到Rental.
选中方法后,执行Move……操作,IDE自动会分析方法应该移动到Rental类下边。
金额搬迁之后的,所有类的状态:
3.临时变量往往容易导致大量参数传来传去,观察下边的代码,thisAmount应该删除。
4. 同样的方法来处理frequentRenterPoints的计算代码,将其提炼为一个单独的方法getFrequentRenterPoints(),并移动到Rental类中。
分析上图的矩形区域内的代码,每次进入while循环的if语句时 frequentRenterPoints+2,否则frequentRenterPoints+1;根据此写出代码,并移动到Rental类之后。
frequentRenterPoints()处理之后的UML图如下:
5. 去除临时变量totalAmount,将其值得计算用函数getTotalAmount()替代。
6 同样处理frequentRenterPoints,用方法getFrequentRenterPoints()替代
private int getFrequentRenterPoints(){
int result = 0;
Enumeration<Rental> rentals = _rentals.elements();
while (rentals.hasMoreElements()) {
Rental each = (Rental) rentals.nextElement();
result += each.getFrequentRenterPoints();
}
return result;
}
1.4 利用多态逻辑取代与价格相关的条件逻辑。
引入了state模式来进行重构。
1.5重构总结
各个重构过程中UML的变换图如下: