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

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

2013-12-10 17:19 267 查看
JAVA按值传递,给参数赋值不会改变原值,但修改参数对象会改变原对象状态(引用)

值参数不可改

一个方法或类只承担一个职责。

目的清晰,说明明确,让人理解,一些潜规则,比如继承等

1.带来的问题:

某方法很难重用,一个相似功能就需要写一个新的方法,结果就是两个相似的方法存在,之后如果有改动,需要两个同时都改,越来越复杂

2.代码块越小,代码的功能就越容易管理,代码的处理和移动也就越轻松

3.每个函数粒度都很小,那么函数被复用的机会就更大,像注释

一.步骤:

1) 建测试环境

2) 分解并重组函数

a. 找出代码的逻辑泥团并提成一个新的方法:没被修改的作为参数传递,修改了的如果一个可以作为返回值

3)好的变量名是代码清晰的关键,好的代码应该清楚的表现自己的功能

4)绝大多数情况下,函数应该放在它所使用的数据的所属对象内, 修改原先引用

5) 尽量少的临时变量

6) switch 中的参数应该是本类中的属性。

二.原则:

1) 事不过三,三则重构

2) 增加中间层可以解决很多问题:

a.允许逻辑共享

b.分开解释意图和实现

c.隔离变化

d.封装条件逻辑

4.坏代码:

1) 重复代码: 提出成一个方法

a.子类有类似的方法: 提出到超类;如果是相似,则将变化与不变隔离

b. 两个不想关的类出现重复代码:将重复代码提炼成一个重复的类

2) 过长的函数:

a.小函数容易理解的真正关键在于一个好名字

b.每当感觉需要用注释说明时,把需要说明的东西写在一个独立函数中,并以其用途命名

c.循环和其内的代码提炼到一个独立函数中

3) 过大的类: 当利用单个类做太多事情,内部往往会出现太多实例变量

a.不是一直都用所有的实例变量: 提出几个相关的到新类中

b.太多代码: 先确定客户端如何使用它们,然后为某种方式提炼出一个接口

c.过长的参数列表: 将参数变成对象传过去(同时也会造成大对象和被调用对象的依赖关系)

4)针对于某一外界变化所有相应修改,都只应该发生在单一类中:一个变化需要修改多个类,一个类被多个变化影响

5)将数据和对数据的操作行为包装在一起,如果函数对某个类的兴趣大于自己所处的类,那么就移到那个类中。如果被几个类依赖,拆成小方法然后移到最多依赖的类中。 将总是一起变化的东西放在一起

6)当两个类中有相同的字段,许多函数签名中都有相同的参数。把他们提炼到一个独立的对象上: 删掉其中的一项,其余的是否会失去意义

三.重构方式:(132)

1.过长函数:

1) 提炼函数: 困难是处理局部变量

a.用意图去命名:做什么而非怎样做

b.原函数局部变量换成参数

c.只是该代码块内部用的设为局部变量

d.如果改变了原类的值,需要有返回值

2)以查询取代临时变量:临时变量在类的其它部分也需要,且该临时变量只被赋值一次(final)-->换成方法

3)引入解释型变量: 将该复杂表达式(或一部分)的结果放进一个临时变量,以变量名称来解释表达式用途

4)分解临时变量: 某个变量被赋值超过一次,把该变量拆成两个变量。每个临时变量只承担一个责任,用final试验

5) 移除对参数的赋值: 如果传的非对象,那么以一个临时变量取代该参数的位置,返回该临时变量

6) 面对一个大型函数,由于局部变量很多无法提出成小的方法,以函数对象取代函数:将这个函数变成一个对象,所有的临时变量为这个类的属性,这样就不用再传递参数,然后再提

四.在对象之间搬移特性:

1.搬移函数:使用另一个对象的次数比使用自己所驻对象的次数还多

2.提炼类:类的职责过多,提出子类

3.本地扩展,原类需要添加职责,所以建立新类,导入原有类,在新类中加新方法

4.以对象取代数据值: 有一个数据项,需要与其它数据和行为(方法)一起使用才有意义。197

5.以对象取代数组: 有一个数组,但其中的元素各自代表不同的东西:以对象替换数组。对于数组的每个元素,以一个字段来表示(意义更清晰)

6.以字面常量取代魔法数: 有一个字面数值,带有特别的含义:创造一个常量,根据其意义为它命名,并将上述的字面数值替换为这个常量

7.以子类取代类型码: 有不可变的类型码,影响类的行为(一个类中有多个同质的类型):以子类取代这个类型码(整体替代)/用策略模式替代(部分替代) -> 工厂

五.简化条件表达式:

1.分解条件表达式: if - else if -- ... -- else : 从if,else if,else三个段落中分别提炼出独立的函数 逻辑清晰,体现代码意图

2.合并条件表达式: 有一系列测试都得到相同的结果:用与或关于合成一个条件表达式,并将这个条件表达式提炼成一个独立函数(意思是一起的)

3.合并重复的条件片段: 在条件表达式的每个分支上都有着相同的一段代码:将这段重复的代码搬移到条件表达式之外.这样才能清晰的表现出哪些随条件的变化而变化,哪些东西保持不变

4.以卫语句取代嵌套表达式: 如果某个条件极为罕见,就应该提出来单独检查,而非if-else (告诉读者这个很罕见,不平等)

六.简化函数调用:

1. 函数改名: 给函数写上注释,然后把注释变成函数名(304)

2. 令函数携带参数 建立单一函数,以参数表达那些不同值 ---> 消去重复

3.保持对象完整: 从对象里取出若干值,将它们作为某一次函数调用时的参数 --->传递整个对象(因为有可能调用其它的值)

4.减少参数长度: 如果该函数参数由另一个函数获得,让该函数直接调用那个函数

5.引入参数对象:某些参数总是很自然地同时出现---->以一个对象取代这些参数,解决数据泥团

6.当一个函数没有被其它任何类用到,将这个函数设置为private

7.以异常取代错误码: 异常只用来处理意料之外的行为

七.处理概括关系

1.如果两个子类拥有相同的字段:将该字段移至超类

2.函数上移:某些函数在各个子类中产生完全相同的结果--->将该函数移至超类 (避免修改了一个没有修改另一个)

3.构造函数本地上移:子类中的构造函数有共通点--->在父类建造一个新的构造函数,在子类构造函数中调用它

4.塑造模板函数:子类中某些操作执行顺序相同,细节不同-->将这些操作分别放到独立函数中,起相同的函数签名,将原函数上移至超类

5.以委托取代继承:某子类只用超类一部分接口-->子类中添加超类引用属性,将继承改为委托

八.大型重构:384

1.某个继承体系同时承担两种责任:建立两个继承体系,并通过委托关系让一个调用另外一个

2.将过程化设计转化为对象设计:将数据记录变为对象,将大块行为分成小块,并将行为移入相关对象中

3.将领域和表述/显示分离: 将领域逻辑分离出来,为它们建立独立的领域类

4.提炼继承体系:建立继承体系,以一个子类表示一种特殊情况
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: