6. 技巧

  • 首要的防御手段是封装变量
  • 移除局部变量
  • 变量改名
  • 移动代码
  • 函数改名
  • 移动函数
  • 拆分遍历
  • 以查询取代派生变量
  • 管道操作(如filter和map)可以帮助我们更快地看清被处理的元素以及处理它们的动作。
  • 迁移式做法:如果有必要的话,先对函数体内部加以重构,使后面的提炼步骤易于开展。
  • 当你需要写一行注释时候,就适合重构了

渐进式修改

如果要重构一个已对外发布的API,在提炼出新函数之后,你可以暂停重构,将原来的函数声明为"不推荐使用"(deprecated),然后给客户端一点时间转为使用新函数。等你有信心所有客户端都已经从旧函数迁移到新函数,再移除旧函数的声明。

移除标记参数(Remove Flag Argument)

title content
场景 在函数实现内部,如果参数值只是作为数据传给其他函数,这就不是标记参数;只有参数值影响了函数内部的控制流,这才是标记参数。
意义
定义  
做法 针对参数的每一种可能值,新建一个明确函数。
对于"用字面量值作为参数"的函数调用者,将其改为调用新建的明确函数。
注意

保持对象完整(Preserve Whole Object)

title content
场景
意义 传递整个记录"的方式能更好地应对变化
定义
做法
注意

移除设值函数(Remove Setting Method)

title content
场景 如果为某个字段提供了设值函数,这就暗示这个字段可以被改变。
如果不希望在对象创建之后此字段还有机会被改变,那就不要为它提供设值函数(同时将该字段声明为不可变)
意义 只能在构造函数中赋值,我"不想让它被修改"的意图会更加清晰,并且可以排除其值被修改的可能性——这种可能性往往是非常大的。
定义  
做法  
注意

以命令取代函数(Replace Function with Command)

Warning

命令对象的灵活性也是以复杂性作为代价的。

title content
场景
意义
定义
做法 如果要在作为一等公民的函数和命令对象之间做个选择,95%的时候我都会选函数。
只有当我特别需要命令对象提供的某种能力而普通的函数无法提供这种能力时,我才会考虑使用命令对象。
注意

demo

title content
场景
意义
定义
做法
注意