Litong's Blog

Work to become, not to acquire.

第10章 简化条件逻辑

程序的大部分威力来自条件逻辑,但程序的复杂度也大多来自条件逻辑。

很多条件逻辑是用于处理特殊情况的,例如处理 null 值,可引入空对象消除重复代码。

如果想明确地表述以及检查程序的状态,引入断言是一个不错的补充(不过 JVM 的断言开关默认是关闭的)。

分解条件表达式(Decompose Conditional)

大型函数本身就会使代码的可读性下降,而条件逻辑则会使代码更难阅读。

将大块的条件分支代码分解为多个独立的函数,根据每个小块代码的用途,为分解而得到的新函数命名,从而更清楚地表达自己的意图。

合并条件表达式(Consolidate Conditional Expression)

如果检查条件各不相同,但是最终行为却一致,此时就应该将它们合并为一个条件表达式。

可以将合并后的条件表达式提炼为一个函数,它把描述”做什么“的语句换成了”为什么这样做“。

以fail-fast语句取代嵌套条件表达式(Replace Nested Conditional with Guard Clauses)

条件分支有两类,一类是两个条分支都属于正常行为;另一类则只有一个分支是正常行为,另一个分支是异常的情况。

如果两条分支都是正常行为,就应该使用形如 if…else… 的条件表达式。

如果某个条件及其罕见,就应该单独检查该条件,并 fail-fast-return。

if…else…then 传递给阅读者的信息就是:各个分支有同样的重要性。

而 fail-fast 语句传递的信息是:这种情况不是本函数的核心逻辑所关心的,如果它真发生了,请做一些必要的整理工作,然后退出。

保持代码清晰才是最关键的。

以多态取代条件表达式(Replace Conditional with Polymorhpism)

复杂的条件逻辑是编程中最难理解的东西之一。

很多时候可以将复杂条件逻辑拆分到不同的场景,但使用类和多态能把逻辑拆分表述得更清晰。

多态是面向对象编程的关键特征之一。它也很容易被滥用。

如果现有的类尚不具备多态行为,就用工厂函数创建之,令工厂函数返回恰当的对象实例。

引入特例(Introduce Special Case)

如果代码库中有多处以同样方式应对同一个特殊值,那么就把这个处理逻辑收拢到一处。

创建一个特例元素,用以表达对这种特例的共用行为的处理。

Null 对象是特例模式的一个特殊例子。

引入断言(Introduce Assertion)

常常会有这样一段代码:只有当某个条件为真时,该段代码才能正常运行。

这样的假设通常并没有在代码中明确表现出来,有时候你必须阅读整个算法才能看出——有一种更好的方式:使用断言明确标明这些假设。

断言是一个条件表达式,应该总是为真。如果它失败,表示程序员犯了错误。断言的失败不应该被系统任何地方捕捉。

断言是一种很有价值的交流形式,它告诉阅读者,程序执行到这一点时,对当前状态做了何种假设。

断言应该不会对系统运行造成任何影响,所以”加入断言“永远都应该是行为保持的。

注意,不要滥用断言。它只应该用来检查”必须为真“的条件,用来预防程序员的错误。