重新组织函数
提炼函数(Extract Method)
- 现象:一个函数过长或需要注释才能让人理解用途
- 好处:小粒度函数易被复用、覆写,且使高层函数更易读
- 做法:
- 创造一个新函数,以“做什么”(函数的意图)命名新函数
- 将提炼出的代码从源函数复制到新函数
- 仔细检查提炼出的代码,看其中是否引用了“作用域限于源函数”的变量(局部变量,源函数参数)
- 检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中将它们声明为临时变量
- 检查被提炼代码段,看是否有任何局部变量的值被它改变。如果一个临时变量值被修改了,看是否可以将被提炼代码段处理为一个查询,并将结果赋值给相关变量。如果很难这样做,或如果被修改的变量不止一个,你就不能仅仅将这段代码原封不动地提炼出来,你可能需要先使用Split Temporary Variable,then try again. 也可以使用Replae Temp with Query将临时变量消灭掉
- 将被提炼代码段中需要读取的局部变量,当做参数传给目标函数
- 处理完所有局部变量后,编译
- 在源函数中,将被提炼代码段替换为对目标函数的调用
Inline method (内联函数)
- 现象:函数本体和名称同样清楚易懂
- 做法:去掉这个函数,直接使用其中的代码。间接性可能带来帮助,但非必要的间接性总是让人不舒服,找出有用的间接层,去除无用的间接层
- 注意,确保该函数不具有多态性
内联临时变量(Inline Temp)
- 现象:一个临时变量只被一个简单的表达式赋值一次,而它妨碍了其他重构手法
- 做法:将所有对该变量的引用动作,替换为对它赋值的那个表达式自身。
- 常在Replace Temp with Query中用到
Replace Temp with Query
- 现象:以一个临时变量保存某一表达式的运算结果
- 做法:将这个表达式提炼到一个独立函数中,将这个临时变量的所有引用点替换为对新函数的调用。此后,新函数就可以被其他函数使用。
Introduce Explaining Variable(引入解释性变量)
- 现象:你有一个复杂而难以阅读的表达式
- 做法:将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途
- 优先使用Extract Method,难以进行时(如,一个拥有大量局部变量的算法),再使用此方法
- Introduce Explaining Variable > Replace Temp with Query > Extract Method
Split Temporary Variable(分解临时变量)
- 现象:一个临时变量被赋值超过一次,被赋予不同意义的值,在函数中承担了一个以上的责任,它既不是循环变量,也不被用于收集计算结果
- 做法:针对每次赋值,创建一个独立、对应的临时变量
Remove Assignments to Parameters(移除对参数的赋值)
- 现象:代码对一个参数进行赋值
- 做法:以一个临时变量取代该参数的位置。如果使用的是“出参数”的语言,不必遵循这条规则。
- 作者使用的Java语言做的介绍,Java只采用按值传递方式。因此,对参数的赋值并不会对调用者造成任何影响
Replace Method with Method Object(以函数对象取代函数)
- 现象:你有一个大型函数,其中对局部变量的使用使你无法采用Extract Method
- 做法:将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。
Substitute Algorithm(替换算法)
- 现象:想要替换某个算法为更清晰的算法
- 做法:将函数本体替换为另一个算法