跳转到内容

第七部分导读:重构 API

函数的内部写得再好,调用方看到的只有它对外的样子:名字、参数、返回值,以及调用它会不会顺手改掉什么。这一部分的手法都在处理这个外观。外观不好,代价落在每一个调用处:调用处写着 delivery_date(order, True),读的人得跳进函数里才知道 True 是加急;调用方先从房间对象里取出最低温和最高温再分别传进去,函数要多看一个字段,所有调用方都得跟着改;一个查名单的函数顺手拉响了警报,于是谁都不敢为了“看一眼”去调用它。

判断标准有两条。第一,调用处读起来是否就是它要做的事,不需要跳进函数体去核对。第二,函数要的数据变了,或者行为分了叉,改动是否只落在函数内部,而不是摊到每个调用方。第 6 章的改变函数声明是这一部分所有手法的基础工具,本部分的大多数手法,最后一步都是一次迁移式的改声明。

手法 一句话 流行度 档
将查询函数和修改函数分离(第 42 章) 返回值的函数不改状态 ★★★ 完整
函数参数化(第 43 章) 几个只差一个值的函数合成一个 ★★ 精简
移除标记参数(第 44 章) 用两个有名字的函数替掉布尔开关 ★★★ 完整
保持对象完整(第 45 章) 传整个对象,而不是从它身上拆出来的几个值 ★★ 精简
以查询取代参数 / 以参数取代查询(第 46 章) 函数自己能算的值不要传;外部状态改成参数传进来 ★★ 精简
移除设值函数(第 47 章) 创建后不该变的字段不提供修改方法 ★ 速览
以工厂函数取代构造函数(第 48 章) 用有名字的函数创建对象 ★★ 精简
以命令取代函数 / 以函数取代命令(第 49 章) 拆不动的长函数变成对象;没用上对象能力的命令变回函数 ★★ / ★ 精简

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

  • 可变数据,一个返回结果的函数顺手改了共享状态 → 第 42 章 将查询函数和修改函数分离;字段只该在创建时设一次 → 第 47 章 移除设值函数。
  • 过长参数列表,调用处写着 f(x, True) → 第 44 章 移除标记参数;参数是从同一个对象里拆出来的 → 第 45 章 保持对象完整;参数能由函数自己算出 → 第 46 章 以查询取代参数。
  • 重复代码,几个函数只差几个字面量 → 第 43 章 函数参数化。
  • 全局数据,函数内部读了全局变量,测试要先摆弄它 → 第 46 章 以参数取代查询。
  • 过长函数,局部变量缠在一起、提炼函数拆不动 → 第 49 章 以命令取代函数。