1. 重构定义:
重构是对软件内部结构的调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
2. 重构节奏:
小步前进,频繁测试。
3. 重构意义:
1. 改进软件设计
2. 使软件更容易被理解
3. 帮助找到 bug
4. 提高编程速度
恶劣的设计会让你的速度慢下来,你会把时间花在调试上面,无法添加新功能,修改时间越来越长,因为你必须花更多时间来理解系统,寻找重复代码。
5. 获得更高层次的认识
4. 何时重构
1. 重复代码
2. 过长函数
有注释的地方一般需要重构
3. 过大的类
4. 过多的 switch 或者 if else
switch 或者 if else 过多会导致有任何修改都需要修改 switch,而且枚举如果在多个地方使用就会涉及多个地方修改
5. 重构的技巧
1.Extract Method:提炼函数
1.1. 重构场景:
方法过长,代码中注释过多
1.2. 做法
创建一个新函数,根据它的意图来命名(以【做什么】而不是【怎么做】来命名)。
2.Inline Temp:内联临时变量
2.1. 重构场景
一个内联变量被简单的表达式赋值一次
2.2. 做法
取消赋值动作,直接替换为对它赋值的表达式本身
2.3. 举例
double basePrice = getBasePrice();
return basePrice;
应该改为
return getBasePrice();
3.Replace Temp with Query 以查询取代临时变量
3.1. 重构场景
以临时变量保存某一表达式结果,临时变量的问题在于,它们是临时性 的,而且只能在所属的函数内访问,所以它 会驱使你写出更长的函数,只有这样你才能访问到那些临时变量。如果把临时变量替换为一个查询,那么同一个类中的所有函数都可以访问这个临时变量。
3.2. 做法
将临时变量使替换为新函数引用
3.3. 举例
重构前
public class Base {
private int quantity;
private int itemPrice;
public double getTotalPrice() {
double basePrice = quantity * itemPrice;
if(basePrice < 1000) {return basePrice * 0.95;} else {return basePrice * 0.98;}
}
}
第一次:重构后
取消临时变量 -> 变成函数引用
public class Base {
private int quantity;
private int itemPrice;
public double getTotalPrice() {if(basePrice() < 1000) {return basePrice() * 0.95;
} else {return basePrice() * 0.98;
}
}
public double basePrice() {return quantity * itemPrice;}
}
再次重构:
获取结果方法从打折和总额耦合 -> 把打折逻辑独立出去
public class Base {
private int quantity;
private int itemPrice;
public double getTotalPrice() {return basePrice() * discountFactor();}
public double basePrice() {return quantity * itemPrice;}
public double discountFactor() {if(basePrice() > 1000) {return 0.95;} else {return 0.98;}
}
}
4.Introduce Explaining Variable:引入解释变量
对于复杂查询通过引入解释变量来降低复杂性。
怎么区分使用 Extract Method 还是 Introduce Explaining Variable 呢?
在一个方法里面临时变量很多,使用 Extract Method 变得很困难的时候使用它。