1、前言
代码被阅读和被修改的次数远远多于它被编写的次数。
- 我们不难想象保持代码可读性是多么的重要!而保持代码易读、易修改的关键,就是重构!
- 重构具有风险,它修改运作中的程序,这可能引入一些不易察觉的错误。所以要求重构的方式恰当,遵守重构规则。因此我们应该“一次一小步的重构”。
- 设计模式为重构提供了目标。然后“确定目标”只是问题的一部分而已,改造程序以达到目标,是另一个难题。
所谓重构是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。 本质上说,重构就是在代码写好之后改进它的设计。
如果把重构比作一门功夫的话,它的威力全部来自日积月累的勤学苦练。记住所有的“坏味道”,记住它们对应的重构手法,记住常用的重构步骤,然后你才可能有信心面对各种复杂情况----学会所有的招式,才可能“无招胜有招”。
2、重构,第一个案例
无
3、重构原则
何谓重构?
重构(Refactoring)就是在不改变软件可观察行为的前提下,通过调整程序代码的结构,提高其可理解性,降低其修改成本。
为何重构?
重构能够改进软件设计, 使软件更容易理解,并帮助找到bug,最终提高编程速度。
何时重构?
事不过三,三则重构。即第一次做某件事时只管去做;第二次做类似的事会产生反感,但无论如何还是可以去做;第三次再做类似的事,你就应该重构。
重构时机:即添加功能时、修补错误时、复审代码时。
重构的难题
重构与设计
重构与性能
4、代码的坏味道
Duplicated Code(重复代码)
- 同一个类的两个函数含有相同的表达式
- 两个互为兄弟的子类内含有相同表达式
- 两个毫不相关的类出现相同表达式
这时候你需要做的就是采用Extract Method(110)提炼出重复的代码,然后让这两个地点都调用被提炼出来的那一段代码。
5、重新组织函数
5.1 Extract Method(提炼函数)
Extract Method(110)是最常用的重构手法之一。当看到一个过长的函数或者一段需要注释才能让人理解用途的代码,这时候就可以将这段代码放进一个独立函数中。当然这个函数要简短且命名良好,因为这样做有以下几种好处:首先,如果每个函数的粒度都很小,那么函数被复用的机会就更大;其次,这会使高层函数读起来就像一系列注释;再次,如果函数都是细粒度,那么函数的覆写也会更容易些。
- 创建一个新函数,根据这个函数的意图来对它命名(以它“做什么”来命名,而不是以它“怎么做”命名)。即使想要提炼的代码非常简单,哪怕只是一条消息或一个函数调用,只要新函数的名称能够以更好方式昭示代码意图,也应该提炼它。但如果想不出一个更有意义的名称,就别动。
- 将提炼出的代码从源函数复制到新建的目标函数中。
- 仔细检查提炼出的代码,看看其中是否引用了“作用域限于源函数”的变量(包括局部变量和源函数参数)。
- 检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中将它们声明为临时变量。
- 检查被提炼代码段,看看是否有任何局部变量的值被它改变。如果一个临时变量值被改变了,看看是否可以将被提炼代码段处理为一个查询,并将结果赋值給相关变量。如果很难这样做,或如果被修改的变量不止一个,你就不能仅仅将这段代码原封不动地提炼出来。你可能需要先使用Split Temporary Variable(128),然后再尝试提炼。也可以使用Replace Temp with Query(120)将临时变量消灭掉。
- 将被提炼代码段中需要读取的局部变量,当作参数传给目标函数。
- 处理完所有局部变量之后,进行编译。
- 在源函数中,将被提炼代码段替换为目标函数的调用。