前言
文章是对书:<重构 改善既有代码的设计>的整理。
重构的好处
重构之后软件功能和之前一样,不同的是性能优化了,执行速度快了或者代码易于理解等。
1.重构改进软件设计
2.重构使使软件容易理解
3.重构帮助找到bug
4.重构提高编程速度
何时重构
就是下面要写的代码的坏味道,这只是一些经验,具体什么时候要重构,要看一个见识广博者的直觉了。
代码的坏味道
1.重复代码
解决: 重复代码可以提取出一个方法,放到要被调用的类中,或者提炼出一个独立类中。
example:
//判断字符串是否为空
(BOOL)stringIsNull:(NSString *)checkString
{
if ((NSNull *)aCheckString == [NSNull null] ||
aCheckString.length == 0 ||
[aCheckString isEqualToString:@""] ||
[aCheckString isEqualToString:@"<null>"])
return YES;
else
return NO;
}
2.过长的方法
拥有短函数的对象会获得比较好、比较长。“间接层”所能带来的全部利益-解释能力、共享能力、选择能力都是由小型函数支持的。
文中说,我们可以遵循这样一个原则:每当感觉需要注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现方法)命名
(我觉得可以考虑一下,并不绝对)
解决: 分解成若干短函数
3.过大的类
类内如果有太多代码,也是代码重复、混乱并最终走向死亡的源头。
解决:可以试着提炼方法,提炼工具类,把数据和UI分开。
4.过长的参数列
解决:太长的参数列会变得难以理解,可以封装成一个对象。
5.Divergent Change(发散式变化)
标题的意思是:某个类经常因为不同的原因在不同的方向上发生变化。
针对某一外界变化的所有相应修改,都只应该发生在单一类中,而这个类中的所有内容都应该反应此变化。
解决:可以找出某特定原因造成的所有变化,把他们提炼到另一个类中。
6.Shotgun Surgery(霰弹式修改)
标题的意思是:每遇到某种变化,你都必须在许多不同的类中做出许多小修改。
解决: 把所需要修改的代码放到同一个类
发散式变化是指“一个类受多种变化的影响”,霰弹式变化是指“一种变化引发多个类相应修改”。这两种情况下你都会希望整理代码,使外界变化与“需要修改的类”趋于一一对应。
7.依恋情结
如果我们看到某个函数为了计算某个值,从另一个对象那儿调用了几乎半打的取值函数。
解决: 把这个函数移至另一个地点。
如果一个函数用到了好几个类的功能。
解决:我们的原则是:判断哪个类拥有最多被此函数使用的数据,然后就把这个函数和那些数据摆在一起。或者将这个函数分解为数个小函数并分别置于不同地点。
最根本的原则:数据和引用这些数据的行为总是一起变化的,但也有例外。如果例外出现,我们就搬移那些行为,保持变化只在一地发生。
8.Data clumps(数据泥团)
如果两个类中有一些相同的字段,如果删掉其中一项,其他字段不再有意义。你应该为它们创建一个新对象。
9.基本类型偏执
大多数编程华景都有两种数据:结构类型允许你将数据组织成有意义的形式,基本类型则是构成类型的积木块。
意思是:我们不应该偏执的只使用一些基本类型,我们应该试着创建一些小对象— 像是结合数值和币种的money类、由一个起始值和一个结束值组成的range类。
10.Switch Statements(switch惊悚现身)
面向对象的一个最明显的特征就是:少用switch(或case)语句。
从本质上说,switch语句的问题在于重复。
解决 用多态来替换它。如果你只是在单一函数中有些选择事例,且不想改变它们,那多态就有点杀鸡用牛刀了。这种情况可以为参数的每个值,建立一个独立函数。
11.平行继承体系
每当你为某个类增加一个子类,必须也为另一个类相应增加一个子类。
12.冗赘类
每一个类都要去理解它,维护它。如果重构使它身形缩水,不再做那么多工作。或者这个类只是来应付未来的变化,而变化并没有发生。
解决: 将类内联化,或者直接删除掉。
13.夸夸其谈未来性
当有人说“噢,我们总有一天需要做这事” 并企图以各式各样的钩子和特殊情况来处理一些非必要的事情,这种坏味道就出现了。 这会造成代码更难理解和维护。
如:某个抽象类其实并没有太大作用,如果函数的某些参数未用上。
14.另人迷惑的暂时字段。
对象中某个实例变量仅为某种特定情况而设。这样的代码让人不易理解。因为你通常认为对象在所有时候都需要它的所有变量。在变量未被使用的情况下猜测当初其设置目的,会让你发疯的。