重构(Refactoring)技巧
本文简要整理重构方法的读书笔记及个人在做
Code Review
过程中,对程序代码常用的一些重构策略。通过适当的重构代码,的确可以显著提高代码的质量,令人赏心悦目。毫无疑问,这些重构策略均来自于
Martin Fowler
的
《重构-改善既有代码的设计》,只是如何在实际项目中灵活运用而已。(注:本文重构策略的名称及其大部分内容来自《重构-改善既有代码的设计》一书,
Martin Fowler
著,侯捷等译)。
先看看重构的定义吧:
(
1
)
Refactoring means rewriting existing source code with the intent of improving its design rather than changing its external behavior. The focus of refactoring is on the structure of the source code, changing the design to make the code easier to understand, maintain, and modify.
-
来自
Borland Together
提供的文档,觉得这个定义很清晰明了。
(
2
)重构是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,已改进程序的内部结构。-来自
Martin Fowler
的定义。
不过,我一般使用一些重构的工具,如
ReSharper for VS.Net v1.0
和
Borland Together for VS.Net v2.0
,这些重构工具可以帮助你做很多事情,可以简化你许多工作,同时也可以避免出现一些错误。关于
ReSharper for VS.Net v1.0
的简单介绍,可以参考Rickie 以前的一篇
Posting【
体验ReSharper V1.0 for VS.Net 2003 - Part IVS.Net 2005已经内置了重构功能。不过,目前这些重构工具还远远不能涵盖各种重构方法,有总比没有好了。
,
体验ReSharper V1.0 for VS.Net 2003 - Part II】。另外
因此,掌握必要的重构技巧逐步成为对程序员基本的要求,重要的是在掌握这些技巧后,也有助于类库初期设计的质量,避免或减少代码的坏味道
(bad smell)
。
一、代码坏味道(Bad Smell in Codes)及其重构策略
1.尽量消除重复的代码,将它们合而为一
根据重复的代码出现在不同的地方,分别采取不同的重构的策略:
在同一个
Class
的不同地方:通过采用重构工具提供的
Extract Method
功能提炼出重复的代码,
然后在这些地方调用上述提炼出方法。
在不同
Subclasses
中:通过
Extract Method
提炼出重复的代码,然后通过
Pull Up Method
将该方法移动到上级的
Super class
内。
在没有关系的
Classes
中:通过对其中一个使用
Extract Class
将重复的代码提炼到一个新类中,然后在另一个
Class
中调用生成的新类,消除重复的代码。
2.拆解过长的函数
过长的函数在我们的日常代码中经常可见,在
C#
中常通过
#region #endregion
区隔为不同的功能区域。
重构策略:通过
Extract Method
将过长的函数按照功能的不同进行适当拆解为小的函数,并且给这些小函数一个好名字。通过名字来了解函数提供的功能,提高代码的理解性。
3.拆解过大的类
过大的类也经常见到,特别是类中含有大量的成员变量。
重构策略:通过
Extract Class
将一些相关成员变量移植到新的
Class
中,如
Employee
类,一般会包含有联系方式的相关属性(电话,
Mobile
,地址,
Zip
等等),则可以将这些移植到新的
EmployeeContact
类中。
4.过长的参数列
过长的参数列的主要问题是难以理解,并且难以维护。如果要增加新的参数或者删除某一参数,易造成参数前后不一致。
重构策略:如果可以通过向已存在的对象查询获取参数,则可通过
Replace Parameter with Method
,移除参数列,通过在函数内部向上述已存在的对象查询来获取参数。
如果参数列中若干参数是已存在对象的属性,则可通过
Preserve Whole Object
将这些参赛替换为一个完整对象,这样不仅提高代码的可读性,同时已易于代码今后的维护。
另外,还可以将若干不相关的参数,使用
Introduce Parameter Object
来创建一个新的参数类。不过,我个人觉得如果这些情况过多的话,会产生很多莫名其妙的参数类了,反而降低代码的可读性。
个人觉得前面
4
种坏味道比较显而易见,也比较容易处理。
现象:当某个
Class
因为外部条件的变化或者客户提出新的功能要求等时,每次修改要求我们更新
Class
中不同的方法。不过这种情况只有在事后才能觉察到,因为修改都是在事后发生的么(废话)。
重构策略:将每次因同一条件变化,而需要同时修改的若干方法通过
Extract Class
将它们提炼到一个新
Class
中。实现目标是:每次变化需要修改的方法都在单一的
Class
中,并且这个新的
Class
内所有的方法都应该与这个变化相关。
6
.
Shotgun Surgery