重构-改善既有的代码设计-------代码的坏味道

重构-改善既有的代码设计

代码的坏味道

神秘命名(Mysterious Name)

给函数、变量、模块和类命名时,要使它能清晰地表明自己的功能和用法,使得写下的代码直观明了。
常用重构手法为重命名,包括:

  • 改变函数声明
  • 变量改名
  • 字段改名等

重复代码(Duplicated Code)

若代码中有一处以上的相同的代码结构,例如同一个类的两个函数含有相同的表达式,修改重复代码设法将其合并会使得程序更好
常用的重构方法包括:

  • 提炼函数:适用于同一个类中完全相同的重复代码
  • 移动语句:适用于同一个类中相似的重复代码
  • 函数上移:适用于位于同一超类不同子类的重复代码

过长函数(Long Function)

函数过长会导致函数可读性差,越难被理解。把大函数拆分成小函数,会使得程序有更好的阐释力、更易于分享、更多的选择。

提炼一个小函数的应遵循以下原则:

  • 每当感觉需要以注释来说明什么的时候,就把需要说明的东西写进一个独立的函数里面,并且以其用途(而非实现手法)命名。
  • 条件表达式通常需要提炼函数:分解条件表达式、以多态取代条件表达式等等
  • 循环表达式通常需要提炼函数: 将循环和循环内的代码提炼到一个独立的函数中

常用的重构手法包括:

  • 提炼函数:找到函数中适合集中在一起的部分,将他们提炼出来形成一个新函数。若函数内存在大量的临时变量时,采用此方法会将许多参数传递给提炼函数,导致可读性依旧很差,这是可采用:
    • 以查询取代临时变量方法
    • 引入参数对象方法
    • 保持对象完整方法
  • 若采用以上方法提炼函数后还是有很多临时变量和参数,这时可使用以命令取代函数方式

过长的参数列表(Long Parameter List)

函数的参数列表过长会使得阅读性差,常用的重构方式有:

  • 以查询取代参数:若某个参数可以由另一个参数发起查询获得,则可通过此方式去掉一个参数
  • 保持对象完整:传入完整的数据结构
  • 引入参数对象
  • 移除标记参数
  • 函数组合成类

全局数据(Global Data)

全局数据例如全局变量、类变量、单例等容易被某处代码修改而导致问题出现及难以定位的情况,常用重构方式是封装变量

可变数据(Mutable Data)

代码中对某处数据修改更新,但另一处使用该变量的代码可能期望不一样的值,导致该处功能失效。常用的重构方式包括:

  • 封装变量
  • 拆分变量
  • 移动语句
  • 提炼函数
  • 将查询参数和修改函数分离
  • 移除设值函数
  • 以查询取代派生变量等等

发散式变化(Divergent Change)

某个模块经常因为不同原因在不同方向上发生变化,也就是说,每当新加入了一个功能,希望能跳到系统中某一点,我们只需要在该处修改,而不需要在多处修改。
常用的重构方式包含:

  • 搬移函数
  • 拆分阶段
  • 提炼函数
  • 提炼类等

霰弹式修改(Shotgun Surgery)

类似发散式变化,指的是每次遇到某种变化,都必须在不同的类内做出许多小修改。
常用的重构方法包括:

  • 搬移函数
  • 搬移字段
  • 函数组合成类
  • 函数组合成变换
  • 内联函数或者内联类等

依恋情节(Feature Envy)

模块化指的是将代码分出区域,最大化区域内部的交互、最小化跨区域的交互。若某个函数跟另一个模块中的函数或者数据交流格外频繁,远胜于在自己所处模块内部的交流,这时就出现了典型的依恋情节。
常用的重构方式包括:

  • 搬移函数
  • 提炼函数

数据泥团(Data Clumps)

两个类中相同的字段、许多函数签名中的相同的参数等等之类的很多地方都出现的相同的几项数据称之为数据泥团
常用的重构方式包括:

  • 提炼类
  • 引入参数对象
  • 保持对象完整

基本偏执类型(Primitive Obsession)

不创建对自己问题域有用的基本类型而使用基本数据类型,例如钱、坐标、范围等,继而会出现把钱当做普通数字来计算的情况、计算物理量时无视单位的情况以及大量if判断语句。
常见的重构方式包括:

  • 以对象取代基本类型
  • 以子类取代基本类型
  • 以多态取代条件表达式

重复的switch(Repeated Switches)

每当想增加一个新的选择分支,必须要找到所有的switch,并逐一更新。常用的方式是以多态取代条件表达式

循环语句(Loops)

以更好的方式替代循环语句,例如以管道取代循环等

冗赘的元素(Lazy Element)

程序元素是冗余的,例如某个函数的名字和实现代码看起来一模一样,或者说某个类其实就是一个简单的函数,这个时候该元素就是冗余的。
常见的重构方式包括:

  • 内联函数或者内联类
  • 这得继承体系

夸夸其谈通用性(Speculative Generality)

某个元素并没有太大作用或者说并没有被用上或者说唯一用户是测试用例,则该元素应该被清理
常见的重构方式包括:

  • 内联函数或者内联类
  • 改变函数申明
  • 移除死代码

临时字段(Temporary Field)

类里面的某个字段仅为某种特定的情况而设,使得代码难以理解
常见的重构方法包括:

  • 提炼类
  • 搬移函数
  • 引入特例

过长的消息链(Message Chains)

消息链指的是用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再…。这将导致代码与查找过程的导航结构紧密耦合,一旦对象间的关系发生变化,代码就需要做出相应修改
常见的重构方法包括:

  • 隐藏委托关系
  • 提炼函数
  • 搬移函数

中间人(Middle Man)

封装往往容易导致委托,过度运用委托例如某个类的接口有一半函数都委托给其他类
常见的重构方法包括:

  • 移除中间人
  • 内联函数

内幕交易(Insider Trading)

尽量减少模块间的 数据交换,并把这种交换放到明面上来
常见的重构方法包括:

  • 搬移函数
  • 隐藏委托关系
  • 委托取代子类
  • 委托取代超类

过大的类(Large Class)

某个类做了太多事情,导致其里面出现太多字段,继而导致重复代码
常见的重构方法包括:

  • 提炼函数
  • 以子类取代类型码

异曲同工的类(Alternative Classes With Different Interfaces)

使用类可以方便替换,但只有两个类接口一致时才能做此种替换
常见的重构方法包括:

  • 改变函数申明
  • 搬移函数
  • 提炼超类

纯数据类(Data Class)

纯数据类指的是它拥有一些字段,以及用于访问这些字段的函数,除此之外一无长物
常见的重构方法包括:

  • 封装记录
  • 移除设值函数
  • 搬移函数
  • 提炼函数
  • 拆分阶段

被拒绝的遗赠(Refused Bequest)

若子类复用了超类的实现,却又不愿意支持超类的接口
常见的重构方法包括:

  • 以委托取代子类
  • 委托取代超类

注释(Comments)

当你感觉需要写注释的时候,请先尝试重构,试着让所有注释都变得多余
常见的重构方法包括:

  • 提炼函数
  • 改变函数申明
  • 引入断言
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值