心法
2022-01-01 18:23:14 6 举报
1111111111111
作者其他创作
大纲/内容
Extract Method(提炼函数)_____你有一段代码可以组织在一起并独立出来
创造一个新函数,根据这个函数的意图来对它命名。以它做什么来命名,而不是以它“怎样做”来命名。
将提炼出的代码从源函数复制到新建的目标函数中
仔细检查提炼出的代码,看看其中是否引用了“作用域限于源函数”的变量,包括局部变量和源函数参数
检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中把它们声明为临时变量
检查被提炼代码段,看看是否有任何局部变量的值被他改变。如果一个临时变量值被修改了,看看能不能提炼成一个查询函数,如果被修改的变量不止一个,你就不能仅仅将这段代码原封不动的提炼出来。
将被提炼代码段中需要读取的局部变量,当作参数传给目标函数
Inline Method(内联函数)_____一个函数的本体与名称同样清楚易懂
内部代码和函数同样清晰,去掉这个函数,直接使用代码,间接性可能带来帮助,但非必要的间接性总是让人不舒服
手上有一群组织不甚合理的函数。你可以将他们都内联到一个大型函数中,再从中提炼出组织合理的小型函数。
检查函数,确定它不具多态性
找出这个函数的所有被调用点
将这个函数的所有被调用点都替换为函数本体
遇到复杂情况,那么就不应该使用这个重构手法
lnline Temp(内联临时变量)
你有一个临时变量,只被一个简单表达式赋值一次,而它妨碍了其他重构手法,将所有对该变量的引用动作,替换为对它赋值的那个表达式自身。
你发现某个临时变量被赋予某个函数调用的返回值。一般来说,这样的临时变量不会有任何危害,可以放心地把它留在那儿。但如果这个临时变量妨碍了其他的重构手法,例如Extract Method(110),你就应该将它内联化。
做法:
检查给临时变量赋值的语句,确保等号右边的表达式没有副作用。
如果这个临时变量并未被声明为fina1,那就将它声明为fina1,然后编译。找到该临时变量的所有引用点,将它们替换为“为临时变量赋值”的表达式修改完所有引用点之后删除该临时变量的声明和赋值语句
→这可以检查该临时变量是否真的只被赋值一次,最后删除该临时变量
如果这个临时变量并未被声明为fina1,那就将它声明为fina1,然后编译。找到该临时变量的所有引用点,将它们替换为“为临时变量赋值”的表达式修改完所有引用点之后删除该临时变量的声明和赋值语句
→这可以检查该临时变量是否真的只被赋值一次,最后删除该临时变量
Replace Temp With Query(以查询取代临时变量)____你的程序以一个临时变量保存某一表达式的运算结果
临时变量的问题在于:它们是暂时的,而且只能在所属函数内使用。由于临时变量只在所属函数内可见,所以它们会驱使你写出更长的函数,因为只有这样你才能访问到需要的临时变量。如果把临时变量替换为一个查询,那么同一个类中的所有函数都将可以获得这份信息。这将带给你极大帮助,使你能够为这个类编写更清晰的代码。
Introduce Explaining Variable(引入解释性变量)____你有一个复杂的表达式
这是一个很常见的重构手法,但我得承认,我并不常用它。我几乎总是尽量使用Extract Method(110)来解释一段代码的意义。毕竟临时变量只在它所处的那个函数中才有意义,局限性较大,函数则可以在对象的整个生命中都有用,并且可被其他对象使用
Split Temporary Variable(分解临时变量)____你的程序有某个变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果
临时变量应该只被赋值一次。如果它们被赋值超过一次,就意味它们在函数中承担了一个以上的责任。如果临时变量承担多个责任,它就应该被替换(分解)为多个临时变量,每个变量只承担一个责任。同一个临时变量承担两件不同的事情,会令代码阅读者糊涂。
在待分解临时变量的声明及其第一次被赋值处,修改其名称。
如果稍后之赋值语句是[i=i+某表达式]形式,就意味这是个结果收集变量,那么就不要分解它。结果收集变量的作用通常是累加、字符串接合、写入流或者向集合添加元素。
如果稍后之赋值语句是[i=i+某表达式]形式,就意味这是个结果收集变量,那么就不要分解它。结果收集变量的作用通常是累加、字符串接合、写入流或者向集合添加元素。
Remove Assignments to Parameters(移除对参数的赋值)____代码对一个参数进行赋值
建立一个临时变量,把待处理的参数值赋予它。
以对参数的赋值为界,将其后所有对此参数的引用点,全部替换为“对此临时变量的引用”
Replace Method With Method Object(以函数对象取代函数)____你有一个大型函数,其中对局部变量的使用使你无法用提炼函数
建立一个新类,根据待处理函数的用途,为这个类命名。
在新类中建立一个构造函数,接受源对象及原函数的所有参数作为参数。
在新类中建立一个Compute函数
将原函数的代码复制到Compute函数中,如果需要调用源对象的任何函数,请通过源对象字段调用
Substitute Algorithm(替换算法)____你想要把某个算法替换为另一个更清晰的算法
MoveMethod(搬移函数)____你的程序中,有个函数与其所驻类之外的另一个类有更多的交流,调用后者,或者被后者调用
检查源类中被源函数所使用的一切特性(包括字段和函数),考虑它们是否也该被搬移。
检查源类的子类和超类,看看是否有该函数的其他声明。
当我需要使用源目标类的特性的时候,有4种选择
将这个特性也移到目标类
建立或使用一个从目标类到源类的引用关系
将源对象当作参数传给目标函数
如果所需特性是个变量,将它当作参数传给目标函数
如果目标函数需要太多源类特性,就得进一步重构。通常这种情况下,我会分解目标函数,并将其中一部分移回源类。
MoveField(搬移字段)____你的程序中,某个字段被其所驻类之外的另一个更多地用到
Extract Class(提炼类)____某个类做了应该由两个类做的事
决定如何分解类所负的责任。
建立一个新类,用以表现从旧类中分离出来的责任。
建立从旧类访问新类的连接关系
Inline Class(将类内联化)_____某个类没有做太多事情
在目标类身上声明源类的public协议,并将其中所有函数委托至源类。
修改所有源类引用点,改而引用目标类。
Hide Delegate(隐藏委托关系)_____客户通过一个委托类来调用另一个对象
0 条评论
下一页