代码重构学习笔记(一)
什么是代码重构,没有一个清楚的定义,它有时甚至不能帮助你更快的完成任务,但代码重构对项目有这重要的意义,通过代码重构,你可以将代码梳理的井井有条,方便阅读和修改,也可以增加代码的稳定性,让你的项目更稳定,更快速的运行。代码重构无需抽出专门的时间来进行,它伴随着功能的增加,代码的编写,你往往在编写代码的时候发现以下情况,这或许意味着——你该重构你的代码了。
代码的坏味道,即什么样的代码应该考虑进行重构。
1.重复代码(Duplicated Code)
如果你在一个以上的地点看到相同的程序结构,这意味着你应该考虑把他们合而为一。
比如:
(1)同一个类的两个函数含有相同的表达式,那么就可以把重复的代码提炼出来,然后在上面的两个地方调用被提炼出来的代码。
(2)互为兄弟的子类含有相同的表达式,要考虑把他们整理到超类中,或者把相同的部分融为一个函数在超类中进行调用。
(3)如果两个毫无关联的类出现相同的代码。考虑建立一个新的类来完成相同的工作,再在上面的两个类中调用第三个类。
2.过长函数(Long Method)
当你感觉函数中某个地方的代码需要通过注释来帮助理解或加以说明,这说明你需要把这部分代码提炼出来成为一个单独的函数,并参考注释来命名这个新的函数。注意函数中如果存在大量的参数和临时变量,可能会对重构造成影响。这时可以多使用查询来取代临时变量。
3.过大的类(Large Class)
当你想利用单个的类来完成太多工作,其内部往往就会出现太多实例变量,一旦这样,重复代码也会接踵而至。这时要懂得把类分解,把具有相关性的几个变量提炼为一个新的类,具有相同前缀和后缀的变量往往可以和为一个类(如果你使用英文规范命名的话)。
如果你无从下手的话,可以先看看客户端如何使用这些变量,然后为每一种使用方式编写一个接口,这可能有助于你看清如何分解这个类。
4.过长参数列(Long Parameter List)
记住对象比参数好用,如果使用对象,你可以直接对对象发出查询请求来获取变量(即get,set方法),即使你多发送几次请求,也优于过长的参数,因为过长的参数不利于理解,而且你一旦需要更多数据,就不得不修改它。
5.发散式变化(Divergent Change)
如果一个类经常会因为不同的原因在不同的方向发生变化,例如在一个类中,如果新加一个数据库,就要修改其中三个函数,如果新加入一个工具,就要修改另外四个函数,那这个时候可能把这个类拆开成两个类是更好的选择,这种问题往往在你做出加入工具等操作时才会看到,但一旦看到,最好作出修改,保证对某个外界变化的所有修改只在一个类中,而一个类的所有内容也都针对这个变化进行改变。
6.霰弹式修改(Shotgun Surgery)
与发散式变化相反,如果某一个外界变化会导致在多个类中做出小修改,那意味着你该把这些内容提炼到一个类中如果没有合适的类,就创造一个,因为如果出现上面的情况,意味着你不但要艰难的找到他们,也很容易忘记某个关键的修改。
7.依恋情结(Feature Envy)
如果某个函数要进行一个计算,需要从另一个对象中获取将近一半的参数,或者要调用将近一半的取值函数(即get,set方法),这意味着,或许你该把这个函数换个位置,移到取了一半的参数的对象中去,有时候一个函数中可能只有某些参数需要大量取值,这时你可以把这部分提炼成一个新的函数,移到该去的对象中。
8.数据泥团(Data Clumps)
数据就像小孩子,喜欢成群结队的呆在一块,如果你常常在很多地方看到相同的几项数据,或者两个类中相同的字段,又或者两个函数中相同的函数,这往往意味着你可以把他们提炼到一个独立对象中,然后再用对象将他们替换,如果你能用一个对像替换来两个即以上的参数,这意味着你值回票价了。