软件演化的类型
软件演化就像生物进化一样,有些突变对物种是有益的,而有些是有害的。
区分软件演化类型的关键,就是程序质量在这一过程中时提高了还是降低了。其二,就是这样的演化是源于程序构建过程中的秀海,还是维护过程中的修改。
重构简介
要实现软件演化基本准则,最关键的策略就是重构。
重构的理由
1、代码重复,重复的代码几乎是代表着最初设计里彻底分解方面的一个事物。无论何时,如果需要对某个地方进行修改,你都不得不在另一个地方完成这样的修改——重复代码总会将你置于一种两线作战的尴尬境地。
2、冗长的子程序,改善方法之一就是提升其模块性。
3、循环过长或嵌套过深
4、内聚性太差的类,如果有某个类中写了很多彼此无关的东西,那么这个类就应该被拆分成多个类,每个类负责一组具有内在的互相关联的任务。
5、类的接口未能提供层次一致的抽象。
6、拥有太多参数的参数列表
7、类的内部修改往往被局限某个部分,变化导致多个类的相同修改,如果发现常常对同一组类进行修改,这表明这些类中的代码应当被重新组织,使修改仅影响到其中的一个类。
8、对继承体系的同样修改,每次为某个类添加派生类时,都会发现自己不得不对另一个类做同样的操作。这就是一种特殊的相同修改,应该避免这种情况。
9、同时使用的相关数据并未以类的方式进行组织,如果常常对同样一组数据进行操作,应当想想是否应该将这些数据及其操作组织到一个类里面。
10、成员函数使用其他类的特征比使用自身类的特征还要多,这就暗示了这一子程序应该被放到另一个类中区,然后再原来的类里调用。
11、过多使用基本数据类型
12、某个类无所事事,有时代码的重构会导致某个已有的类无事可做。如果一个类看起来名不副实,那么就应该考虑是否将该类的功能转交给其他的类,然后彻底删除这个类。
13、一系列传递数据的子程序
14、中间人对象无事可做,如果某个类中的绝大部分代码只是去调用其他类中的成员函数,请考虑是否把这样的中间人去掉,转而直接调用其他类。
15、某个类同其他类过于亲密,如果需要使程序具备更强的可管理性,并最大限度地减少更待代码周围的连带影响,那么(信息隐藏)可能是最强有力的工具了。
16、子程序命名不当,只要看到此问题就应立刻修改。
17、数据成员被设置为公用,请认真考虑吧public数据成员藏在访问器子程序背后。
18、某个派生类仅使用基类的很少一部分成员函数,通常,这种情况表明这一类派生类的创建仅仅是由于基类碰巧有了该类所需要的子程序,而不是出于逻辑上的派生关系。因此应当考虑进行更完善的封装:把派生类相对于基类的关系从"is-a"转变为"has-a"。
19、注释被用于难懂的代码,不要为了拙劣的代码编写文档,应当重写代码。
20、使用了全局变量
21、程序中的一些代码似乎是在将来的某个时候才会用到的,这样的超前设计应该尽量避免,除非想的相当周到(一般不会出现)。对未来需求有所准备的办法并不是去编写空中楼阁式的代码,而是尽可能将满足当前需求的代码清晰直白地表现出来,使未来的程序员能够理解这个程序的意图。
特定的重构
数据级的重构
1、用具名常量代替神秘数值
2、是变量名字跟加清晰传递出更多信息
3、将表达式内连化
4、用函数来代替表达式
5、引入中间变量
6、用多个单一用途变量代替某个多用途变量
7、在局部用途中使用局部变量而不是参数
8、将基础类型数据转化为类
9、将一组类型码转化为类或枚举类型
10、将一组类型码转换为一个基类及其相应的派生类
11、将数组转换为对象
12、把群集封装起来
13、用数据类来代替传统记录
语句级的重构
1、分解布尔表达式
2、将复杂布尔表达式转换成命名准确的布尔函数
3、合并条件语句不通部分的重复代码片段
4、使用break或return而不是循环变量来退出
5、在嵌套的if-else语句中一旦知道答案就立即返回,而不是去赋一个返回值
6、用多态来替代条件语句
7、创建和使用null对象而不是去检测空值
子程序级重构
1、提取子程序或方法
2、将子程序的代码内连化
3、将冗长的子程序转换为类
4、用简单算法替代复杂算法
5、增加参数
6、删除参数
7、将查询操作从修改操作中独立出来
8、合并相似的子程序,通过参数区分它们的功能
9、将行为取决于参数的子程序拆分开来
10、传递整个对象而非特性成员
11、传递特性成员而非整个对象
12、包装向下转型的操作
类实现的重构
1、将值对象转化为引用对象,如果返现创建并维护着多个一模一样的大型复杂对象,请改变对象的使用方式,仅仅保留一份拷贝,然后在其他地方引用它。
2、将引用对象转化为值对象,如果自己某个小型简单对象进行了多次引用操作,请将这些对象都设为值对象。
3、用数据初始化代替虚函数
4、改变成员函数或成员数据的位置,将数据移到基类中,将子函数移动到基函数中
5、将特殊代码提取为派生类
6、将相似的代码结合起来放置到基类中,如果两个派生类有相似的代码,将这些代码结合起来并放到基类中。
类接口的重构
1、将成员函数放到另一个类中
2、将一个类变成两个
3、删除类
4、去除委托关系
5、去掉中间人
6、用委托代替继承
7、用继承代替委托
8、引入外部的成员函数
9、引入扩展类
10、对暴露在外的成员变量进行封装
11、对于不能修改的类成员,删除相关的set()成员函数
12、隐藏那些不会在类之外被用到的成员函数
13、封装不适用的成员函数
14、合并那些实现非常类似的基类和派生类
系统级重构
1、为无法控制的数据创建明确的索引源
2、想单向的类联系改为双向类联系,如果两个类,且他们各自需要用到对方的功能,但仅有一个类能访问另一个类。这时就应该将对两个类进行修改,使其能互相调用。
3、将双向的类联系改为单向联系,如果两个类,彼此都知道对方,但实际上只有一个类需要访问另一个类,此时就需要这种变换。
4、用异常取代错误处理代码或者相反方向变换,这取决与错误处理的策略。
安全的重构
重构是一种改善代码质量的强有力技术,但是使用不当,重构会带来很多麻烦。下面是一些小建议:
1、保存初始代码:防止改错了无法复原
2、重构的步伐应该小一些
3、同一时间只做一项重构
4、把要做的事情一条条列出来
5、设置一个停车场,在某次重构的过程中,可能会发现需要进行另一次重构。正在着手这次新的重构时,获取又发现第三个重构将会给程序带来很多好处。为了处理这些并不重要立即对付的修改工作,最好设置一个“停车常”,把需要在未来某个时间进行而现在可以放在一边的修改工作列出来。
6、多使用还原点,在重构的时候,很容易出现代码没有按照设想正常运行的情况。除了保存初始代码外,在重构中还应该在多个地方设置还原点。这样可以如果改的程序无法运行,可以恢复到之前可以运行的状态。
7、利用编译器警告信息
8、重新测试
9、增加测试用例
10、检查对代码的修改
11、根据重构风险级别来调整重构方法
重构策略
1、在增加子程序时进行重构
2、在添加类的时候进行重构
3、在修补缺陷的时候进行重构
4、关注易于出错的模块
5、关注高度复杂的模块
6、在维护环境下,改善手中正在处理的代码
7、定义清楚干净代码和拙劣代码之间的边界,然后尝试把代码移过这条边界
原文地址:http://blog.csdn.net/zs2538596/article/details/41540945