8.1搬移函数
动机:根本目的是为了更好的模块化,直接原因是:如果一个函数频繁引用其他上下文,可能说明这个函数跟另一个上下文的关系更加紧密,此时,让这个函数与那些更亲密的元素相会,也许可以取得更好的封装效果。
在类之间搬移函数
class Acount{
double getBankCharge(){
double result = 4.5;
if(this.daysOverdraw > 0) result += getOverdraftCharge();
return result;
}
double getOverdraftCharge(){
if(this.type.getIsPremium()){
double baseCharge = 10;
if(this.daysOverdraw <= 7)
return baseCharge;
return baseCharge + (this.daysOverdraw - 7)*0.85;
} else {
return this.daysOverdrawn * 1.75;
}
}
}
//可以看到,OverdraftCharge透支金额折扣计算与账户的类型this.type有关,所以可以考虑移动到type类型中
//而daysOverdrawn与具体的账户有关,所以不能移动都type类型,需要通过参数传递
class AcountType{
Boolean isPremium;
double getOverdraftCharge(double daysOverdrawn){
if(this.getIsPremium()){
double baseCharge = 10;
if(daysOverdraw <= 7)
return baseCharge;
return baseCharge + (daysOverdraw - 7)*0.85;
} else {
return daysOverdrawn * 1.75;
}
}
}
class Acount{
double getOverdraftCharge(){
return this.type.getOverdraftCharge(this.daysOverdraw);
//也可以直接内联到getBankCharge函数中
}
}
8.2搬移字段
动机:良好的数据结构是一个健壮程序的根基,但很难一开始便能设计好的数据结构。
发现:
- 传入一个参数时,总是需要传入另一个记录的某条字段
- 总是一同出现,一同作为函数传递的数据——和数据泥团有什么区别?
- 修改一条记录时,总是需要改动另一条记录
- 更新一个字段,总是要再多个结构中同时修改
class Customer{
String name;
double disCountRate;
CustomerContract contract = new CustomerContract(new Today());
//使用到discount的函数
double usedDisCount(){
return this.disCountRate = this.disCountRate + 0.3;
}
}
class CustomerContract{
private Day day;
public CustomerContract(Day day){
this.day = day;
}
}
//希望把顾客中的discountRate移动到合同中
class Cutomer(){
double getDisCount(){
return this.contract.getDisCountRate();
}
void setDisCount(double discount){
this.contract.setDisCountRate(discount);
}
//使用到discount的函数
double usedDisCount(){
return getDisCount() + 0.3;
}
}
class CutomerContract(){
double disCountRate();
}
8.3搬移语句到函数
动机:消除重复代码
8.4搬移语句到调用者
动机:程序的抽象能力来自函数,而抽象边界并非总是很好平衡,随着系统的演进,边界可能已经偏移:曾经视为一个整体的行为,可能已经分化出多个不同的关注点,以往多个地方共用的行为,现在可能需要在某些调用点表现出不同的行为。
步骤:先提炼函数,再在调用点进行内联
8.5 以函数调用取代内联代码
动机:可以将相关行为打包,通过良好的函数命名提升代码的表达能力。
8.6移动语句
动机:让存在关联的代码一起出现,可以使代码更容易理解。
8.7拆分循环
动机:经常有身兼多职的循环,若在一次循环中做了多件事情,意味着需要同时理解多件事情,而拆分循环可以让你一次只理解一件事情。此外,拆分循环后还可以提炼函数,将每一个循环提炼到有单独意义的函数。
People[] peoples = getAllPeoples();
for(People people : peoples){
if(paople.age < youngest)
youngest = people.age;
totalSalary+=people.salary;
}
//重构后
double getYoungest(){
...
for(People people : peoples){
if(paople.age < youngest)
youngest = people.age;
}
return youngest;
}
double getTotalSalary(){
for(People people : peoples){
totalSalary+=people.salary;
}
return totalSalary;
}
8.8以管道取代循环
动机:增强代码可读性
java中的stream
8.9移除死代码
动机:消除无用代码带来是思维负担