重新组织函数

《重构:改善既有代码的设计》一书学习笔记。
并没有完全写出书中所有例子,只摘抄了自己认为比较常用的一些,如果感兴趣可以阅读书籍.

原则

  1. 代码的命名和函数应该让程序员看到后就像注释一样,可以不看这段代码的逻辑就知道这段代码是做什么的。
  2. 一个函数只做一件事情,如果函数超过一定行数,比如说一屏,那么这段代码一定做了不止一件事情,可以将函数进行拆分。

方法

提取临时变量

例如:

private double getPrice(){
    int basePrice = quantity * itemPrice;
    double discontFactor;
    if (basePrice > 1000){
        discontFactor = 0.85;
    } else{
        discontFactor = 0.95;
    }
    return basePrice * discontFactor;
}

step1
basePrice是一个通用的计算方式,数量*单价,所以为了保证其他函数也可以调用,我们把临时变量basePrice抽取成basePrice(),结果如下:

private double getPrice(){
    double discontFactor;
    if (basePrice() > 1000){
        discontFactor = 0.85;
    } else{
        discontFactor = 0.95;
    }
    return basePrice() * discontFactor;
}

private int basePrice(){
    return quantity * itemPrice;
}

step2
变量discontFactor,也可以用类似方法提取

private double getPrice(){
    return basePrice() * discontFactor();
}

private int basePrice(){
    return quantity * itemPrice;
}

private double getDiscontFactor(){
    if (basePrice() > 1000){
        return 0.85;
    } else{
        return 0.95;
    }

}

ok,经过上面的提取,我们直接看getPrice方法,可以一眼明确,价格 = 总价 * 折扣,甚至我们根本不用关心总价和折扣是怎么来的,总之我要的只是一个价格.

加入解释性变量

例如,我们经常可以看到,if判断语句中做了复杂的判断,一般令人难以理解,这时候应该将复杂的判断用一个解释行的变量来代替

if((platform.toUpperCase().indexOf("MAC")))
        ||(platform.toUpperCase().indexOf("WINDOWS")){

}

乍一看很长一段判断,不容易让人一眼看明白,我们就可以加入解释性变量解决

boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
boolean isWindowsOs = platform.toUpperCase().indexOf("WINDOWS");
if(isMacOs || isWindowsOs){

}

这样同样的我们不用关心是怎么判断是mac还是windows的,if语句变得清晰明了.

移除对参数的赋值

如果不必要,不要直接对函数的参数赋值,但有些时候是需要的,个人感觉不是很强制.
例1,容易让人误会的赋值,赋值对基本数据类型无效,所以新命名一个变量比较好理解:

public static void main(String[] args){
    int x = 5;
    triple(x);
    print("x = " + x);
}

private static void triple(int x){
    x = x * 3;
    print("x = " + x);
}

例2,对对象赋值

public static void main(String[] args){
    Date d1 = new Date("1 Apr 98");
    nextDateUpdate(d1);
    print("d1 after nextDay" + d1);

    Date d2 = new Date("1 Apr 98");
    nextDateReplace(d2);
    print("d2 after nextDay" + d2);
}

private static void nextDateUpdate(Date date){
    date.setDate(date.getDate() + 1);
    print("date in nextDay" + date);
}

private static void nextDateReplace(Date date){
    date = new Date(date.getYear(), date.getMonth(), date.getDate() + 1);
    print("date in nextDay" + date);
}

替换算法

替换更清晰的算法,例如:

private String foundPerson(String[] people){
    for (int i = 0 ; i < people.length ; i++){
        if("Don".equals(people[i])){
            return "Don";
        }
        if("John".equals(people[i])){
            return "John";
        }
        if("Kent".equals(people[i])){
            return "Kent";
        }
    }
    return "";
}

看起来似乎也比较清晰,但是试想一下,person变成了10个,甚至更多怎么办,是不是要写10个if判断。所以我们采用另一种方式

private String foundPerson(String[] people){
    List candidates = Arrays.asList(new String[]{"Don", "John","Kent"});
    for (int i = 0 ; i < people.length ; i++){
        if(condidates.contains(people[i])){
            return people[i];
        }    
    }
    return "";
}

这样如果加更多的人名,只需要往条件中添加就可以.