1. 简化条件表达式
1.1 Decompose Conditional(分解条件表达式)
你有一个复杂的条件(if-then-else)语句。从if、then、else三个段落中分别提炼出独立函数。
动机
复杂的条件逻辑使得代码的可读性大大降低。
做法
- 将if段落提炼出来,构成一个独立函数。
- 将then段落和else段落都提炼出来,各自构成一个独立函数。
范例:略。
1.2 Consolidate Conditional Expression(合并条件表达式)
你一系列条件测试,都得到相同结果。将这些测试合并为一个条件表达式,并将这个条件表达式提炼成为一个独立函数。
动机
检查条件不同,最终行为却一致。
做法
- 确定这些条件语句都没有副作用。
- 使用适当的逻辑操作符,将一系列相关条件表达式合并为一个。
- 编译,测试。
- 对合并后的条件表达式实施Extract Method。
范例:略。
1.3 Consolidate Duplicate Conditional Fragments(合并重复的条件片段)
在条件表达式的每一个分支上有着相同的一段代码。将这段重复代码搬移到条件表达式之外。
动机
一组条件表达式的所有分支都执行了相同的某段代码。
做法
- 鉴别出执行方式不随条件变化而变化的代码。
- 如果这些共同代码位于条件表达式起始处,就将它移到条件表达式之前。
- 如果这些共同代码位于条件表达式尾端,就将它移到条件表达式之后。
- 如果这些共同代码位于条件表达式中段,就需要观察共同代码之前或之后的代码是否改变了什么东西。如果的确有所改变,应该首先将共通代码向前或向后移动,移至条件表达式的起始处或尾端,再以前面说的办法来处理。
- 如果共通代码不止一条语句,应该首先使用Extract Method将共通代码提炼到一个独立函数中,再以前面所说的办法来处理。
范例:略。
1.4 Remove Control Flag(移除控制标记)
在一系列布尔表达式中,某个变量带有控制标记的作用。以break语句或return语句取代控制标记。
动机
程序中加入了某些控制标记,大大降低条件表达式的可读性。
做法
- 找出让你跳出这段逻辑的控制标记值。
- 找出对标记变量赋值的语句,代以恰当的break语句或continue语句。
- 每次替换后,编译并测试。
范例:略。
1.5 Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件表达式)
函数中的条件逻辑使人难以看清正常的执行路径。使用卫语句表现所有特殊情况。
动机
如果条件分支都是正常行为,就应该使用if…else…。如果某个条件极其罕见,就应该单独检查该条件。
做法
- 对于每一个检查,放进一个卫语句。
- 每次将条件检查替换成卫语句后,编译并测试。
范例:略。
1.6 Replace Conditional with Polymorphism(以多态取代条件表达式)
你手上有个条件表达式,它根据对象类型的不同选择不同的行为。将这个条件表达式的每一个分支放进一个子类内的覆写函数中,然后将原始函数声明为抽象函数。
动机
你需要根据对象的不同类型而采取不同的行为。
做法
- 如果要处理的条件表达式是一个更大函数的一部分,首先对条件表达式进行分析,然后使用Extract Method将它提炼到一个独立函数去。
- 如果有必要,使用Move Method将条件表达式放置到继承结构的顶端。
- 任选一个子类,在其中建立一个函数,使之覆写超类中容纳条件表达式的那个函数。将与子类相关的条件表达式分支复制到新建函数中,并对它进行适当调整。
- 编译,测试。
- 在超类中删掉条件表达式内被复制了的分支。
- 编译,测试。
- 针对条件表达式的每个分支,重复上述过程,直到所有分支都被移到子类内的函数为止。
- 将超类之中容纳条件表达式的函数声明为抽象函数。
范例:略。
1.7 Introduce Null Object(引入Null对象)
你需要再三检查某对象是否为null,将null值替换为null对象。
动机
你需要大量判断对象是否为null时。
做法
- 为源类建立一个子类,使其行为就像是源类的null版本。在源类和null子类中加入isNull()函数,前者的isNull()应该返回false,后者的isNull()应该返回true。
- 编译。
- 找出所有索求源对象却获得一个null的地方。修改这些地方,使它们该而获得一个空对象。
- 找出所有将源对象与null作比较的地方。修改这些地方,使它们调用isNull()函数。
- 编译,测试。
- 找出这样的程序点:如果对象不是null,做A动作,否则做B动作。
- 对于每一个上述地点,在null类中覆写A动作,使其行为和B动作相相同。
- 使用上述被覆写的动作,然后删除对象是否等于null的条件测试。编译并测试。
范例:略。
1.8 Introduce Assertion(引入断言)
某一段代码需要对程序状态作出某种假设。以断言明确表现这种假设。
动机
断言可以作为交流与调试的辅助。在交流的角度上,断言可以帮助程序阅读者理解代码所做的假设;在调试的角度上,断言可以在距离bug最近的地方抓住他们。
做法
- 如果你发现代码假设某个条件始终为真,就加入一个断言明确说明这种情况。
范例:略。
本文引用自图灵程序设计丛书:重构 改善改善既有的代码设计。