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

代码的坏味道

神秘命名(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. 【重构】 代码的坏味道总结 Bad Smell (一) (重复代码 | 过长函数 | 过大的类 | 过长参数列 | 发散式变化 | 霰弹式修改)

    膜拜下 Martin Fowler 大神 , 开始学习 圣经 重构-改善既有代码设计 . 代码的坏味道就意味着需要重构, 对代码的坏味道了然于心是重构的比要前提; . 作者 : 万境绝尘 转载请注明出 ...

  2. 代码的坏味道与重构技术

    一.前言 本文大部分内容.图片来自Martin Flower的<Refactoring>一书以及refactoringguru网站(一个很棒的网站),之前在博客发表过,这次属于整理后重新发 ...

  3. 重构笔记——代码的坏味道(上)

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42041757 在重构入门篇中,简单地介绍了重构的定义.为何 ...

  4. 讲点码德!避免这些代码坏味道,努力做一名优秀的程序员

    Martin Fowler:任何一个傻瓜都能写出计算机可以理解的代码.唯有写出人类容易理解的代码,才是优秀的程序员. 大家闭着眼睛想一下什么是好代码?也许你的脑海中漂浮着一堆词:干净.整洁.命名规范. ...

  5. 讲点武德!避免这些代码坏味道,努力做一名优秀的程序员

    Martin Fowler:任何一个傻瓜都能写出计算机可以理解的代码.唯有写出人类容易理解的代码,才是优秀的程序员. 大家闭着眼睛想一下什么是好代码?也许你的脑海中漂浮着一堆词:干净.整洁.命名规范. ...

  6. java 代码坏味道_代码中的坏味道

    前言 在日常生活中,当我们买的水果放久了之后会发出一种难闻的气味("坏味道"),这个时候我们就应该把它扔掉.同样,代码也有"坏味道",当然确定什么是和不是代码& ...

  7. 在项目中寻找代码的坏味道(命名)

    介绍 这段时间一直做项目,所以相对忙碌些,今天终于有时间回过头来好好看一下自己写的代码,看哪里有问题,哪里有"坏味道". 慢慢过,慢慢回忆代码.开始捕捉坏味道. 常做的和常想的事情 ...

  8. 重构-改善既有代码的设计:重构原则(二)

    1.什么是重构 重构(Refactoring):在不改变软件的功能和外部可见性的情况下,为了改善软件的结构,提高清晰性.可扩展性和可重用性而对软件进行的改造,对代码内部的结构进行优化. 2.为何重构 ...

  9. 《重构-改善既有代码设计》读书笔记-重构篇

    2019独角兽企业重金招聘Python工程师标准>>> 重构定义 名词 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本.--<重 ...

最新文章

  1. GNN教程:图注意力网络(GAT)详解!
  2. 关于内存管理-提前释放的问题
  3. Java Byte取值范围
  4. 计算机主机内置的地址码被称为,2016年职称计算机考试WPS_Office单选练习试题1
  5. PHP易混淆函数的区分方法及意义
  6. UnitOfWork知多少
  7. GPS/轨迹追踪、轨迹回放、围栏控制
  8. python怎么测试c代码_如何正确测试python中的C-API,C-API返回错误代码
  9. 别小看无人配送,长大了就是自动驾驶的最终实现。
  10. VOS防止盗打及后门的安全策略
  11. xv6实验课程:Xv6和Unix实用程序
  12. Chrome谷歌浏览器离线安装包下载
  13. 直播特效的实现原理与难点
  14. 两个重要极限 常用等价无穷下小 泰勒展开 麦克劳林公式
  15. 美金融犯罪执法局文件遭泄露:汇丰、摩根大通、渣打等国际大行涉嫌非法转移资金...
  16. VS Code无法更新,问题解决
  17. 【AutoSAR CAN】01 - CAN模块的功能及提供的API
  18. A股-入门-融资融券介绍及操作技巧
  19. 高德地图图形面积计算
  20. Chrome 113 发布,默认启用 WebGPU

热门文章

  1. .NET 指南:包装异常
  2. HTML中利用堆栈方式对Table进行行排序
  3. Linux IO 测试工具 fio命令
  4. 阿尔伯塔大学的计算机科学专业好吗,去阿尔伯塔大学留学这些专业千万不能错过!...
  5. Mysql执行计划的extra列及filesort祥析
  6. Nodejs事件循环
  7. 关于 ls 命令的一个小小的缺陷
  8. [Azure][PowerShell][ASM][12]ACL
  9. SQL Server Pivot 隐藏group
  10. AngularJs angular.equals