引言
- 对付过长函数,一项重要的重构首发就是Extract Method(提炼函数),它把一段代码从原先函数中提取出来,放进一个单独函数中。Inline Method(内联函数)正好相反:将一个函数调用动作替换为该函数本体。如果在进行多次提炼之后,意识到提炼所得的某些函数并没有做任何实质事情,或如果需要回溯恢复原先函数,就需要Inline Method。
- Extract Method最大的困难就是处理局部变量,而临时变量则是其中一个主要的困难源头。处理一个函数时,可以运用Replace Temp with Query(以查询取代临时变量)去掉所有可去掉的变量。如果很多地方使用了某个临时变量,则先运用Split Temporary Variable(分解临时变量)将它变得更容易替换。
- 有时临时变量太过混乱,难以替换。这时候我就需要使用Replace Method with Method Object(以函数对象取代函数)。它让我可以分解哪怕最混乱的函数,代价则是引入一个新类
- 参数带来的问题比临时变量稍微少一些,前提是你不在函数内赋值给它们。如果你已经这样做了,就得使用Remove Assignments Parameters(移除对参数的赋值)
- 函数分解完成后,就可以知道如何让它工作得更好。也许还会发现算法可以改进,从而使代码更清晰。这时就可以使用Substitute Algorithm(替换算法)引入更清晰的算法
1. Extract Method(提炼函数)
情景:你有一段代码可以被组织在一起并独立出来
做法:将这段代码放进一个独立函数中,并让函数名称解释该函数的用途。
动机:如果每个函数的粒度都很小,那么函数被复用的机会就更大;这会使高层函数读起来就像一系列注释;如果函数都是细粒度,那么函数的复写也会更容易些。
2. Inline Method(内联函数)
情景:一个函数的本体与名称同样清楚易懂
做法:在数据调用点插入函数本体,然后移除该函数
动机:间接性可能带来帮助,但非必要的间接性总是让人不舒服
3. Inline Temp(内联临时变量)
情景:有一个临时变量,只被一个简单表达式赋值一次,而它妨碍里其他重构方法
做法:将所有对该变量的引用动作,替换为对它赋值的那个表达式自身
4. Replace Temp with Query(以查询取代临时变量)
情景:程序以一个临时变量保存某一表达式的运算结果
做法:将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数的调用。此后,此函数就可被其他函数使用(我不完全赞同这一点,如果在同一个函数中,查询一次赋值给一个临时变量,后续用这个临时变量即可)
动机:把临时变量替换为一个查询,那么同一个类中的所有函数都将可以获得这份信息
5. Introduce Explaining Variable(引入解释性变量)
情景:有一个复杂的表达式
做法:将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途
动机:表达式有可能非常复杂而难以阅读,这种情况下,临时变量可以帮助你将表达式分解为比较容易管理的形式
6. Split Temporary Variable(分解临时变量)
情景:有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果
做法:针对每次赋值,创造一个独立、对应的临时变量
动机:同一个临时变量承担两件不同的事情,会令代码阅读者糊涂
7. Remove Assignments to Parameters(移除对参数的赋值)
情景:代码对一个参数进行赋值
做法:以一个临时变量取代该参数的位置
8. Replace Method with Method Object(以函数对象取代函数)
情景:有一个大型函数,其中对局部变量的使用使你无法采用Extract Method
做法:将这个函数放进一个单独对象中,如此依赖局部变量就成了对象内的字段。然后就可以在同一个对象中将这个大型函数分解为多个小型函数
9. Substitute Algorithm(替换算法)
情景:你想把某个算法替换为另一个更清晰的算法
做法:将函数本体替换为另一个算法
网友评论