‘代码写了几年后,每每遇到看不下的代码,却又苦于找不到好的优化改善的办法,只能用读书少,读码少来挖苦自己了~’
当你在代码里看到一堆if-else,并且还嵌套的时候,第一反应一定是我去喝杯水吧,否则要吐了。今天先把Martin Fowler的原文搬上来,自己的例子后补
1. Decompose Condition(分解条件表达式)
从if,then,else三个段落中分别提炼出独立函数
if(date.before(SUMMER_START) && date.after(SUMMER_END)){
charge = quantity*_winterRate+ _winterServiceCharge;
}
else{
charge = quantity*_summerRate;
}
改造成
if(notSummer(date)){
charge = winterChange(quantity);
}
else{
charge = summerChange(quantity)
}
private boolean notSummer(Date date){
return date.before(SUMMER_START) && date.after(SUMMER_END);
}
private double winterChange(int quantity){
return quantity*_winterRate+ _winterServiceCharge;
}
private double summerChange(int quantity){
return quantity*_summerRate;
}
2. 合并条件表达式
当有一系列的条件测试,都去执行相同的代码或者返回相同的结果时,把这些条件抽取到一个函数中,用逻辑运算联系起来
double disabilityAmount(){
if(_seniority<2)return 0;
if(_monthsDisabled > 12)return 0;
if(_isPartTime) return 0;
}
改成
double double disabilityAmount(){
if(isNotEligibleForDisability())return 0;
}
private boolean isNotEligibleForDisability(){
return (_seniority<2)||(_monthsDisabled > 12)||(_isPartTime);
}
3. 合并重复的条件片段
如果在不同的分支里执行了相同的代码,则考虑将这样的代码放在条件之外执行
4. 移除控制标记
我们经常会写一些标记来传递结果或者用以记录判断何时停止的控制标示,将这种情况替换成break或者continue,或者return语句
void checkSecurity(String[] people){
boolean found = false;
if(int i=0;i<people.length;i++){
if(!found){
if(people[i].equals("Don")){
sendAlert();
found = true;
}
if(people[i].equals("John")){
sendAlert();
found = true;
}
}
}
}
改成
void checkSecurity(String[] people){
if(int i=0;i<people.length;i++){
if(people[i].equals("Don")){
sendAlert();
break;
}
if(people[i].equals("John")){
sendAlert();
break;
}
}
}
5. Replace Nested Conditional with Guard Clauses
如果满足一个条件就能退出整个函数,则直接返回,不要在用else一层层去嵌套
double getPayAmount(){
double result;
if(_isDead){
result = deadAmount();
}else{
if(_isSeparated){
result = separatedAmount();
}else{
result = normalAmount();
}
}
}
改成
double getPayAmount(){
double result;
if(_isDead)return deadAmount();
if(_isSeparated)return separatedAmount();
return normalAmount();
}
Tips:有的时候可能你还得把条件做一次反转,如果它不能标示一个出口的时候,那它的反面也许是可以的。
6. 以多态取代条件表达式
如果根据不同的对象类型而选择不同的行为时,就可以把条件表达式的分支放进子类复写的函数中,然后将原始函数定义为抽象函数
7. 引入Null对象
之前傻乎乎的用了一个ListUtils#EMPTY_LIST。还想往里面put元素。今天看到这个,才知道NULL Object的设计模式。
学习下这个类就ok。
org.apache.commons.collections.ListUtils#EMPTY_LIST
空对象一定是个常量,它的任何成员都不会发生变化。
8. 引入断言
如果某段代码执行的条件一定要满足某个条件的话,那个该条件不被满足的时候就可以执行抛出异常。因此可以直接用断言语句进行判断,从而减少条件语句的使用。