概述
6.1 Extract Method(提炼函数)
解释:有一段代码可以被组织在一起并独立出来。
处理机制:将这段代码放进一个独立的函数中,并让函数名称解释该函数的用途。第三章代码的坏味道,Long Method中也提到,让小函数容易理解的关键在于有一个好的名字,读者可以通过函数名来了解函数的作用。并且有一个原则,每当感觉需要用注释来说明什么的时候,就将需要说明的部分固定到一个函数中,并且给它取个好名字。
提炼函数的动机:函数过长或者一段代码需要注释才能让人理解。
函数提炼的好处:1.提炼后的函数粒度小,被复用的机会更大;2.使高层函数读起来像一系列注释;3.函数的复写更容易。
做法:1.创造新函数,根据函数的意图命名函数;2.将需要提炼的代码复制到新函数中;3.检查代码是否引用“作用于限于源函数”的变量;4.检查是否有“仅用于被提炼代码段”的临时变量,如有,在目标函数中将它们生命为临时变量;5.检查是否有任何局部变量的值被改变;6.将被提炼代码段中需要读取的局部变量当作参数传递给目标;6.在被提炼函数原来位置调用新函数;7.编译,测试;
6.2 Inline Method(内联函数)
解释:一个函数的本体与名称同样清楚易懂,在该函数被调用的地方插入函数本体,移除调用。
动机:1.函数简洁易懂,非必要的间接性让人不舒服;2.需要将一群组织不合理的小函数内联到大函数中再提炼出合理的小函数,在实施Replace Method with Method Object(以函数对象取代函数)前这么做会有不错的效果;3.使用了太多间接层,只为对另外一个函数的简单委托,去除无用的间接层。
做法:1.检查函数确定其不具有多态性(因为如果有子类继承,实施内联函数后子类将无法覆写);2.找出该函数所有被调用点,替换为函数本体;3.编译测试;4.删除该函数定义。
6.3 Inline Temp(内联临时变量)
解释:有一个临时变量只被简单表达赋值一次,而且妨碍了其他重构手法。
处理机制:将所有对该变量的引用动作都替换为对它赋值的表达式自身。
动机:多半作为Replace Temp with Query(以查询取代临时变量)的一部分,正真的动机出现在后者中。唯一单独使用的情况是某个临时变量被赋予某个函数调用的返回值。如果这个临时变量妨碍其他重构手法,就应该将它内联化。
做法:1.检查给临时变量赋值的语句,确保等号右边没有副作用;2.将这个临时变量声明为final,然后编译(可以检查该临时变量是否只被赋值一次);3.将所有引用点替换为“为临时变量赋值”的表达式;4.每次修改完编译测试;5.修改完所有引用点,删除该临时变量声明和赋值语句;6.编译测试。
6.4 Replace Temp with Query(以查询取代临时变量)
解释:程序以一个临时变量保存某一表达式的运算结果。将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数的调用。此后新函数就可以被其他函数使用。
动机:临时变量是暂时的,只能在所属函数内使用,如果将临时变量替换为查询,同一个类中的所有函数都可以获得这个信息。
做法:1.找出只被赋值一次的临时变量并且声明为final;2.编译(检查以确保该临时变量只被赋值一次);3.将“对该临时变量赋值”的语句等号右侧部分提炼到一个独立函数中(声明为private,后期可能有更多类使用它;确保提炼出来的函数无副作用);4.编译测试;5.在该临时变量上实施Inline Temp(内联临时变量)。
6.5 Introduce Explaning Variable(引入解释性变量)
解释:有一个复杂的表达式,将该复杂表达式(或者其中一部分)的结果放进一个临时变量,以此变量的名称来解释表达式的用途。
动机:表达式可能复杂难以阅读,临时变量代替原有表达式,取一个好的名字,例如放入条件语句中,可以方便代码阅读与理解。条件语句中,引入解释性变量显得很有价值,在较长的算法中可以用临时变量来解释每一步算法的意义。
局限:临时变量只在它所处的函数中有意义,更多时候使用提炼函数,当提炼函数难以进行时候,就引入解释性变量。
做法:1.声明final临时变量,将复杂表达式中一部分运算结果赋值给它;2.用声明的临时变量代替对应的表达式;3.编译测试。
6.6 Split Temporary Variable(分解临时变量)
解释:程序有某个临时变量被赋值超过一次,它既不是循环变量也不被用于收集计算结果。——针对某次赋值,创造一个独立、对应的临时变量。
动机:临时变量用途不同,某些用途会导致临时变量被多次赋值,同一个临时变量承担两件不同的事情,会令代码阅读者糊涂,因此,如果临时变量承担多个责任,它就应该被替换(分解)为多个临时变量,每个变量只承担一个责任。
做法:1.在待分解临时变量的声明及第一次被赋值处修改其名称(如果赋值语句是i=i+”xxx”,说明该临时变量在收集结果,则不分解)2.新变量声明为final;3.以第二次赋值动作为界,修改此前对该临时变量的所有引用点,让其引用新临时变量;4.在第二次赋值处重新声明原先临时变量;5.编译测试。
6.7 Remove Assignments to Parameters(移除对参数的赋值)
解释:代码对一个参数进行赋值,以一个临时变量取代该参数的位置。
动机:对参数的赋值降低了代码的清晰度,而且混用了按值传递与按引用传递。
做法:1.建立一个临时变量,将待处理的参数赋值给它;2.以“对参数赋值”为界,将气候所有对此参数的引用点,全部替换为“对此临时变量的引用”;3.修改赋值语句,使其改为对新建之临时变量赋值;4.编译测试。
6.8 Replace Method with Method Object(以函数对象取代函数)
解释:你有一个大型函数,对其中局部变量的使用是你无法采用提取函数手法。——将这个函数放进一个单独对象中,如此一来局部变量就成为对象内的字段,然后你就可以在同一个对象中将这个大型函数分解为多个小型函数。
动机:小型函数优美动人,只要将相对独立的代码从大型函数中提炼出来,就可以大大提高代码的可读性,但是局部变量的存在会增加函数的分解难度,有时候会发现根本无法拆解一个需要拆解的函数,这时候以函数对象取代函数手法就可以将所有局部变量都变成函数对象的字段,然后就可以使用提炼函数了。
做法:1.新建一个类,根据待处理函数的用途来命名这个类;2.在心累中建立一个final字段,保存原先大型函数所在的对象,将这个对象称为源对象。同时针对原函数每个临时变量和每个参数,在新类中建立一个对应的字段保存之;3.在心累中建一个构造函数,接收源对象和原函数的所有参数作为参数;4.在新类中建一个compute()函数;5.将原函数的代码复制到compute()函数中。如果需要调用源对象的任何函数,请通过源对象字段调用;6.编译;7.将旧函数的函数本体替换为这样的话:“创建上述新类的一个新对象,而后调用其中的compute()函数”。
6.9 Substitute Algorithm(替换算法)
解释:想要把某个算法替换为另一个更为清晰的算法,将函数本体替换为另一个算法。
动机:解决问题一般都有多种方法,如果发现做一件事可以有更清晰的方式,就应该用更清晰的方式来代替原来的方式。算法也是一样,“重构”可以把一些较为复杂的东西分解为较为简单的小块,有时候需要删掉整个算法,用更为简单的算法取代原先的算法。
做法:1.准备好另一个(替换用的)算法,让其通过编译;2.针对现有的测试,执行上述的新算法,如果结果与原本的结果相同,重构结束;3.如果测试结果不同于原先,在测试和调试的过程中,以旧算法为比较参考的标准。
最后
以上就是开放乌龟为你收集整理的重构第六章读书笔记(每次命名都不统一。。)的全部内容,希望文章能够帮你解决重构第六章读书笔记(每次命名都不统一。。)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复