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

news2024/11/18 11:41:48
  1. 前言

近期在看Martin Fowler著作的《重构.改善既有代码的设计》这本书,这是一本经典著作。书本封面誉为软件开发的不朽经典。书中从一个简单的案例揭示了重构的过程以及最佳实践。同时给出了重构原则,何时重构,以及重构的手法。用来改善既有代码的设计,提升软件的可维护性。

这里会对本书持续进行阶段性总结,希望自己能够从中学习到精髓。

  1. 什么是重构

书中提到,所谓重构(refactoring)是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。

通常一个系统的第一个版本会经过很大很精细的设计,且会遵循先设计后编码的开发流程。但是随着时间的流逝,人们会不断的修改代码。中间随着人员的流动,项目业务性质的变化......,如果按照原先设计所得系统,整体结构会逐渐衰弱,或者说渐渐偏离起初的设计。这样,编码工作就会从一开始的严谨逐渐堕落为胡砍乱劈的随性。

书中提到重构的2层含义:

名词,对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
动词,使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
  1. 两顶帽子

当我们在重构软件时,经常会把时间分配给两种截然不同的行为:

  1. 添加新功能

  1. 重构

添加新功能时,你不应该修改既有的代码,只管添加新功能。编写测试,你可以衡量自己的工作进度。

重构时,你就不能再添加新功能,只管改进程序结构,此时不应该添加任何的测试,只在绝对必要时才修改测试。

但是往往我们在开发过程中,会发现要经常变换帽子。首先你会尝试添加新功能,然后意识到:如果把程序结构改一下,功能添加会容易很多。于是乎,你就换了一定帽子,做一会重构工作。等程序结构调整好后,你又换上原先的帽子继续添加新功能......但无论何时,你都应该清楚知道自己戴的是哪顶帽子。

  1. 为何重构

  1. 重构改进软件设计

当人们只为短期目的,或是在完全理解整体设计之前,就贸然修改代码,程序会逐渐失去自己的结构,程序员越来越难通过阅读源码而理解原来的设计。重构很像是在整理代码,你所做的就是让后所有的东西回到应处的位置上。

代码结构的流失是累积性的,越难看出代码所代表的设计意图,就越难保护其中的设计,于是该设计就腐败的越快。经常性的重构可以帮助代码维持自己该有的形态。

因此改进设计的一个重要方向就是:消除重复代码

  1. 重构使软件更容易理解

一般情况下,我们所编写的代码告诉计算机要做什么事,他的响应则是精确按照你的指示行动。但是除了计算机外,你的源码还有其他读者:几个月后可能会有另一位程序员尝试读懂你的代码并尝试做一些修改。

通常,当你努力的让程序正常运转的时候,很容易忘记第二位读者,但是未来出现的读者(开发者)才是最重要的。计算机多花了几个小时编译,又有什么关系呢?如果一个程序员花一周的时间修改代码,这才要命。有可能理解了你的代码之后,真正的修改只需一个小时。

所以我们应该改变一下开发节奏,对代码适当进行修改,让代码变得更容易理解。这种编程模式的核心就是“准确说出我所要的”。

  1. 重构帮助找到bug

对代码进行重构,可以深入理解代码的作为,并恰到好处的把新的理解反馈回去。搞清楚程序结构的同时,也清楚了自己所作的一些假设,于是想不把bug揪出来都很难。

  1. 重构提高编程速度

良好的设计是快速开发的根本,事实上,拥有良好的设计才可以做到快速开发。

如果没有好的设计,或者在起初阶段,你的进展会很迅速。但是缺乏设计(或恶劣的设计)很快会让你的速度慢下来。你会把时间花在调试上,无法添加新功能。修改时间越来越长,因为你必须花越来越多的时间去理解系统、寻找重复代码。各种打补丁,新特性需要更多的代码才能实现,一直恶性循环下去。

所以前面的一些都归结到这一点:重构帮助你更快速的开发程序

  1. 何时重构

  1. 三次法则

书中提到了Don Roberts提出的准则:

  • 第一次做某件事,只管去做;

  • 第二次做类似的事情会产生反感,但无论如何还是可以去做;

  • 第三次做类似的事,你就应该重构。

事不过三,三则重构
  1. 添加功能时重构

这里,重构的一个原动力是:代码的设计无法帮助我轻松和那个添加所需要的特性。然后对自己说:“如果用某种方式设计,添加特性会简单很多。”这么做的部分原因是为了让未来增加新特性时能够更轻松一些。

  1. 修补错误时重构

调试过程中运用重构,多半是为了让代码更具可读性。如果收到一份错误报告,这就是需要重构的信号,因为显然代码还不够清晰,至少没有清晰到让你能一眼看出bug。

  1. 复审代码时重构

极限编程[XP]中的“结对编程”形式,把代码复审的积极性发挥到了极致。一旦采用这种形式,所有正式开发任务都由2名开发者在同一台机器上进行,这样便在开发过程中形成随时进行的代码复审工作,而重构也被包含在开发过程中了。

  1. 何时不该重构

1、代码根本无法工作,或太糟糕。代码重构还不如重写来的简单;
2、在项目的最后期限,应该避免重构。

小结

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

1、如果发现自己需要为程序添加一个特性,而代码结构使得你无法很方便地达成目的,那么就需要重构那个程序了。使特性的添加比较容易进行,然后再添加特性。
2、代码块越小,代码的功能就越容易管理,代码的处理和移动也就越轻松。
3、代码应该表现自己的目的。任何一个人都能写出计算机可以理解的代码,唯有写出人类容易理解的代码,才是优秀程序员。

后续阶段性阅读该书后,会持续更新中......

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/388922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2.0开发之——购物车案例-Goods组件封装-商品名称和图片(46)

一 概述 循环渲染Goods组件为Goods组件封装title属性为Goods组件封装pic属性 二 循环渲染Goods组件 2.1 App.vue中导入Goods组件 import Goods from /components/Goods/Goods.vue2.2 App.vue中注册Goods组件 components: {Header,Goods}2.3 循环渲染每一个商品的信息 <…

记录--在Vue3这样子写页面更快更高效

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 在开发管理后台过程中&#xff0c;一定会遇到不少了增删改查页面&#xff0c;而这些页面的逻辑大多都是相同的&#xff0c;如获取列表数据&#xff0c;分页&#xff0c;筛选功能这些基本功能。而…

windows下neo4j安装及配置,并绘制人物关系图谱

neo4j安装及配置&#xff0c;绘制人物关系图谱 先升级pip&#xff0c;安装py2neo pip install py2neo2021.0.1依赖 jdk1.8&#xff0c; neo4j 3.xx&#xff1b; 或者jdk18&#xff0c;neo4j 4.x&#xff0c;5.x&#xff1b; 官网下载了neo4j4.x,5.x 因为jdk版本原因都不行&am…

段错误排查方法与防御性措施~

什么是段错误 首先我们需要知道什么是段错误&#xff0c;才能对症下药。 段错误是一种在程序运行时发生的错误&#xff0c;通常是由于程序试图访问不在其地址空间范围内的内存引起的。 例如&#xff0c;当一个程序访问空指针或者已经被释放的内存时&#xff0c;就有可能触发…

Mybatis框架的搭建与使用

Mybatis框架的搭建 一.创建新模块 二、在pom.xml导入依赖 <dependencies><!-- Mybatis核心 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependenc…

软件研发管理经验总结 - 技术管理

软件研发管理经验总结 - 技术管理 技术管理主要负责有技术团队建设、管理团队成员技术相关事务、帮助团队成员成长、负责团队成员交付的代码质量、以及负责产品技术方向、以及产品相关前沿技术调研&#xff1b;管理团队成员技术相关事务有代码Review、故障率跟踪、分析及根据分…

算法系列之数值积分的目的

PLC算法里的数字积分器详细介绍请参看下面的文章链接: PLC算法系列之数值积分器(Integrator)_RXXW_Dor的博客-CSDN博客数值积分和微分在工程上的重要意义不用多说,闭环控制的PID控制器就是积分和微分信号的应用。流量累加也会用到。有关积分运算在流量累加上的应用,请参看下…

LeetCode 349. 两个数组的交集和 692. 前K个高频单词

两个数组的交集 难度 简单 题目链接 这道题的难度不大&#xff0c;我们可以把数组里的数据存到set里面。这样就完成了排序和去重&#xff0c;然后我们再把一个set里面的数据和另外一个set数据进行比较。如果相同就插入到数组里。 代码如下&#xff1a; 但是这个算法的时间复…

自学大数据第四天~hadoop集群的搭建

Hadoop集群安装配置 当hadoop采用分布式模式部署和运行时,存储采用分布式文件系统HDFS,此时HDFS名称节点和数据节点位于不同的机器上; 数据就可以分布到多个节点,不同的数据节点上的数据计算可以并行执行了,这时候MR才能发挥其本该有的作用; 没那么多机器怎么办~~~~多几个虚拟…

网络安全之资产及攻击面管理

“摸清家底&#xff0c;认清风险”做好资产管理是安全运营的第一步。那么什么是资产&#xff0c;资产管理的难点痛点是什么&#xff0c;如何做好资产管理&#xff0c;认清风险。带着这些问题我们来认识一下资产及攻击面管理。 一、资产的定义 《GBT 20984-2007信息安全技术信…

论文阅读_善用Midjourney

论文信息 name_en: Grimm in Wonderland: Prompt Engineering with Midjourney to Illustrate Fairytales name_ch: 用Midjourney生成格林童话插图 paper_addr: http://arxiv.org/abs/2302.08961 date_publish: 2023-02-17 author: Martin Ruskov,米兰大学 读后感 针对生成图…

力扣-计算特殊奖金

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;1873. 计算特殊奖金二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他总…

【C++】stl_list介绍和实现,list和vector区别,list vector string 迭代器失效

本篇博客详细介绍list的实现&细节讲解&#xff0c;并且在文章末对list和vector&#xff0c;string进行区分和复习 list的基本结构就是双向带头循环链表&#xff0c;链表和顺序表的差别我们在前面数据结构的时候早就学过了&#xff0c;不再赘述 在使用stl库里面list时&…

3.1 第一个外设GPIO GPIO输出

GPIO简介•GPIO是通用输入输出口&#xff08;俗称IO口&#xff09;•可配置为8种输入输出模式•引脚电平&#xff1a;0V~3.3V&#xff08;数据0是0V&#xff0c;数据1是3.3V&#xff09;&#xff0c;部分引脚可容忍5V.•输出模式可控制端口输出高低电平&#xff0c;用以驱动LED…

Javascript周学习小结(初识,变量,数据类型)

JS的三大书写方式行内式如图所示&#xff1a;几点说明&#xff1a;JS的行内式写在HTML的标签内部&#xff0c;(常以on开头)&#xff0c;如onclick行内式常常使用单引号括住字符串以区分HTML的双引号可读性差&#xff0c;不建议使用引号易出错&#xff0c;不建议使用特殊情况下使…

【冲刺蓝桥杯的最后30天】day2

大家好&#x1f603;&#xff0c;我是想要慢慢变得优秀的向阳&#x1f31e;同学&#x1f468;‍&#x1f4bb;&#xff0c;断更了整整一年&#xff0c;又开始恢复CSDN更新&#xff0c;从今天开始更新备战蓝桥30天系列&#xff0c;一共30天&#xff0c;如果对你有帮助或者正在备…

Java代码是如何被CPU狂飙起来的?

&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3;&#x1f4e3; &#x1f38d;大家好&#xff0c;我是慕枫 &#x1f38d;前阿里巴巴高级工程师&#xff0c;InfoQ签约作者、阿里云专家博主&#xff0c;一直致力于用大白话讲解技术知识 &#x…

Stable Diffusion WebUI安装instruct-pix2pix插件

instruct-pix2pix作者团队提出了一种通过人类自然语言指令编辑图像的方法。他们的模型能够接受一张图像和相应的文字指令(也就是prompt)&#xff0c;根据指令来编辑图像。作者团队使用两个预训练模型&#xff08;一个是语言模型GPT-3, 另一个是文本到图像模型Stable Diffusion)…

Python---正则表达式

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;Python在学&#xff0c;希望能够得到各位的支持&#xff01;&#xff01;&#xff01; 正则表达式前言概念作用和特点使用场景正则符号re模块re.compile()match()search()span()findall()group()sub()…

uniapp系列-报错或常见问题处理集锦

问题一&#xff1a;执行完命令&#xff0c;就不动了&#xff0c;或者是uniapp 遇到编译很慢&#xff0c;无法正常运行的情况 情况1&#xff1a;执行run dev命令后&#xff0c;一直就不动了&#xff0c;输出如下 PS C:\XXXXXXXX> npx yarn run dev:h5 yarn run v1.22.19 wa…