现在的位置: 首页 > 编程语言 > 正文

代码重构意义和方法

2018年02月13日 编程语言 ⁄ 共 4075字 ⁄ 字号 评论关闭

摘要:很多人认为重构浪费时间,影响项目进度,其实重构不仅可以让我们的代码更加强壮而且还可以加快我们的项目进度。就和我们盖一个高楼大厦一样,我们的架构和地基越好,我们的楼房会越坚固和牢靠。

一、什么是重构
         重构就是通过调整程序代码,但并不改变程序的功能特征,达到改善软件的质量、性能,使程序的设计模式和架构更趋合理,更容易被理解,提高软件的扩展性和维护性。

二、为什么要代码重构
          需求的不断变更是重构的最根本原因,而且重构是每一个开发人员都要面对的功课。
          代码架构最初的设计也是经过精心的设计,具有良好架构的。但是随着时间的推移、需求的剧增,必须不断的修改原有的功能、追加新的功能,还免不了有一些缺陷需要修改。为了实现变更,不可避免的要违反最初的设计构架。经过一段时间以后,软件的架构就千疮百孔了。bug越来越多,越来越难维护,新的需求越来越难实现,最初的代码构架对新的需求渐渐的失去支持能力,而是成为一种制约。最后新需求的开发成本会超过开发一个新的软件的成本,这就使这个app的生命走到了尽头。

代码重构就能够最大限度的避免这样一种现象。系统发展到一定阶段后,使用重构的方式,不改变系统的外部功能,只对内部的结构进行重新的整理。通过重构,不断的调整系统的结构,使系统对于需求的变更始终具有较强的适应能力。

三、通过代码重构可以达到以下的目标
1、持续偏纠和改进软件设计
2、使代码更被其他人所理解
3、帮助发现隐藏的代码缺陷
4、从长远来看,有助于提高编程效率,增加项目进度(进度是质量的敌人,质量是进度的朋友)
三、何时需要代码重构
1、模糊的不具有任何意义的方法名。

-(void)Ping:(NSString*)str;
重构为:
/**
* 初始化并启动ping
*
* @param strProxyServer 要ping的服务器
*/
-(void)autoPingProxyServer:(NSString*)strProxyServer
{
}

2、臃肿的类 。
3、长方法 。
4、大量的传参。

-(void)studentRegister:(NSString *)school name:(NSString *)name class:(NSString *)class age:(int)age

{

}
重构为:
-(void)studentRegister:(StudentModel *)model
{

}

5、模糊的方法名。

-(void)Ping:(NSString*)str;
改为:
-(void)autoPingProxyServer:(NSString*)strProxyServer;

6. 现有的代码对它要实现的功能显得过于复杂,并且你分析过它。
7. 修改后的代码远比现存的代码逻辑要清晰。
8. 有足够的时间,人手,财力来支持对项目进行回归测试。
9. 现有的代码陈旧无效率。
10. 无人认领的,写的很烂的代码都属于此类。
11. 代码禁区。这部分代码只有一个人可以修改,而且修改可能带来更大的隐患。
四、哪些情况不需要考虑代码重构
1. 逻辑看起来过于复杂,没时间去分析梳理。
2. 不理解为什么前任程序员要这样编写。
3. 负责的是一个很重要的系统,而且时间很紧。
4. 团队的新成员,或者开发者新接触的语言
五、重构的具体方法
1、提取类/抽离方法
正如上面提到的,像“臃肿的类”(xmppmanager.h)这种代码臭味应该将原有类中的方法和属性移动到适当数目的新类中去。旧类中对应新类的方法和属性应该被移除。另外,有时候一些类过于臃肿是因为它包含了被其他类使用本应该是其他类的成员方法的成员方法。这些方法也应该被迁移到合适的类中。

3、分离条件
许多时候,一个方法很长是因为包含好几个分支语句(if-else)。这些分支条件可以被提取和移动到几个单独的方法中。这确实能大大改善代码可读性和可理解性。

If(date.before(monday) || date.after(friday) )
{
total=number*_rate+_fridaycharge;
}
else
{
total=number*_fridayrate;
}
重构为:
if(notFriday(date))
{
total = mondaytotal(number);
}
elser
{
total = fridaytotal (number);
}
-(bool)notFriday(NSDate *)date

return date.before(monday) || date.after(friday);

-(void)mondaytotal(int)number
{
return number*_rate+_fridaycharge;
}
-(void)fridaytotal(int)number
{
return _fridaycharge;
}

4、引入参数对象/保留全局对象
在我做代码审查时发现另外一个很常见的情况 - 好几个参数被传入方法。问题主要与需要从已有方法中增加或者移除一个方法参数有关。在这种场景,建议将相关方法参数组成一个对象(引入参数对象),让方法传递这些对象而不是每个单独的参数。

5、用符号常量替换无意义数字
对于有意义的并且到处被使用的字面常量,应该为它们分配一个命名常量。这能大大增强代码可读性和可理解性。

If(iosSystemversion >7.)
重构为:
#define iosSystemversion7 7 //ios系统为7
If(iosSystemversion > iosSystemversion)

6、重命名方法
正如上面提到的,模糊不清的方法名会影响代码的可使用性。这些模糊不清的名称应该重命名为有意义的可能与业务术语有关的名称,来帮助开发者通过业务上下文更好地理解代码。

-(void)function(nsstring *)str; //截取string
-(void)trimstring(nsstring *)str; //截取string

7、内存优化
检查工程的内存使用情况,及时Release。
8、去除硬编码,将文案统一至模块化的宏定义文件
将一些通过的文案,常用的文案统一便写到宏定义文件

#define ASK_CREATEQUESTION @" " 
重构为:
#define ASK_HOSTURL @"/"

#define ASK_CREATEQUESTION ASK_HOSTURL@"" 
 
六、当重构没有现成的明显的方向时,我们可以遵循下面的原则
1、代码规范

a.图片用英文名:例如:ToolView_Emotion_HL.png
错误: 确定.png, aa@2x.png
b.代码注释规范。 例如: int age;//年龄
c.宏定义规范(涉及到全局的,环境变化的)。
例如:#define PACHAT_ENVIRONMENT 1 //0:int 开发环境 1:stg 测试环境 2:prd 生产环境
d.类名,方法名,变量名命名规范,要有意思,最好用英语。
例如:
#pragma mark -
#pragma mark 查找公众号
e.log信息提交svn时要删除
f.冗余代码要删除(废弃的方法、变量名,注释掉的代码快)
g.新建文件夹要在相应的工程目录文件夹里面新建

2、当属性、方法或类存在任何的需要复用的意向时,归纳提炼它们。
3、不要低估小方法对代码整洁的作用。使用小方法能让你节省很多笔墨。
4、用封装控制可见度。
5、消除依赖。
6、简化构造方法——即使这样做会使代码变复杂。
7、不确定时,将计算操作移入到这些数据的所有者对象里,或将数据移动到执行计算操作的对象里。
8、使用小对象,松耦合,避免大对象,高聚合。

-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{
//TODO:大量的业务逻辑处理
}
重构为:
- (void)dealwithphotoInfo:(NSDictionary *)info
{
//TODO: 具体的业务逻辑处理
….
}

-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{

NSMutableDictionary *dicinfo = [NSMutableDictionary dictionaryWithDictionary:info];

[dicinfo setObject:[NSNumber numberWithInt:picker.sourceType ] forKey:@"camreSourceType"];

[self performSelector:@selector(dealwithphotoInfo:) withObject:dicinfo afterDelay:0.1]; // 延时处理图片压缩和保存

[picker dismissViewControllerAnimated:YES completion:nil];

 
9、使用代理对象,模拟对象和辅助对象来隔离网络,数据库,文件和用户接口。
10、不确定时,尽量在model里添加代码,必要时才往controler添加代码。view里添加的都应该是便捷功能和简写方法,但不要局限于此。
七、如何降低重构的风险
1. 使用自动化的回归测试,快速的验证你的修改。这非常重要,如果没有准备自动化测试,你应该在做任何修改前建好它。
2. 尽量让你的重构处于很短的开发周期,产品更新发布周期也尽可能短。
3. 把你重构的代码和其它程序隔离开,这样能让你更容易找到出问题的地方。
4. 为你的重构活动准备测试计划,包括回归测试,功能测试,反向测试,负载测试,性能测试和用户确认测试。
5. 投入全部精力来研究其中的逻辑,不要分心做其它事情。
6. 在需要的地方使用设计模式。不要为了设计模式而增加设计模式。设计模式应该用在合适的时间和合适地方。

抱歉!评论已关闭.