代码重构(一)

代码重构

  1. 代码坏味

1.1重复代码(Duplicated Code)

出现的情况:

  1. 相同的代码结构重复出现不同地方时,我们可以将它们合而为一。
  2. 两个互为新工地的子类内包含相同的表达式

具体采用的方法:

  1. 采用Extract Method提炼重复代码
  2. 只需对两个类都是用Extract Method,然后再对被提炼出来的代码使用Pull Up Method将它推入超类内
  3. 如果两个毫不相关的类出现重复代码,可以考虑使用Extract Class将重复代码提炼到一个独立类中,然后在另一个类内使用这个新类。

 

1.2 Long Method(过长函数)

1.采用Extract Method把函数变小

2.如果函数内有大量的参数和临时变量,经常可以运用Replace Temp with Query来消除这些临时元素。Introduce Parameter Object 和 Preserve Whole Object 则可以将过长的参数列表变得更简洁。如果仍然有太多临时变量和参数,那就应该使出杀手锏:Replace Method with Method Object。

 

1.3 Large Class(过大的类)

1.可以使用Extract Class将几个变量一起提炼至新类内,提炼时应该选择类内彼此相关的变量将它们放在一起。如果这个组件适合作为一个子类,也可以使用Extract Subclass。

 

1.4 Long Parameter List(过长参数列)

1.如果向已有的对象发出一条请求就可以取代一个参数,那么你应使用Replace Parameter wiht Method。

 

1.5 Divergent Change(发散式变化)

特点:如果某个类经常因为不同的原因在不同的方向上发生变化,当需要修改代码时,我们希望能够跳到系统的某一点,只在该处做修改。(一个类受多种变化的影响)

1.针对某一外界变化的所有修改,都至应该发生在单一类中,而这个新类内的所有内容都应该反应此变化。可以运用Extract Class将他们提炼到另一个类中。

 

1.6 Shotgun Surgery (散弹式修改)

该方法和Divergent change类似但是相反。如果每遇到某种变化,你都必须在许多不同的类内做出许多小修改,此即为Shotgun Surgery。(一种变化引起多个类响应修改)

重构方法:可以使用Move Method 和 Move Field把所有需要修改的代码放进同一个类内。如果没有何时的类可以放置这些代码,可以新建一个。通常使用Inline Class 把一系列相关行为放进同一个类。

1.7 Feature Envy(依恋清洁)

官方的:函数对某个类的兴趣高过对自己所处类的兴趣。

影响:数据和行为不在一处,修改不可控。

目标:将数据和操作数据的行为包装在一起。

 

1.8 Data Clumps(数据泥团)

数据项(data items)就像小孩子:喜欢成群结队地待在一块儿。你常常可以在很多地方看到相同的三或四笔数据项:两个classes内的相同值域(field)、许多函数签名式(signature)中的相同参数。这些「总是绑在一起出现的数据」真应该放进属于它们自己的对象中。首先请找出这些数据的值域形式(field)出现点,运用Extract Class (提炼类)将它们提炼到一个独立对象中。然后将注意力转移到函数签名式(signature)上头,运用Introduce Parameter Object(引入参数对象) 或Preserve Whole Object(保持对象完整) 为它减肥。这么做的直接好处是可以将很多参数列缩短,简化函数调用动作。是的,不必因为Data Clumps只用上新对象的一部分值域而在意,只要你以新对象取代两个(或更多)值域,你就值回票价了。

 

一个好的评断办法是:删掉众多数据中的一笔。其他数据有没有因而失去意义?如果它们不再有意义,这就是个明确信号:你应该为它们产生一个新对象。

 

缩短值域个数和参数个数,当然可以去除一些坏味道,但更重要的是:一旦拥有新对象,你就有机会让程序散发出一种芳香。得到新对象后,你就可以着手寻找Feature Envy,这可以帮你指出「可移至新class」中的种种程序行为。不必太久, 所有classes都将在它们的小小社会中充分发挥自己的生产力。

 

1.9 Primitive Obsession(基本类型偏执)

定义:Coding的时候总喜欢用基本类型,而不喜欢用对象。

影响:增加扩展和修改的复杂性。

 

1.10 Switch Statements(Switch 惊悚现身)

面向对象程序的一个最明显特征就是:

少用switch(或case)语句.

从本质上说,switch语句的问题在于重复. 你会发现同样的switch语句散布于不同地点.如果要为它添加一个新的case子句,就必须找到所有并修改它们,面向对象的多态概念可为此带来优雅的解决方案.

大多数时候,一看到swith语句,你就应该考虑以多态来替换它. 问题是多态该出现在哪里?Switch语句常常根据类型码进行选择,你要的是

"与该类型码相关的函数或类"

所以应该使用Extract Method将switch语句提炼到一个独立函数中,再以Move Method 将它们搬移到需要多态性的那个类里. 此时你必须决定是否使用Replace Type Code with Subclasses(用子类取代类型码)或者Replace Type Code With State/Strategy(用state或Strategy替代类型码) . 一旦这样完成继承结构之后, 你就可以运用Replace wonditional with
Polymorphism(用多态取代条件表达式)

如果你只是在单一函数中有些选择事例, 且并不想改动它们,那么多态就有点杀鸡用牛刀了. 这种情况下Replace Parameter with Explicit Methods(以明确函数取代参数)是个不错的选择. 如果你的选择条件之一是null, 可以试试Introduce Null Object(引入Null对象).


tips

Replace Type Code with Subclasses(用子类取代类型码)

如果你面对的类型码不会影响宿主类的行为,
可以使用Replace Type Code with Class来处理它们.
 
但如果类型码会影响宿主类的行为,
那么最好的办法就是借助多态来处理变化行为.

1.11 Parallel Inheritance Hierarchies (平行继承体系)

含义:
    每当为一个类增加子类时,必须也为另一个类相应增加子类。
坏处:
    重复的类
目标:
    让其中一个继承体系的实例引用另一个继承体系的实例,减少平行继承的类。
实现方法:
    让其中一个继承体系的实例引用另一个继承体系的实例
使用Move Method (搬移函数) 和**Move Field(搬移字段)**消除引用,最终这些平行继承的类。
 

 

 

 

 

  1. 名词注释
  1. Duplicated Code                 重复代码
  2. Extract Method                   提取方法
  3. Pull Up Method                    方法上移
  4. Template Method                 模板设计模式                    
  5. Extract Class 提取类
  6. Extract Subclass 提取子类
  7. Long Method 过长函数
  8. Inline Temp 内联临时变量
  9. Replace Temp with Query      用查询来替换临时变量本身
  10. Introduce Parameter Object 引入参数对象
  11. Data Clumps 数据泥团
  12. Preserve Whole Object 保持对象完整
  13. Move Method 搬移函数
  14. Replace Method with Method Object    用方法对象代替方法
  15. Decompose Conditional 分解条件表达式
  16. Replace Nested Conditional with Guard Clauses   以卫语句取代嵌套条件表达式
  17. Replace Parameter with Methods 以函数取代参数

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞_哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值