《重构 改善既有代码的设计》 读书笔记(十九)

tech2022-08-18  129

6.2 内联函数(Inline Method)

如果一个函数本体和名称一样清楚易懂,就意味着这个函数没有什么作用,此时就可以去除函数调用,替换成函数中的内容。

动机

提炼函数有个度,过度提炼后,会发现小函数无处不在,特别频繁,此时就应该考虑,是不是有些函数可以合并起来呢?

提炼函数从某种意义来讲是一种间接性的体现,它可能带来帮助,但没必要的间接性会适得其反,反而加重了阅读代码的负担。

除此之外,还有一种需要使用内联函数的情况:当手头上的函数东一头西一头,逻辑很乱时,考虑将它们内联成一个大型函数,然后再分解成条理的小函数。

在进行以函数对象取代函数(6.8 Replace Method with Method Object)之前进行内联函数,会有好效果。

以函数对象取代函数(6.8 Replace Method with Method Object):将一群有强关联的函数都放到一个新类中去。当然,方法越少越好。

内联好处在于,能让人有个整体的感观,作为整体移动起来比较简单(如果间接层太多,互相调用过于频繁,会使得有些重构方法很难进行,所以,提炼函数请适可而止)

做法

检查函数,确定它不具多态性。

如果子类继承了这个函数,就不能把此函数内联。

找出这个函数的所有被调用点。

将这个函数的所有被调用点都替换为函数本体。

编译、测试。

删除该函数。

6.3 内联临时变量(Inline Temp)

你有一个临时变量,只被简单表达式赋值一次,而它妨碍了其他重构手法。

将所有对该变量的引用动作,替换为对它赋值的那个表达式本身。

double basePrice = anOrder.basePrice(); return (basePrice > 1000); >>> return (anOrder.basePrice() > 1000);

动机

这其实是很小的一个重构方法,和下一节所讲的以查询取代临时变量几乎一致,真正的动机也和下一节一样。

唯一单独使用内联临时变量的情况是:你发现某个临时变量被赋予某个方法调用的返回值。如果这个临时变量妨碍了提炼函数(6.1 Extract Method),那么就要将其内联化。

做法

检查给临时变量赋值的语句,确保等号右边的表达式没有副作用。

如果这个临时变量并未被声明为final,那就将它声明为final,然后编译。

这是为了检测该临时变量是否真的只被赋值一次。

找到该临时变量的所有引用点,将它们替换为”为临时变量赋值“的表达式。

每次修改后,编译并测试。

修改完所有引用点后,删除该临时变量的声明和赋值语句。

编译、测试。

6.4 以查询取代临时变量(Replace Temp with Query)

你的程序每少一个临时变量,就会多一个对某个表达式的引用点。

将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数的调用。此后,新函数就可被其他函数使用。

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两个方法。

这两种重构方法可以让临时变量的情况变得简单。(第一种能保证临时变量只被赋值一次,第二种没理解)

如果你想要替换的临时变量是用来收集结果的(例如循环累加值),就需要把这部分代码也加到查询函数中。(总之就是要通过查询拿到最后结果)

最新回复(0)