重构——代码坏味道&重组函数.md
Posted Alex_MaHao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重构——代码坏味道&重组函数.md相关的知识,希望对你有一定的参考价值。
代码的坏味道
Duplicated Code ( 重复代码 )
如果你在一个以上的地点看到相同的程序结构,那么设法将它们合而唯一,程序会变得更好
最单纯的Duplicated Code 是同一个类的两个函数含有相同的表达式
另一种常见的情况分就是两个互为兄弟的子类内含相同的表达式
。
Long Method ( 过长函数 )
每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途命名(而非实现手法)。
如何确定该提炼哪一段代码呢?一个很好的技巧是:寻找注释。他们通常能指出代码用途和实现手法之间的语义距离。如果代码前方有一行注释,就是再提醒你:可以将这段代码换成一个函数,而且可以再注释的基础上给这个函数命名。就算只有一行代码,如果它需要以注释来说明,那也值得将它提炼到独立函数中。
Large Class ( 过大的类 )
Long Parameter List ( 过长参数列 )
通过以对象的成员变量,避免一个函数中参数过长。
Divergent Change ( 发散式变换 )
针对某一外界变化的所有相应修改,都只应该发生在单一类中,而这个新类内的所有内容都应该反应此变化。(适配器模式)
Shotgun Surgery ( 散弹式修改 )
如果每遇到某种变化,你都必须在许多不同的类内做出许多小修改。
这种情况应该把所有需要修改的代码放到同一个类中。
Divergent Change 是指 一个类受多种变化的影响
,Shotgun Surgery 是指一个变化引发多个类相应的修改
Feature Envy ( 依赖情结 )
函数对某个类的兴趣高过对自己所处类的兴趣。例如某个函数为了计算某个值,从另一个对象那调用几乎半打的取值函数。
判断哪个类拥有最多被彼此函数使用的数据,然后就把这个函数和那些数据摆在一起。
Data Clumps ( 数据泥团 )
两个类中相同的字段,许多函数签名中参数相同
Primitive Obsession ( 基本类型偏执 )
通过一些基本类型的组装,拼装出一种小的数据类型。例如java中的String
,Date
等。
Switch Statements
面向对象程序的一个最明显的特征就是:少用switch
语句。通过多态的概念来解决。
Paraller Inheritance Hierarchies (平行继承体系)
每当你为某个类增加一个子类,必须为另一个类相应增加一个子类。
Lazy Class
如果一个类的所得不值其身价,他就应该小时。
Temporary Field ( 令人迷惑的暂时字段 )
其内某个实例变量仅为某种特定情况而设定。
重构技巧
Extract Method ( 提炼函数 )
动机
当看见一个过长的函数或者一段需要注释才能让人理解用途的代码,我就会将这段代码放进一个独立函数中。
如果每个函数的粒度都很小,那么函数被复用的机会就更大。其次,这会使高层函数读起来就想一系列注释。再次,函数的复写也会更容易些。
Inline Method ( 内联函数 )
一个函数的本体与名称同样清楚一动
在函数的调用点插入函数本体,然后移除该函数。
Inline Temp ( 内联临时变量 )
你有一个临时变量,只被一个简单表达式赋值一次,而它妨碍了其他重构手法。
将所有对该变量的引用动作,替换为对它赋值的那个表达式自身
double basePrice = anOrder.basePrice();
return (basePrice > 10000);
to
return (anOrder.basePrice()) > 1000);
Replace Temp with Query ( 以查询取代临时变量 )
你的程序以一个临时变量保存某一表达式的运算结果
将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为新函数的调用。此后,新函数就可能被其他函数使用
double basePrice = _quantity * _itemPrice;
if (basePrice > 10000)
return basePrice * 0.95;
else
return basePrice 8 0.98;
to
if (basePrice() > 10000)
return basePrice() * 0.95;
else
return basePrice() * 0.98;
double basePrice()
return _quantity * _itemPrice;
动机
临时变量的问题在于:它们是暂时的,而且只能在所属函数内使用。由于临时变量只在所属函数内可见,它们会驱使你写出更长的函数,因为只有这样你才能访问到需要的临时变量。如果把临时变量替换为一个查询,那么同一个类中所有函数都可以获得这份信息。
Introduce Explaining Variable ( 引入解释性变量 )
将复杂表达式的结果放进一个临时变量,以此变量名称来解释表达式用途。
if ((plathform.toUpperCase().indexOf("Mac") > -1))
to
final boolean isMacOs = plathform.toUpperCase().index("Mac") > -1;
Split Temporary Variable ( 分解临时变量 )
你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果。
针对每次赋值,创造一个独立、对应的临时变量
动机
如果临时变量承担多个责任,它就应该被替换为多个临时变量,每个变量只承担一个责任。
Remove Assignments to Parameters ( 移除对参数的赋值 )
函数内对一个方法的参数进行赋值
以一个临时变量取代该参数的赋值
Replace Method with Method Object ( 以函数对象取代函数 )
将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的字段。然后再这个对象中将大型函数分解为多个小型函数
Subsititute Algorithm ( 替换算法 )
换一种函数内逻辑写法。。。。
以上是关于重构——代码坏味道&重组函数.md的主要内容,如果未能解决你的问题,请参考以下文章