重构之重构

Martin Fowler的重构一书很早就爬到了我的书架上,但一直没有把它完整地读完。一是没有时间;二是每次拿起来看时,看到那些碎碎念念的东西就立即失去了耐心。终于有一天,当我有了时间,有了心情去看这本书时,我几乎只用了一个晚上就一口气读完了这本书。但老实说,这并不是因为书里的内容吸引了我,而是我十分担心这一次又是半途而废。读完之后,我第一个感受,就是明白了候捷先生为什么没有自己亲自去翻译这本书,而先要熊节出第一稿了。我挺佩服熊节的,这么絮絮叨叨的内容,他竟能完整的翻译下来。就像候捷在序里提到的那几个初印象,“重构目标过于平淡,重构步骤过于琐屑”,我完全不能理解这本书为什么会被人称为经典之作,但却能理解熊节所说的,翻译完成后没有再看过第二遍这本书。而且我非常不喜欢这本书里的一些词语,台式的术语叫法让我很不舒服。不管“Type”叫类型,叫型别;不管“Collection”叫集合,叫群集,看起来真是难受。

虽然这些年我重构了不少的代码,但每次重构前,我都有些没信心。那毕竟是目前来看运行还算正常的程序,我清清楚楚地知道我必须得重构它,但我却很不想下手。而每次重构完成后,,也让我更深刻地体会到了XP价值观中的Courage了。没有一点勇气,还真是不愿意对原来的代码下手。我知道根源在于代码是否有单元测试,没有单元测试就不敢保证修改之后它还能正常运行。单元测试极其重要,可是它与重构手法却关系不大,----无论用什么样的重构手法都必须得用单元测试,但有了单元测试,却不一定要用Fowler的那些重构方法。

Martin Fowler列举了多达72种重构手法,这些重构手法中有相当一部分内容可以直接通过IDE来实现,比如Extract Method在Eclipse中就很容易完成。还有相当一部分其实没有什么必要单独列举出来,尤其是在使用IDE的情况下,类似Add Parameter和Remove Parameter这种重构手法被罗列进重构目录,实现是有点小题大做。以Eclipse为例,给一个方法添加或删除参数,需要修改哪些地方,一目了然,根本没必要以Martin的方法,那么小心翼翼。但考虑到Martin写作的时间是1999年,还没有这么优秀的编程条件,这种小心翼翼便不难理解了。

有人将《重构》与《设计模式》并列为经典,我极不认可。《重构》写于1999年,以现在的目光来看,很多重构手法未免小题大做;而与之相比,《设计模式》写于1995年,快20年的时间了,几乎所有模式还依然闪闪发光。《重构》虽然列举了72种重构方法,但核心思想其实就一个,即小步重构。例如,以Rename Method为例,Martin的做法是先以新名称声明一个新方法,然后再在老方法中调用新方法,这样调用端就不会受到影响,继而再去修改所有调用者。其它重构手法也类似,但以现在的情况来看,这种方式实在没有必要,而且这样做了反而不好。因为在IDE的情况下,如果我们以这种方法重构,哪些地方调用了这个方法,就很难找出来了。相反,如果我们直接改方法名称,那么IDE会以红色标注出来哪些地方受到了影响。另外,如果Rename Method要列为重构手法,那Rename Interface,Rename Package为什么不列为重构手法呢?所以说,Martin洋洋洒洒的列举了72种重构手法,不能不让人怀疑他的初衷。不仅如此,像Rename Method这样的重构手法,使用Eclipse已经能够自动完成了,总的来说现在有17种重构手法已经可以自动实现,列举如下:
Extract Method(提炼函数)
Extract Class(提炼类)
Extract Interface(提炼接口)
Extract Superclass(提炼超类)
Inline Class (将类内联化
Inline Method(将函数内联化)
Inline Temp(将临时变量内联化)
Pull Up Constructor Body(构造函数本体上移)
Pull Up Field(值域上拉)
Pull Up Method(函数上拉)
Pull Down Field(值域下降)
Pull Down Method(函数下移)
Encapsulate Field(封装值域)
Move Field (搬移值域)
Move Method(搬移函数)
Replace Constructor With Factory Method(以工厂方法取代构造函数)
Rename Method(重新命名函数)

不过,Martin的许多重构原则还是很值得借鉴的。比如:
1、尽可能地去除临时变量或局部变量,因为变量会妨碍方法的提取,并且使代码不清晰。有些重构手法在使用时会影响性能,但一旦清晰了结构后,性能问题会得到很好的解决。
2、尽可能地去除注释,代码自身应该能够说明他自己,如果不能说明,就应该重构。不是说不能加注释,而是说注释是一种代码不清晰的信号。
3、尽可能地去除分支结构,分支结构响应变化的能力低下
4、巧妙运用final关键字。
5、频繁测试,小步前行。

猜你喜欢

转载自weatry.iteye.com/blog/2158271