重新组织函数
大多数问题都源于Long Methods,因为他们往往包含了大量的信息,而这些信息有被函数中错综复杂的逻辑所掩盖,不易甄别。所以重新组织函数中最主要的重构手法就是extract method。在使用extract method的手法时一般需要用到处理参数的一些手法,如:replace temp with query,split temporary varaibable和replace method with method object.
当然如果发现原来的实现方式复杂导致了过程函数,而又另外的更为简明、解决方式更优的方法的话,可以使用substitute algorithm手法替换掉该Method。
一.Extract Method【★】
如果有一段代码可以组织在一起并且独立出来,那么就可以把它们放进一个独立的函数中,并让函数名解释这段代码的用途。
一般如果一个函数过长或者一段代码需要注释才能看懂,那么这段代码就可能需要放进一个可以自解释的独立函数中。
处理步骤:
1.提炼出该代码片段,放到一个新函数中,新函数的函数名能够描述该段代码的用途。
2.找出该新函数中访问到的作用域仅限于源函数的局部变量和参数。
这些变量中较为难处理里主要包括3类基本类型的局部变量和参数:
⑴.对于源函数的参数,直接放到新函数中的参数列表中。
注:应确保原函数中不要修改传入的参数。否则用过使用Remove Assignments to Parameters手法先处理掉。
⑵.仅用于该提炼代码片段的局部变量(临时变量),对于这里变量可以直接在新函数中声明为新函数的局部变量。
⑶.在提炼代码片段以外的地方进行了有意义地赋值或者访问的变量。
如果该代码段中只有一个局部变量被赋值了,那么可以考虑将该新函数修改为一个查询或者返回该变量值的函数。如果这样处理非常难或者有不止一个局部变量被修改了,那么这个段代码可能不能这样原封不动的提炼出来了,可能需要先根据一个变量一个职责的原则先用split temporary avariable等手法先处理下这个方法,然后再尝试提炼。另外也可以先使用relpace temp with query的手法消灭一部分局部变量。
3.处理完局部变量之后,进行编译。
4.替换源函数中的代码段为调用该新函数,并去除不用的局部变量声明。
5.编译,测试。
二.Inline method
如果一个函数的实现同他的函数名称一样明了,而且比较简单。那么就可以将该函数的内容移入到调用该函数的地方去。然后移除该函数。
一般该手法是配合Extract Method使用的,在进行Extract Method之前使用Inline Method,然后使用Extract Method重新组织函数。
注:如果该函数是多态调用的,那么不可以进行这样的重构。
三.Inline Temp
使用不多。
四.Replace Temp with Query
程序中以一个临时变量保存一个表达式的结果,那么可以将该表达式提炼到一个新函数中去,然后在使用这个临时变量的地方换成调用该函数即可。
注:该手法用在Extract Method之前用来减少临时变量。
五.Introduce Explaining Variable
用的不多,基本上都是可以使用extract method。
六.Split Temporary Variables
原则:每个临时变量都应该只承担一个责任。
如果一个变量被赋值了一次以上的(不包括循环变量和结果累计变量),那么就意味着该变量的职责不是一个了,就应该被替换为多个变量,每个变量分担一个职责。
七.Replace Method with Method Object【★】
有一个大型函数,其中局部变量的使用使得你无法采用Extract Method的时候:
将这个函数放到一个单独的对象中,如此一来函数中的局部变量就变成了该对象的属性字段了。然后你就可以在这个对象中将这个大型函数分解成多个小函数了。
处理步骤:
1.根据该大型方法的功能,新建一个类。
2.新类中新建一个final属性保存该大型函数所在的原对象。
3.对于原函数中的局部变量和参数在新对象中新建一个属性与之对应。
4.新建一个构造函数,构造参数包含一个源对象和各个局部变量以及源函数的参数
5.新建方法,然后将原函数搬入(假设命名为compute)
6.重构该函数。
7.编译测试。
8.替换原函数体为new 一个新对象,并调用新建对象的方法compute。
八.Substitute Algorithm
用新算法替换掉旧函数体