您的位置:首页 > 编程语言

《重构--改善既有代码的设计 》

2005-07-01 16:57 429 查看
重构--改善既有代码的设计(中文版)
(原书名:Refactoring:Improving the Design of Existing Code)
【美】Martin Fowler 著
候 捷  熊 节  译

1 重新组织你的函数(Composing Methods)
1.1 Extract Method(提炼函数)
1.2 Inline Method(将函数内联化)
1.3 Inline Temp(将临时变量内联化)
1.4 Replace Temp with Query(以查询取代临时变量)
1.5 Introduce Explaining Variable(引入解释性变量)
用一个变量来表达一个复杂表达式,该变量名称能明确表示表达式的作用。
1.7 Split Temporary Variable(剖解临时变量)
将一个被赋值多次的临时变量替换为多个变量。
1.9 Remove Assignments to Parameters(移除对参数的赋值动作)
在函数内部声明一个变量来存放参数值,防止直接对参数的值做改动。
1.11 Replace Method with Method Object(以函数对象取代函数)
将某个函数放进一个单独对象中,如此一来局部变量就成了对象内的值域(field)。然后可以在同一个对象中将这个大型函数分解卫数个小型函数。
1.13 Substitute Algorithm(替换你的算法)
将函数本体替换为另一个更清晰的算法。

2 在对象之间搬移特性(Moving Features Between Objects)
2.1 Move Method(搬移函数)
如果某个类中的某个函数,与其它类有更多的交互,则把该函数放到后面的类中;
2.3 Move Field(搬移值域)
某个类中的域被另一个类更多的用到,则把该域搬移到后面的类中;
2.5 Extract Class(提炼类)
如果某个类做了应该有两个classes做的事,则建立一个新的类,将相关值域和函数从旧class搬移到新class;
2.7 Inline Class(将类内联化)
将class的所有特性搬移到另一个class中,然后移除原class;
2.9 Hide Delegate(隐藏[委托关系])
在委托类中简历一个被委托方法的同名函数。如果要调用被委托方法,则直接可以调用委托类中的该同名方法,隐藏了委托关系。
2.11 Remove Middle Man(移除中间人)
让客户直接调用delegate(受托类);
2.13 Introduce Foreign Method(引入外加函数)
server class需要一个额外函数,但是无法修改这个class。此时可以在client class中建立一个函数,并以一个server class实体作为第一引树(vargument),实现该额外函数的功能。
2.15 Introduce Local Extension(引入本地扩展)
server class需要一个额外函数,但是无法修改这个class。此时也可以从该server class派生出一个子类,在子类中添加这些额外函数。

3 重新组织数据(Organization Data)
3.1 Self Encapsulate Field(自封装值域)
只能以getter/setter函数来对类中的值域存取/更改;便于多态的实现
3.3 Replace Data value to Reference(以对象取代数据值)
将该数据值放到一个新类中,使用原数据值的对象改为对该类实例的引用;
3.5 Change value to Reference(将实值对象改为引用对象)
一个类中A包含另一个类B的多个实体时,可以考虑在被引用的类B中创建一个构造器(creator),负责创建其本身的实体。此时,A类只需一个对类B引用,然后通过这个creator来创建多个实体对象;
3.7 Change Reference to value(将引用对象改为实值对象)
3.8 Replace Array with Object(以对象取代数组)
3.9 Duplicate Observed Data(复制[被监视数据])
将负责数据表现形式的类中的数据放到负责数据存储的类中(相当于MVC中的V和M),通过Observer和Observable来实现数据同步;
3.11 Change Unidirectional Association to Bidirectional(将单向关联改为双向)
3.12 Change Bidrectional Association to Unidirectional(将双向改为单向)
3.13 Replace Magic Number with Symbolic Constant(以符号常量/字面常量取代魔法数)
3.14 Encapsulate Field(封装值域)
3.15 Encapsulate Collection(封装群集)
将返回群集的函数返回该群集的一个只读副本;将为群集变量赋值的函数改为add/remove(即setCollection()-addCollectionElement()/ removeCollectionElement() )
3.17 Replace Record with Data Class(以数据类取代记录)
3.18 Replace Type Code with Class(以类取代型别码)
该类中只有一个表示型别码的值域;
3.20 Replace Type Code with Subclass(以子类取代型别码)
3.21 Replace Type Code with State/Strategy(以State/Strategy取代型别码)
以State类来表示型别
3.23 Replace Subclass with Fields(以值域取代子类)

4 简化条件表达式(Simplifying Conditional Expressions)
4.1 Decompose Conditional(分解条件式)
将条件式中的复杂语句提炼出来;
4.3 Consolidate Conditional Expression(合并条件式)
将多个判断语句合并到一个判断语句或判断函数中;
4.5 Consolidate  Duplicate Conditional Fragments(合并重复的条件片断)
在条件式的每个分支上有着相同的一段代码,则将该段代码搬移到条件片断之外(后)
4.7 Remove Control Flag(移除控制标记)
单一入口和多出口原理!用break或return语句来替代控制标记
4.9 Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件式)
当多层嵌套条件式使人难以看清正常的执行路径时,可以用卫语句来替代该实现方案。
位于据:if(条件表达式)返回结果;
4.12 Replace Conditional with Polymorphism(以多态取代条件式)
将条件式的每个分支放进一超类内的覆写函数中,然后将原始函数声明为抽象函数;
4.14 Introduce Null Object(引入Null对象)
将null value 替换卫 null object;
4.16 Introduce Assertion(引入断言)
保证某个条件为真时,后续代码才能执行;相当于代码执行的先决条件;

5 简化函数调用(Making Method Calls Simpler)
5.1 Rename Method(重新命名函数)
5.2 Add Parameter(添加参数)
5.3 Remove Parameter(移除参数)
5.4 Separate Query from Modifier(将查询函数和修改函数分离)
5.5 Parameterize Method(令函数携带参数)
若干函数做了类似的工作,但在函数本体中却包含了不同的值,此时可以建立单一函数,以参数表达那些不同的值,从而完成不同而又类似的工作;
5.7 Replace Parameter with Explicit Methods(以明确函数取代参数)
与“ 令函数携带参数”相反;
5.9 Preserve Whole Object(保持对象完整)
从某个对象中取出若干值,作为某一次函数调用时的参数,则可以把整个对象作为该函数的参数传入;
5.11 Replace Parameter with Method(以函数取代参数)
对象调用某个函数,并将所得结果作为参数,传递给另一个函数;而接受该参数的函数也可以(也有能力)调用前一个函数。此时,则可以让参数接受者去除该项参数,并直接在函数体内调用前一个函数。
5.13 Introduce Parameter Object(引入参数对象)
以一个对象取代多个参数;
5.15 Remove Setting Method(移除设值函数)
某个类中的某个值域,应在对象创建时被设值,然后就不在改变,则可以去掉该值域的所有设值函数(setter);
5.17 Hide Method(隐藏某个函数) 函数声明为private;
5.19 Replace Constructor with Factory Method(以工厂函数取代构造函数)
5.20 Encapsulate Downcast(封装[向下转型]动作)
某个函数返回的对象,需要由函数调用者执行[向下转型]动作,则可以将该转型动作移到函数中;
5.22 Replace Error Code with Exception(以异常取代错误码)
5.23 Replace Exception with Test(以测试取代异常)
面对一个『调用者可预先加以检查』的条件,不应抛出异常。此时可以修改调用者,使它在调用函数之前先做检查,避免该类异常的抛出。

6 处理概括关系(Dealing with Generalization)
6.1 Pull Up Field(值域上移)
将子类共同拥有的值域移到他们的超类中;
6.3 Pull Up Method(函数上移)
将子类拥有的相同功能的函数移到他们的超类中;
6.5 Pull Up Constructor Body(构造函数本体上移)
在各个子类中拥有一些构造函数,它们的本体(代码)几乎完全一致。此时,可以在超类中新建一个构造函数,并在subclass构造函数中通过super()来调用它;
6.7 Push Down Method(函数下移)
超类中的某个函数只有部分的subclass有关,将该函数移动相关的那些subclasses中;
6.9 Push Down Field(值域下移)
超类中的某个函数只有部分的subclass用到,将该函数移动相关的那些subclasses中;
6.11 Extract Subclass(提炼子类)
类中的某些特性只被某些实体用到,则新建一个subclass,将上面所说的那部分特性移到subclass中。
6.13 Extract Superclass(提炼超类)
6.14 Extract Interface(提炼接口)
6.15 Collapse Hierarchy(折叠继承体系)
当超类和子类之间无太大区别时,可以将它们合为一体;
6.17 Form Template Method(塑造模板函数)
有一些子类,其中相应的某些函数以相同顺序执行类似的措施,但各措施实际上有所不同。则将哥哥各个分别放进独立函数中,并保持它们都有相同的签名式(signature),于是原函数也就变得相同了。然后将原函数上移到superclass。
6.19 Replace Inheritance with Delegation(以委托取代继承)
子类只使用超类接口中的一部分,或是根本不需要继承而来的数据。
6.21 Replace Delegation with Inheritance(以继承取代委托)
在两个classes之间使用委托关系,并经常为整个接口编写许多极简单的请托函数,此时可以考虑使用集成来实现这种关系;

共有111个重构方法;
部分参考资料: http://st-www.cs.uiuc.edu/~brant/RefactoringBrowser  未来的软件开发工具 www.junit.org JUnit
发表:2004-8-26 8:05:05
整理于:2005-07-01 16:58
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息