第9章 简化条件表达式
简介:
这章主要是讲解了怎样简化程序中的条件表达式,简化代码逻辑。
分解条件表达式(Decompose Conditional)
1.理解:
你有一个复杂的条件(if-then-else)语句,可以从if,then,else三个段落中分别提炼独立函数。
2.动机:
越来越多复杂的条件表达式,会增加阅读代码的难度。所以分解,提炼成多个独立函数是很有必要的。提炼出的函数根据每个小块代码用途来命名,清楚表达自己的意图。
3.做法:
类似“以查询替代临时变量”的方式,这里是以查询替代表达式。
合并条件表达式(Consolidate Conditional Expression)
1.概念:
你有一系列条件测试,都得到相同的结果。将这些测试合并为一个条件表达式,并将这个条件表达式提炼成为一个独立函数。
//合并前 double disabilityAmount() { if (seniority < 2) return 0; if (monthsDisabled > 12) return 0; if (isPartTime) return 0; } //合并后 double disabilityAmount { if (isNotEligableForDisability()) return 0; }
2.做法:
先将这些能合并的表达式合并,到底用提炼函数将它们提取到一个函数里,还是用一个完整表达式直接显示出来,视情况而定。
合并重复的条件片段(Consolidate Duplicate Conditional Fragments)
1.概念:
很好理解,顾名思义。
//合并前 if (isSpecialDeal()) { total = price * 0.95; send(); } else { total = price * 0.98; send(); } //合并后 if (isSpecialDeal()) { total = price * 0.95; } else { total = price * 0.98; } send();
移除控制标记(Remove Control Flag)
1.概念:
在一系列布尔表达式中,某个变量带有“控制标记”的作用,则以break语句或者return语句取代控制标记。
2.动机:
移除控制标记会使条件语句的用途更加清晰。
3.例子:
//改变前 public class ControlMark { public void checkSecurity(String[] people) { boolean found = false; for (int i = 0; i < people.length; i++) { if (!found) { if (people[i].equalsIgnoreCase("Don")) { //do something found = true; } if (people[i].equalsIgnoreCase("John")) { //do something found = true; } } } } //改变后 public String checkSecurityAfer(String[] people) { for (int i = 0; i < people.length; i++) { if (people[i].equalsIgnoreCase("Don")) { //do something return "Don"; } if (people[i].equalsIgnoreCase("John")) { //do something return "John"; } } return " "; } }
以卫语句取代嵌套条件表达式(Replace Nested Conditional with Guard Clauses)
1.什么是卫语句:
卫语句就是把复杂的条件表达式拆分成多个条件表达式,比如一个很复杂的表达式,嵌套了好几层的if - then-else语句,转换为多个if语句,实现它的逻辑,这多条的if语句就是卫语句。
2.概念:函数中的条件逻辑使人难以看清正常的执行路径,使用卫语句表现所有特殊情况。
//改变前 public class ComplicatedClauses { public void soulStandard() { String soulmate = ""; if ("boy".equalsIgnoreCase(soulmate)) { //not accept; } else if ("bad temperature".equalsIgnoreCase(soulmate)){ //not accept; } else { if ("beauty".equalsIgnoreCase(soulmate)) { if ("nice smile".equalsIgnoreCase(soulmate)) { //accept } else { //not accept } } } } } //使用卫语句,改变后 public class ComplicatedClauses { public void soulStandard() { String soulmate = ""; if ("boy".equalsIgnoreCase(soulmate)) { //not accept } if ("bad temperature".equalsIgnoreCase(soulmate)) { //not accept } if ("beauty".equalsIgnoreCase(soulmate) && "nice smile".equalsIgnoreCase(soulmate)) { //accept } else { //not accept } } }
3.动机:
条件表达式通常有两种表达形式:
(1)所有分支都属于正常行为,用if...else...语句。
(2)条件表达式提供的答案中只有一种是正常行为,其他都是不常见的,用卫语句。
→其实“以卫语句取代嵌套条件表达式”方法的精髓就是,给某条分支以特别的重视,如果它真的发生了,请做一些必要整理工作,然后退出。if...then...else各分支的重视程度是相等的。
4.注意:
在以卫语句表达时,可以考虑将条件反转
//原式 if (result > 0) { .... } //改为 if (result <= 0) return result;
以多态取代条件表达式(Replace Conditional with Polymorphism)
1.概念:
你手上有个条件表达式,它根据对象类型的不同而选择不同的行为。将这个条件表达式的每个分支放进一个子类的覆写函数中,然后将原始函数声明为抽象函数。
//原式
public double getSpeed() { switch (type) { case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; case NORWEGIAN_BLUE: return (isNailed) ? 0 : getBaseSpeed(voltage); } throw new RuntimeException("Should be unreachable"); }
引入Null对象(Introduce Null Object)
1.概念:
你需要再三检查某对象是否为null,将null值替换为null对象。
2.疑问:
将null替换为null对象,现在貌似没有看到这么做的了?
引入断言(Introduce Assertion)
1.概念:
某一段代码需要对程序状态做出某种假设。以断言明确表现这种假设。
2.经验:
目前经历中一般在测试类加,其他情况视情况而定。