选择在何处重构(下)
洪流学堂,让你快人几步。
本篇内容来自洪流读书会精选内容。
上一次我们解读了前6种代码需要被重构时的迹象,今天我们将继续解读剩下的16种。
选择在何处重构
霰弹式修改
第七种,霰弹式修改。
霰弹式修改类似于发散式变化,但又恰恰相反。如果每遇到某种变化,你都必须在许多不同的类内做出许多小修改,你所面临的问题就是霰弹式修改。如果需要修改的代码散布四处,你不但很难找到它们,也很容易错过某个重要的修改。
面对霰弹式修改,一个常用的策略就是使用与内联相关的重构,把本不该分散的逻辑拽回一处。完成内联之后,可能会出现长函数或者过大的类,不过你总可以用与提炼相关的重构手法将其拆解成更合理的小块。
依恋情结
第八种,遇到腻腻歪歪的依恋情结。
所谓模块化,就是力求将代码分出区域,最大化区域内部的交互、最小化跨区域的交互。但有时你会发现,一个函数跟另一个模块中的函数或者数据交流格外频繁,远胜于在自己所处模块内部的交流,这就是依恋情结的典型情况。无数次经验里,我们看到某个函数为了计算某个值,从另一个对象那儿调用几乎半打的取值函数。疗法显而易见:这个函数想跟这个数据待在一起,那就使用搬移函数把它移过去。有时候,函数中只有一部分受这种依恋之苦,这时候应该使用提炼函数把这一部分提炼到独立的函数中,再使用搬移函数带它去它的梦想家园。
数据泥团
第九种,遭遇数据泥团。
数据项就像小孩子,喜欢成群结队地待在一块儿。你常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。这些总是会绑在一起出现的数据应该拥有属于它们自己的对象。我们处理的方法是先找出这些数据以字段形式出现的地方,运用提炼类将它们提炼到一个独立对象中。然后将注意力转移到函数签名上,运用引入参数对象和保持对象完整为它瘦身。
我们在这里提倡新建一个类,而不是简单的记录结构,因为一旦拥有新的类,你就有机会让程序散发出一种芳香。得到新的类以后,你就可以着手寻找“依恋情结”,这可以帮你找出能够移至新类中的种种行为。这样使有用的类被创建出来,大量的重复被消除,后续开发得以加速。
重复的switch
第十种,看到重复的switch语句时。
重复的switch的问题在于:每当你想增加一个选择分支时,必须找到所有的switch,并逐一更新。多态给了我们对抗这种问题的武器,使我们得到更优雅的代码库。
循环语句
第十一种,留心看到的循环语句。
遇到难以理解的循环语句,一般我们以管道取代循环的方式帮助我们更快地看清被处理的元素以及处理它们的动作。
冗赘的元素
第十二种,发现代码中冗赘的元素时。
程序元素(如类和函数)能给代码增加结构,从而支持变化、促进复用或者哪怕只是提供更好的名字也好,但有时我们真的不需要这层额外的结构。通常只需使用内联函数和内联类,如果这个类处于一个继承体系中,可以使用折叠继承体系。
夸夸其谈的元素
第十三种,遇到夸夸其谈的元素时。
如果你的某个抽象类其实没有太大作用,请运用折叠继承体系。不必要的委托可运用内联函数和内联类去除掉。如果函数的某些参数未被用上,可以用改变函数声明去掉这些参数。
临时字段
第十四种,临时字段。
有时你会看到这样的类:其内部某个字段仅为某种特定情况而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有字段。请使用提炼类给这个孤儿创造一个家,然后用搬移函数把所有和这些字段相关的代码都放进这个新家。
过长的消息链
第十五种,发现过长的消息链。
如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象……这就是消息链。在实际代码中你看到的可能是一长串的取值函数或一长串临时变量。采取这种方式,意味客户端代码将与查找过程中的导航结构紧密耦合。一旦对象间的关系发生任何变化,客户端就不得不做出相应修改。
这时候应该使用隐藏委托关系。先观察消息链最终得到的对象是用来干什么的,看看能否以提炼函数把使用该对象的代码提炼到一个独立的函数中,再运用搬移函数把这个函数推入消息链。如果还有许多客户端代码需要访问链上的其他对象,同样添加一个函数来完成此事。
中间人
第十六种,碰见不干实事的中间人时。
针对人们可能过度运用委托的情况,可以使用移除中间人,直接和真正负责对象打交道。如果这样“不干实事”的函数只有少数几个,可以运用内联函数把它们放进调用端。
内幕交易
第十七种,看见正在内幕交易的模块或类时。
软件开发者喜欢模块之间建起高墙,极其反感在模块之间大量交换数据,因为这会增加模块间的耦合。在实际情况里,一定的数据交换不可避免,但我们必须尽量减少这种情况,并把这种交换都放到明面上来。
继承常会造成密谋,因为子类对超类的了解总是超过后者的主观愿望。如果你觉得该让这个孩子独立生活了,请运用以委托取代子类或以委托取代超类的方法让它离开继承体系。
过大的类
第十八种,碰到过大的类时。
如果想利用单个类做太多事情,其内往往就会出现太多字段。一旦如此,重复代码也就接踵而至了。观察一个大类的使用者,经常能找到如何拆分类的线索。看看使用者是否只用到了这个类所有功能的一个子集,每个这样的子集都可能拆分成一个独立的类。一旦识别出一个合适的功能子集,就使用提炼类、提炼超类或是以子类取代类型码将其拆分出来。
异曲同工的类
第十九种,发现异曲同工的类时。
使用类的好处之一就在于可以替换,但只有当两个类的接口一致时,才能做这种替换。请反复运用搬移函数将某些行为移入类中,直到两者的协议一致为止。如果搬移过程中造成了重复代码,或许可运用提炼超类补偿一下。
纯数据类
第二十种,遇见纯数据类时。
所谓纯数据类是指:它们拥有一些字段,以及用于访问(读写)这些字段的函数,除此之外一无长物。可以利用封装记录将它们封装起来。对于那些不该被其它类修改的字段,请运用移除设值函数。
被拒绝的遗赠
第二十一种,需要划清界限的情况。
如果子类复用超类的行为(实现),却又不愿意支持超类的接口,应该运用以委托取代子类或者以委托取代超类彻底划清界限。
注释
第二十二种,感到需要注释自己才能被读懂时。
当你感觉需要注释时,请先尝试重构,试着让所有注释都变得多余。
如果你需要注释来解释一块代码做了什么,试试提炼函数;如果函数已经提炼出来,但还是需要注释来解释其行为,试试用改变函数声明为它改名;如果你需要注释说明某些系统的需求规格,试试引入断言。
总结
至此我们将代码需要重构时的22种迹象已经解读完毕了。
让我们回顾一下这22种迹象:它们分别是神秘命名、重复代码、过长函数、全局数据、可变数据、发散式变化、霰弹式修改、依恋情结、数据泥团、重复的switch、循环语句、冗赘的元素、夸夸其谈的元素、临时字段、过长的消息链、中间人、内幕交易、过大的类、异曲同工的类、纯数据类、被拒绝的遗赠、注释。
扩展阅读
- 为什么要重构
- 重构的原则
- 重构的原则(下)
- 选择在何处重构
【扩展学习】在洪流学堂公众号回复
读书会
可以阅读本系列所有文章
我是大智(vx:zhz11235),你的技术探路者,下次见!
别走!点赞,收藏哦!
好,你可以走了。
选择在何处重构(下)相关推荐
- 开发一个出生年份的下拉选择框供用户选择_你的下拉式菜单设计对了吗?
追波范儿(dribbbledesign)------------------------------------------- 下拉菜单主要有两种类型:1. 用于导航的下拉菜单:2. 用于表单的下拉菜 ...
- 人工智能重构下的金融场景
来源:亿欧 概要:从金融领域来看,国际银行业对人工智能的主要应用集中在资本运营.市场分析.客户营销.风险监管等方面.智能客服.智能投顾.智能量化交易--人工智能在金融领域存在巨大的发展空间,但其也使监 ...
- html 左右选择框,jquery实现下拉框左右选择功能
1.说明 本文demo实现下拉框左右选择 2.代码 .centent { width: 260px; } .cententl { float: left; } .btnAdd { float: lef ...
- mysql创建表选择字段的时候下尽量小
创建表选择字段的时候,在符合业务需求的情况下尽量小,数据类型尽量简单 数据类型尽量简单很好理解,比如,使用数字类型要比使用字符类型效率更高,因为不涉及到校对规则和字符集.而字段尽量小,说的是在满足业务 ...
- php时间下滑出现选择,JQuery设置时间段下拉选择实例_jquery
本文实例讲述了JQuery设置时间段下拉选择的方法.分享给大家供大家参考. 具体实现方法如下: $(document).ready(function() { var arrT = []; var tt ...
- vue 下拉框筛选列表_vue下拉菜单选择输入框_带有下拉菜单的Vue搜索输入可提供更多过滤条件...
vue下拉菜单选择输入框 @ tillhub / vue-search-filter (@tillhub/vue-search-filter) Vue search input with dropdo ...
- 是时候重构下自己的博客了
自去年2月份成为一名pythoner以来,我一直在不断的把工作中遇到的问题整理成博客,目前已经有370几篇.但由于写博客时的环境不同,导致博客的内容长短不一,质量也有很多不尽人意的,是时候发生一些改变 ...
- css3选择器如何选择同一个父级下的相同class的第一个元素 nth-child nth-of-type
1 2 3 4 5 选择第一个类名: .demo .item: nth-of-type(1) { - } || .demo .item: nth-child(1) { - }; 选择最后一个类名: . ...
- 游戏引擎选择 Mac下和Windows下UnrealEngine 4体验对比
前几天我说要学做游戏的流程,现在第一篇文章发上来,当然也同时发到我的博客了. PS:tiny允许发这种吗? UnrealEngine 4和Unity3d的选择 订阅了UrealEngine4(UE4) ...
最新文章
- 深度学习要点———神经网络的类型
- 趣谈网络协议笔记-二(第十八讲)
- Docker用Commit给容器做快照
- 使用Spring框架开发会遇到的所有异常及解决方案(持续更)
- mybatis mysql 配置文件详解_Mybatis的配置文件参数详解
- 干货 | 深度剖析C语言的main函数
- python caffe 训练自己的模型_python接口调用已训练好的caffe模型测试分类方法
- ubuntu下用vagrant搭建集群环境
- integration_Integration Services性能最佳实践–写目标
- 开源的“底线”在哪里?
- 深入Java虚拟机-第二章-Java内存区域-学习笔记
- ctrl z推出查看文本怎么结束_最实用的10个电脑常用快捷键!Ctrl+Z的鬼才反向了解一下!...
- 微信公众平台开发之微团购
- 大师林语堂的英文学习要诀
- TV Input Framework --Android官方说明
- 为何程序员都用茶轴_程序员都用抢票神器,而你还在助力抢票吗?
- 西门子 1200PLC全额补贴课程
- Android Studio 添加javah工具
- Ubuntu16.04+VMware15.0.4系统瘦身
- Postgresql12 安装及设置远程访问
热门文章
- 9-Mybatis 多表查询之一对多
- eclipse添加或者绑定约束文件
- linux中的echo%3e文件,Linux学习笔记-shell脚本中${}的使用方法
- centos7桌面没有计算机图标,centos7下创建桌面图标的方法
- python背诵技巧_python如何记忆方法
- 促销海报模板|经典蓝的带着「节日促销」来搞事情了!
- UI设计师用的最多的素材网站都收纳在一个导航
- 电商移动促销页面设计素材PSD分层模板,轻松出稿稿
- html.textboxfor属性,label标签中的for属性与form属性
- c语言作业答案第四章,C语言程序的设计课件源程序及习题的答案第4章.ppt