class="article_content clearfix">
class="htmledit_views">
转自:http://www.cnblogs.com/rickie/archive/2004/10/04/48859.html
本文继续《重构(
Refactoring
)技巧class="tags" href="/tags/DuShu.html" title=读书>读书笔记
之一
》,重构的确是未来软件工程师需要掌握的一项技能。目前一些支持
.Net
的重构工具,如
ReSharper for VS.Net v1.0
、
Borland Together for VS.Net v2.0
和
VS.Net 2005
等,只能支持一些有限的、比较简单的重构策略。大量的重构策略需要软件工程师清晰的了解,人工为主,运用重构工具辅助进行。
(注:本文重构策略的名称及其大部分内容来自《重构-改善既有代码的设计》一书,
Martin Fowler
著,侯捷等译)。
下面的内容延续上一节的内容,其中提及的一些代码坏味道
(
Bad Smell in Codes
)
及其重构策略相对而言要比较麻烦一些。
一、代码坏味道(
Bad Smell in Codes
)及其重构策略
5
.
Divergent Change
(发散式变化)
现象:当某个
Class
因为外部条件的变化或者客户提出新的功能要求等时,每次修改要求我们更新
Class
中不同的方法。不过这种情况只有在事后才能觉察到,因为修改都是在事后发生的么(废话)。
重构策略:将每次因同一条件变化,而需要同时修改的若干方法通过
Extract Class
将它们提炼到一个新
Class
中。实现目标是:每次变化需要修改的方法都在单一的
Class
中,并且这个新的
Class
内所有的方法都应该与这个变化相关。
6
.
Shotgun Surgery
(霰弹式修改)
现象:当外部条件发生变化时,每次需要修改多个
Class
来适应这些变化,影响到很多地方。就像霰弹一样,发散到多个地方。
重构策略:使用
Move Method
和
Move Field
将
Class
中需要修改的方法及成员变量移植到同一个
Class
中。如果没有合适的
Class
,则创建一个新
Class
。实现目标是,将需要修改的地方集中到一个
Class
中进行处理。
比较
Divergent Change
(发散式变化)和
Shotgun Surgery
(霰弹式修改):
前者指一个
Class
受到多种外部变化的影响。而后者指一种变化需要影响到多个
Class
需要修改。都是需要修理的对象。
7
.
Feature Envy
(依恋情结)
现象:
Class
中某些方法“身在曹营心在汉”,没有安心使用
Class
中的成员变量,而需要大量访问另外
Class
中的成员变量。这样就违反了对象技术的基本定义:将数据和操作行为(方法)包装在一起。
重构策略:使用
Move Method
将这些方法移动到对应的
Class
中,以化解其“相思之苦”,让其牵手。
8
.
Data Clumps
(数据泥团)
现象:指一些相同数据项目(
Data Items
),如
Class
成员变量和方法中参数列表等,在多个
Class
中多次出现,并且这些数据项目有其内在的联系。
重构策略:通过使用
Introduce Parameter Object
(创建新的参数对象取代这些参数)或
Preserve Whole Object
(使用已存在的对象取代这些参数),实现使用对象代替
Class
成员变量和方法中参数列表,清除数据泥团,使代码简洁,也提高维护性和易读性。
9
.
Primitive Obsession
(基本型偏执狂)
现象:在
Class
中看到大量的基本型数据项目(
Data Item
),如
Employee
类中有大量的数据成员,
Employee#, FirstName, MiddleName, LastName, Address, State, City, Street, Zip, OfficePhone, CellPhone, Email……
等等。
重构策略:使用
Extract Class
(提炼新类)或
Preserve Whole Object
(使用已存在的对象取代这些参数),实现使用对象代替基本型数据项目(
Data Item
)。如上述
Employee
类中就可分别提炼出
EmployeeName
和
EmployeeContact
两个新类。
10
.
Switch Statements
(
Switch
语句)
现象:同样的
Switch
语句出现在不同的方法或不同的
Class
中,这样当需要增加新的
CASE
分支或者修改
CASE
分支内语句时,就必须找到所有的地方,然后进行修改。这样,就比较麻烦了。
重构策略:
(1)
首先采用
Extract Method
将
Switch
语句提炼到一个独立的函数。
(3)
进一步使用
Replace Type Code with Subclasses
或者
Replace Type Code with State/Strategy
。这步就比较麻烦些,不过记住如下基本规则:这里一般有
3
个
Class
分别为
Source Class
、
Superclass
和
Subclass
。
Source Class
:
l
使用
Self Encapsulate Field
,将
Type Code
成员变量封装起来,也就是建立对应的
Setter/Getter
函数。
Superclass
:
l
在
Superclass
中创建
Static
工厂化方法生产对应的
Subclass
对象,这里会存在一个
Switch
语句(不要再动脑筋来重构这个
Switch
语句了,这个
Switch
语句不会在多处重复存在,并且这里用于决定创建何种
Subclass
对象,这是完全可以接受的)。
Subclass
:
(4)
现在
Superclass
仍然存在
Switch
分支,是时候轮到
Replace Conditional with Polymorphism
上场了。具体而言,就是在每一个
Subclass
中创建重载方法(注:该方法是
Superclass
中含有
Switch
语句的方法),并将
Superclass
中
Switch
语句对应的
Case
分支剪切过来。最后将
Superclass
中该方法初象化
Abstract
,并清除
Switch
语句及其所有的
Case
分支。
这样就完成了整个重构过程,这个比较麻烦。
注:并不是一看到
Switch
语句及
CASE
分支,就马上
/
偏执狂采用上述重构策略进行重构,画蛇添足或吃亏不讨好(个人观点)。一般而言,只有看到多处出现相同的
Switch
语句时,才应该考虑进行重构。