跳转到内容

第六部分导读:简化条件逻辑

条件逻辑是程序里最难读的部分。一行赋值只有一条路,一个 if 就有两条,三个 if 套在一起,读者脑子里要同时装着八种可能。更麻烦的是,条件往往同时承担两件事:判断“现在是什么情况”,和决定“这种情况下做什么”。if day >= start and day <= end 这一行,读的人要先翻译成“是不是夏季”,才能接着读下面的算式;嵌套到第三层的正常流程,要先读完所有例外才找得到;同一个 match bird.type 抄在五个函数里,加一种鸟就要改五处,漏一处不会报错,只会在某张卡片上显示“未知”;同一句 if customer == "unknown" 散在几十个调用方,新人漏写一句就是线上的空指针。这一部分的六个手法分别对付这些情况:给条件和分支起名字,把结果相同的条件合并,让例外先返回,把按类型的分支交给多态,用特例对象吸收到处出现的空值检查,以及把代码默默依赖的假设写成断言。它们的共同目标是让条件语句读起来像需求文档里的规则原文。

手法 一句话 流行度 档
分解条件表达式(第 35 章) 把条件和每个分支各提成有名字的函数 ★★★ 完整
合并条件表达式(第 36 章) 把结果相同的几个条件合成一个,再起名 ★★ 精简
以卫语句取代嵌套条件表达式(第 37 章) 特殊情况先检查、先返回,正常流程不缩进 ★★★ 完整
以多态取代条件表达式(第 38 章) 按类型的分支改成每种类型一个子类 ★★★ 完整
引入特例(第 39 章) 用一个特例对象替掉到处出现的同一种特殊值检查 ★★ 完整
引入断言(第 40 章) 把代码依赖的假设写成断言 ★ 速览

闻到什么味道先看哪一章:

  • 过长函数,一个 if 的条件是一串比较、分支是一堆算式,要读三遍才知道在说什么 → 第 35 章 分解条件表达式。
  • 重复代码,几个 if 各自返回同一个值,其实是同一条规则 → 第 36 章 合并条件表达式。
  • 过长函数,if 套 if 套 if,正常流程埋在最深一层 → 第 37 章 以卫语句取代嵌套条件表达式。
  • 重复的 switch,同一个按类型的 switch 或 match 出现在好几个函数里 → 第 38 章 以多态取代条件表达式。
  • 重复代码,到处都在写 if x is None 或 if customer == "unknown",而且应对都一样 → 第 39 章 引入特例。