如果一个函数本体和名称一样清楚易懂,就意味着这个函数没有什么作用,此时就可以去除函数调用,替换成函数中的内容。
动机
提炼函数有个度,过度提炼后,会发现小函数无处不在,特别频繁,此时就应该考虑,是不是有些函数可以合并起来呢?
提炼函数从某种意义来讲是一种间接性的体现,它可能带来帮助,但没必要的间接性会适得其反,反而加重了阅读代码的负担。
除此之外,还有一种需要使用内联函数的情况:当手头上的函数东一头西一头,逻辑很乱时,考虑将它们内联成一个大型函数,然后再分解成条理的小函数。
在进行以函数对象取代函数(6.8 Replace Method with Method Object)之前进行内联函数,会有好效果。
以函数对象取代函数(6.8 Replace Method with Method Object):将一群有强关联的函数都放到一个新类中去。当然,方法越少越好。
内联好处在于,能让人有个整体的感观,作为整体移动起来比较简单(如果间接层太多,互相调用过于频繁,会使得有些重构方法很难进行,所以,提炼函数请适可而止)
做法
检查函数,确定它不具多态性。如果子类继承了这个函数,就不能把此函数内联。
找出这个函数的所有被调用点。
将这个函数的所有被调用点都替换为函数本体。
编译、测试。
删除该函数。
你有一个临时变量,只被简单表达式赋值一次,而它妨碍了其他重构手法。
将所有对该变量的引用动作,替换为对它赋值的那个表达式本身。
double basePrice = anOrder.basePrice(); return (basePrice > 1000); >>> return (anOrder.basePrice() > 1000);动机
这其实是很小的一个重构方法,和下一节所讲的以查询取代临时变量几乎一致,真正的动机也和下一节一样。
唯一单独使用内联临时变量的情况是:你发现某个临时变量被赋予某个方法调用的返回值。如果这个临时变量妨碍了提炼函数(6.1 Extract Method),那么就要将其内联化。
做法
检查给临时变量赋值的语句,确保等号右边的表达式没有副作用。
如果这个临时变量并未被声明为final,那就将它声明为final,然后编译。
这是为了检测该临时变量是否真的只被赋值一次。
找到该临时变量的所有引用点,将它们替换为”为临时变量赋值“的表达式。
每次修改后,编译并测试。
修改完所有引用点后,删除该临时变量的声明和赋值语句。
编译、测试。
你的程序每少一个临时变量,就会多一个对某个表达式的引用点。
将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数的调用。此后,新函数就可被其他函数使用。
double basePrice = quantity * itemPrice; if(basePrice > 1000) return basePrice * 0.8; else return basePrice * 0.9; >>> if(getPrice() > 1000) return getPrice() * 0.8; else return getPrice() * 0.9; ... double getPrice(){ return quantity * itemPrice; }动机
首先从临时变量的作用域说起:它们只能在所属函数内使用。也就是说,如果这个变量从始至终贯穿整个方法,那么你就不得不写一个极长的函数来让它一直处于有效的作用域内。
此时,如果将它替换成一句查询,就意味着同一个类中的任意位置都能直接获取这个值,也就是说,我即便把方法分割开来,各部分都能够获取这句查询的值。
以查询取代临时变量往往在运用提炼函数(6.1 Extract Method)之前进行。
这个重构方法较为简单的情况是:临时变量只被赋值一次,或者赋值给临时变量的表达式不受其他条件印象。
但如果临时变量一直在改变,那么我们就不能直接使用这种重构方法,而是先运用分解临时变量(6.6 Split Temporary Variable)或者将查询函数和修改函数分离(10.4 Separate Query from Modifier)。
分解临时变量(6.6 Split Temporary Variable):如果这个临时变量中途被重新赋值(比如一开始a=1;,后来a=10这种直接赋值),那么重新赋值的这个点就可以分隔开,前后就应该分成两个截然不同的变量。
将查询函数和修改函数分离(10.4 Separate Query from Modifier):简单说就是,从前有个函数既修改了对象,又返回了值,那么就把它分成getter和setter两个方法。
这两种重构方法可以让临时变量的情况变得简单。(第一种能保证临时变量只被赋值一次,第二种没理解)
如果你想要替换的临时变量是用来收集结果的(例如循环累加值),就需要把这部分代码也加到查询函数中。(总之就是要通过查询拿到最后结果)