当前位置: 首页 > news >正文

重构·改善既有代码的设计.02

  1. 前言

之前在《重构·改善既有代码的设计.01》中初步了解了重构的基本前提,基础原则等入门知识。今天我们继续第二更......

  1. 识别代码的坏味道

  1. Duplicated Code

重复代码。最单纯的Duplicated Code就是“同一个类中含有相同的表达式”或“两个互为兄弟的子类内含有相同表达式”。

如果你在一个以上的地点看到相同的程序结构,那么可以肯定:设法将他们合二为一,程序会变得更好。

  1. Long Method

过长函数。当感觉需要用注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名。

如何提炼一段代码,一个很好的技巧是:寻找注释。

  1. Large Class

过大的类。通常如果类内的数个变量有着相同的前缀或字尾,这就意味有机会把它们提炼到某个组件内。

  1. Long Parameter List

过长参数列表。对于OO(面向对象)语言来说,只需传给它足够的、让函数能从中获得自己需要的东西就行了。函数需要的东西多半可以在函数的宿主类中找到。

  1. Divergent Change

发散式变化。某个类经常因为不同的原因在不同的方向上发生变化。指一个类受多种变化影响。

  1. Shotgun Surgery

散弹式修改。如果每遇到某种变化,你都必须在许多不同的类内做出许多修改。顾名思义,霰弹枪发散,修改一个东西,发现修改的代码散布在四处。可以考虑把所有需要修改的代码放进同一个类中。指一个变化引发多个类相应修改。

  1. Feature Envy

依恋情结。其实就是代码职责。函数对某个类的兴趣程序高于对自己所处类的兴趣。如果某个函数为了计算某个值,需要从另一个对象中调用几乎一般的取值函数,那么就该迁移到它该去的地方。

  1. Data Clumps

数据泥团。评判方法是:删除众多数据项中的一项,其他数据项会不会因此失去意义?如果是,那么就是个明显的信号。你需要为他们产生一个新对象。

  1. Primitive Obsession

基本类型偏执。

  1. Switch Statements

switch惊悚现身。switch语句的问题在于重复。一般switch语句可以考虑用多态替换。

  1. Parallel Inheritance Hierarchies

平行继承体系。单你为某个类增加一个子类,必须也为另一个类相应增加一个子类。如果你发现某个继承体系的类名称前缀和另一个继承体系的类名称前缀完全相同,那么便是这种坏味道。

  1. Lazy Class

冗赘类。一个类的所得不值其身价,就让他消失。

  1. Speculative Generality

夸夸其谈未来性。“我想我们总有一天需要做这事”,并因而企图以各式各样的钩子和特殊情况来处理一些非必要的事情。

  1. Temporary Field

令人迷惑的暂时字段。比如某对象某个实例变量仅为某种特定情况而设。我们通常认为对象在所有时候都需要他的所有变量,在变量未被使用的情况下猜测当初其设置的目的,会很抓狂。

  1. Message Chains

过度耦合的消息链。如一个对象请求另一个对象,然后再向后请求另一个对象,然后再向后请求另一个对象......

  1. Refused Bequest

被拒绝的遗赠。继承体系中,子类应该继承超类的函数和数据。但如果子类复用了超累的行为(实现),却又不愿意支持超类的接口。就像他们得到所有礼物,却只从中挑选几样来玩。按传统的说法,这就意味着继承体系设计错误。

  1. Comments

过多的注释。当你感觉需要攥写注释时,请先尝试重构,试着让所有注释都变得多余。试想一种情况:当你看到一段代码,有着很长的注释,然后你发现,这些注释之所以存在是因为代码写的很糟糕。视图用注释来说明函数的用意以及实现。这时候应该使用重构手法把这类坏味道去除,重构之后你会发现注释变得多余,因为代码已经说明了一切。

  1. 构筑测试体系

自测代码的价值:修复错误通常比较快,但找出错误却是噩梦一场。
“花合理实践抓出大多数bug”好过“穷尽一生抓出所有bug”
  1. 重构的第一步:构建可靠的测试环境

  1. 类应该包含他们自己的测试代码

  1. 确保所有测试都完全自动化,让它们检查自己的测试结果

  1. 一套测试就是一个强大的bug侦测器,能够大大缩减查找bug所需要的时间

  1. 攥写测试diamagnetic的最有用时机,是在开始编程之前

  1. 在重构之前先确保代码能够进行自我测试

  1. 频繁的进行测试。每次编译请把测试页考虑进去,每天至少执行每个测试一次

  1. 编写测试代码时, 一开始先让它们失败,测试一下测试代码的机制可以运行

  1. 每当收到一个bug报告,请先写一个单元测试来暴露这个bug

  1. 观察类该做的所有事情,然后针对任何功能的任何一种可能失败情况,进行测试

  1. 测试的要诀:测试你最担心出错的部分

  1. 编写未臻完善的测试并实际运行,好过对完美测试的无尽等待

作者提到,当测试数量达到一定程度之后,继续增加测试带来的效益会呈现递减态势,而非持续递增;如果试图编写太多测试,你也可能因为工作量太大而气馁,最后什么都写不成。你应该把测试集中在可能出错的地方。观察代码,看哪儿变得复杂;观察函数,思考哪些地方可能出错。

不要因为测试无法捕捉所有bug就不写测试,因为测试的确可以捕捉到大多数bug。

  1. 小结

到此,刚看完整本书的5个章节。代码的坏味道和构筑测试体系加深了对于重构的认知。重构和设计模式等诸多思想一样,是需要反复学习,反复实践的。重构的技术就是以微小的步伐修改程序。希望真正吸收这些之后,能够看到一个不一样的代码世界。借此,共勉~

持续学习更新中......

相关文章:

重构·改善既有代码的设计.02

前言之前在《重构改善既有代码的设计.01》中初步了解了重构的基本前提,基础原则等入门知识。今天我们继续第二更......识别代码的坏味道Duplicated Code 重复代码。最单纯的Duplicated Code就是“同一个类中含有相同的表达式”或“两个互为兄弟的子类内含有相同表达…...

脑电信号处理总成

目录一. EEG(脑电图)1.1 脑波1.2 伪迹1.2.1 眼动伪迹1.2.2 肌电伪迹1.2.3 运动伪迹1.2.4 心电伪迹1.2.5 血管波伪迹1.2.6 50Hz和静电干扰1.3 伪迹去除方法1.3.1 避免伪迹产生法1.3.2 直接移除法1.3.3 伪迹消除法一. EEG(脑电图) 1.1 脑波 脑波(英语:br…...

判断推理之图形推理

考点一动态位置变化(一)平移1.特征:图形在平面上的移动,图形本身的大小和形状不发生改变。2.方向:直线(上下、左右、斜对角线),绕圈(顺时针、逆时针)3.距离&a…...

【预告】ORACLE Unifier v22.12 虚拟机发布

引言 离ORACLE Primavera Unifier 最新系统 v22.12已过去了3个多月,应盆友需要,也为方便大家体验,我近日将构建最新的Unifier的虚拟环境,届时将分享给大家,最终可通过VMWare vsphere (esxi) / workstation 或Oracle …...

Sql执行流程与Redo log、 Undo log、 Bin log日志文件

文章目录Sql执行流程与日志文件Sql的执行流程Redo LogBin logUndo logSql执行流程与日志文件 Sql的执行流程 mysql的内部组件结构如下图所示 连接器 与客户端建立连接,检验登录密码,分配相应权限 查询缓存 执行sql语句时会先从这里找一下,…...

如何提高软件测试执行力

高效的测试执行力 不管在哪个行业,高校的执行力都是不可或缺的。在软件测试行业更是这样。有些测试人员,很勤奋也很吃苦,但是可能最终不能很好的完成测试任务。究其原因就是一个测试执行力的问题。 高效执行就是有目标,有计划&…...

Open3D 计算点到平面的距离

目录 一、算法原理二、代码实现三、结果展示一、算法原理 平面外一点 ( x 1 , y 1 , z 1 ) (x_1,y_1,z_1) (x...

DDD领域驱动设计初探

DDD 强调领域模型要兼顾业务和技术两个视角。 我们怎么用一套系统化的方法,抽丝剥茧、一步一步地把需求落实到代码呢?咱们看看下面这张图,它表示了领域驱动设计中的主要流程。 领域驱动设计主要的开发流程你可以看到,在整个开发流…...

C中AES_cbc_encrypt加密对应java中的解密

前言知识: 1.AES(Advanced Encryption Standard)高级加密标准,作为分组密码(把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文)。 2.在AES标准…...

演化算法:乌鸦搜索算法 (Crow Search Algorithm)

前言 如果你对这篇文章感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 在机器学习中,我们所要优化的问题很多时候难以求导,因此通常会采用一些演化算法(又称零…...

基于open62541的OPC UA服务器和客户端开发技术

一、OPC UA的基本概念 1、OPC(OLE for Process Control),是一个工业标准,管理这个标准的国际组织是OPC基金会; 2、OPC通信结构:是指包含一个或多个OPC客户端与服务器相互通信的集合。以下是一个简单的流程图:标准的C/S结构。 3、OPC服务器:TOPC基金会定义了四种;...

测试测开面试要知道的那些事01

列表与元组的区别列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数)。元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变。元组缓存于Python运行时环境,这意味着我们每次使用元组时无…...

物联网毕设 -- 智能厨房监测系统(改)

前言 在家庭生活中,厨房是必不可少的,所以厨房的安全问题关乎着我们大家的生命,所以提出智能厨房监测系统,目的就是为我们减少不必要的安全问题 ⚠️⚠️(本文章仅提供思路和实现方法,并不包含代码&#x…...

macOS 13.3 Beta 3 (22E5236f)发布

系统介绍3 月 8 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.3 开发者预览版 Beta 3 更新(内部版本号:22E5236f),本次更新距离上次发布隔了 7 天。macOS Ventura 带来了台前调度、连续互通相机、FaceTime 通话接力…...

Failed to configure a DataSource: ‘url‘ attribute

一 完整的错误信息 *************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. Reason: Failed to dete…...

Mysql高级——锁

锁 mysql锁的分类 从性能上分为:乐观锁、悲观锁从锁的粒度上分:行锁、间隙锁、页锁、悲观锁从对数据库的操作分类:读锁、写锁 乐观锁需要我们自己通过version字段来实现,如果更新失败则在代码中进行where重试。而我们常见的读锁…...

Spring的Async注解线程池扩展方案

目录- [Spring的Async注解线程池扩展方案]- [目录]- [1. 扩展目的]- [2. 扩展实现]- [2.1 扩展Async注解的执行拦截器AnnotationAsyncExecutionInterceptor]- [2.2 扩展Async注解的Spring代理顾问AsyncAnnotationAdvisor]- [2.3 扩展Async注解的 Spring Bean 后置处理器AsyncAn…...

wfb-ng 锁定WiFi接口

wfb-ng 锁定WiFi接口1. 源由2. 需求3. 分析4. 步骤4.1 确认网卡MAC地址4.2 修改udev配置文件4.3 配置重载&重启4.4 确认逻辑网卡接口4.6 修改wfb-ng逻辑WiFi通信接口5. 参考资料6. 补充资料为了更加方便的调试和使用wfb-ng软件,解决由于设备枚举发现时命名可能存…...

Python所有方向的入门和进阶路线,20年老师傅告诉你方法

干了20多年程序员,对于Python研究一直没停过,这几天把我自己对Python的认知和经验,再结合很多招聘网站上的技术要求,整理出了Python所有方向的学习路线图,基本上各个方向应该学什么,都在上面了,…...

RLOAM/RO-LOAM

LOAM框架 LOAM框架包含三个步骤: Scan registration:从原始激光扫描点数据中提取点特征。点特征是角点或者面点。 odometry estimation:在特征提取之后,特征点传递到里程计模块,通过特征匹配和优化步骤计算相对坐标变…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

HTML 列表、表格、表单

1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项,设置文件夹共享为总是启用,点击添加,可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download(这是我共享的文件夹)&…...

【Redis】Redis从入门到实战:全面指南

Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...

LeetCode 2894.分类求和并作差

目录 题目: 题目描述: 题目链接: 思路: 思路一详解(遍历 判断): 思路二详解(数学规律/公式): 代码: Java思路一(遍历 判断&a…...

n8n:解锁自动化工作流的无限可能

在当今快节奏的数字时代,无论是企业还是个人,都渴望提高工作效率,减少重复性任务的繁琐操作。而 n8n,这个强大的开源自动化工具,就像一位智能的数字助手,悄然走进了许多人的工作和生活,成为提升…...