重构---改善其内部结构

    上周读了《重构》这本书,其中的一些思想十分有价值,这里进行一下总结。(文中大多引用书中的观点,特次说明)

一、重构的定义

1.1 何为重构

    书中作者对重构给出了两个定义,分为名词和动词加以区分:

    重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察前提下,提高其可理解性,降低其修改成本。

    重构(动词):使用一系列手法,在不改变软件可观察行为的前提下,调整其结构。

    每个人对名词的理解都不同,对于重构也是如此,简单来说,重构就是对对代码软件内部进行修改,将之前的注释用代码进行表示,但也完全不改变软件的原有功能。一段好的程序应该是这样的:没有任何注释,在阅读时,却能用代码清晰地进行表述。因为注释的维护成本是相当高的,所以不管变量的命名需要多长,个人觉得还是不要简写,使得阅读代码像阅读文章一般轻松。

1.2 为何重构

   1.2.1.改进软件设计:重构就像是在整理代码,所做的就是让所有的东西回到应出的位置上,帮助代码维持该有的形态。改进代码设计的另一个方向就是要消除重复,确定所有的事物和行为在代码中只表述一次,这才是真正优秀设计的根本。

    1.2.2.使软件更容易理解:写代码其实还要考虑到是否方便其他人阅读,如果重构前,一个程序员需要花费1周才能修改某段代码,而如果善于重构,他修改你的代码只需1小时,可见其中节省了多少时间成本。

    1.2.3.帮助找到bug:对代码进行重构,可以深入理解程序的结构,并恰到好处地把新的理解反馈回去。为了重构,所以搞清楚了程序的同时,也轻松地揪出了bug。

    1.2.4.提高编程速度:前面的一切其实都是为了更快速的开发程序。良好的设计是快速开发的根本,因为它可以阻止系统腐败变质,甚至可以提高设计质量。

1.3 何时重构

    在这里要介绍一下三次法则:第一次做某件事情时你尽管去做,第二次做类似的事就会产生反感,但无论如何还是可以去做,第三次再做类似的事情时,你就应该重构。简称为‘事不过三,三则重构’。

    1.3.1.添加功能时重构

    1.3.2.修补错误时重构

    1.3.3.复审代码时重构

    另外,还想说一下何时不该重构。

   有时候,既有的代码实在太混乱,现有的代码根本不能正常运行,那么,可以考虑放弃重构,而是重写。还有一种情况,就是如果项目已接近最后期限,也应该避免重构。不过多个项目经验显示:重构的确能提高生产力。如果最后你没有足够时间,通常就表示你其实早该进行重构。

二、代码的坏味道

    第一次看到“坏味道”这个词时,感觉十分有趣,感觉十分形象,以下主要介绍一下那些属于代码的坏味道。

    2.1.重复代码:如果你在一个以上地点看到相同的程序结构,那么可以肯定,设法将它们合二为一,程序会变得更好。

          最单纯的重复代码就是“同一个类的两个函数有相同的表达式”。这时候就需要提炼出重复的代码,然后让这两个地点都调用被提炼出来的那段代码。

         另一种常见的情况是“两个互为兄弟的子类中含有相同的表达式”。如果代码之间只是类似,并非完全相同,那么可以将相似部分和差异部分割开,构成一个单独的函数。如果有些函数以不同的算法做相同的事,那么可以选择比较清晰地一个,将其他函数的算法替换掉。

        如果是两个毫不相关的类出现了重复代码,那么可以考虑将重复的代码提炼到一个独立类中,然后在另一个类中使用新类。

    2.2 过长函数:拥有短的函数会活的比较好,比较长。程序愈长愈难理解,我们遵循这样一条原则:每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立的函数中,并以其用途(而非实现手法)命名。条件表达式和循环表达式也是提炼的信号,应该将循环和其内部代码提炼到一个独立的函数中。

    2.3 过大的类:如果一个类做了太多的事情,其往往就会出现太多的额实例变量,一旦如此,重复代码也就接踵而至。

          这时可以将几个变量提炼至一个新类中,提炼时应该选择彼此相关的变量,将他们放在一起。如果你的Large Class是个GUI类,你可能需要把数据和行为移到一个独立的领域中去。需要两边各自保留一些重复的数据,并保持两边同步。

    2.4 过长的参数列:太长的参数列难以理解,太长参数会造成前后不一致,不易使用,而且一旦需要更多的数据,就不得不修改它。如果将对象传递给函数,大多数修改都将没有必要,因为你有可能只需(在函数内)增加一两条请求,就能得到更多的数据。

          这里有个重要的例外:有时候你明显不希望造成被“调用对象”与“较大对象”间的某种依赖关系。这时将对象从数据中拆解出来单独作为参数,也是合情合理的。但是请注意其引发的代价。如果参数列太长或者变化太频繁,你就需要重新考虑自己的依赖结构了。

    2.5 发散式变化:如果某个类经常因为不同的原因在不同的方向上发生变化,发散式变化就出现了。针对某一外界变化的所有相应的修改,都只应该发生在单一类中,而这个新类中的所有内容都应该反应此变化。为此,你应该找出某种特定原因而造成的所有变化,然后将他们提炼到另一个类中。

因为本书还没看完,因此总结到此。未完待续。。。

     

    

猜你喜欢

转载自www.cnblogs.com/YYXyeyue/p/9228517.html