终于看到《重构》第六章,开始系统地讲重构的方法。第六章主要讲Composing Methods,今天我想写写这个方法大类中的第一种方法――Extract Method。没有翻译这些作者决定的名字,因为实在无法很好地诠释作者选这个词的意图,所以名字就以英文吧!
先看一下作者书中的简单例子:
原代码:
void printOwing(double amount) {
//print banner
System.out.println(“******************”);
System.out.println(“***Customer Owes***”);
System.out.println(“******************”);
//print details
System.out.println(“name:”+_name);
System.out.println(“amount:”+amount);
}
重构后的代码:
void printOwing(double amount) {
printBanner();
printDetails(amount);
}
void printBanner() {
System.out.println(“******************”);
System.out.println(“***Customer Owes***”);
System.out.println(“******************”);
}
void printDetails(double amount) {
System.out.println(“name:”+_name);
System.out.println(“amount:”+amount);
}
看了上面的例子,可以简单理解为Extract Method就是把比较长的函数分解成更小的函数,然后在原来的函数中依次调用这些分解后的小函数。上面的例子很简单,只是为了说明该方法的实质,在具体的情况下,比较长的函数的表现不是代码长,而是代码语义上距离比较大的几段代码如果存在于一个函数中,就需要把这些代码段提取出来,生成新的功能比较独立的函数。同时要注意这些新函数的命名。作者有一句话说得很好:“name it by what it does, not how it does it”。
在代码提取过程中,如果代码段不涉及到参数,或者只是参数的传递,就像上面的例子一样,是很容易重新生成函数,不需要做什么变动。如果涉及到参数或者临时变量在提取代码段中发生变化,该如何呢?请看下面的例子(对上面的例子做了一些修改):
原代码:
void printOwing() {
Enumeration e = _orders.elements();
double outstanding = 0.0;
printBanner();
//calculate outstanding
while(e.hasMoreElements()) {
Order each = (Order)e.nextElement();
outstanding += each.getAmount();
}
printDetails(outstanding);
}
重构后的代码:
void printOwing() {
printBanner(); //函数体省略
double outstanding = getOutstanding();
printDetails(outstanding); //函数体省略
}
double getOutstanding() {
Enumeration e = _orders.elements();
double outstanding = 0.0;
while(e.hasMoreElements()) {
Order each = (Order)e.nextElement();
outstanding += each.getAmount();
}
return outstanding;
}
可以看出,局部变量outstanding在函数getOutstanding()中发生了变化,所以用返回变化值的方法将变化了的变量赋值给局部变量,就是double outstanding = getOutstanding()的意义所在。