要想后期修改少,代码重构要趁早

news2025/1/15 12:57:25
摘要:在敏捷中,让设计简单化,必须让设计从简单开始,然后变得成熟。要做到这一点,重构是唯一的出路。

本文分享自华为云社区《敏捷技术实践之重构》,作者:华为云PaaS服务小智 。

前言

极限编程(XP)的创始人之一Ron Jeffries说道:“在敏捷中,让设计简单化,必须让设计从简单开始,然后变得成熟。要做到这一点,重构是唯一的出路。”

什么是重构

重构是指改变代码的结构,而不是代码的行为。举个例子:假设一个程序中有两个方法,每个方法都包含几行相同的代码,那么这几行相同的代码可以从原来的两个方法中抽取出来,放到一个新的方法中,在原来放置这几行代码的地方替换为调用这个新的方法。这个重构稍微改善了程序的可读性和可维护性,因为现在一些代码明显被复用,并且重复的代码被移到了一个地方。代码结构发生了改变,但是行为并没有变。

重构不仅对TDD(测试驱动开发)的成功至关重要,同时也有助于防止代码腐烂。代码腐烂是由重复的代码、无数的补丁、糟糕的分类和其他编程差异造成的。团队的开发人员以他们自己的风格编写代码也会导致代码腐烂。产品发布后,代码腐烂是典型的综合症,如果允许代码腐烂,过不了几年,系统就要全部重写。通过不断的重构,并且在一些小问题变成大问题之前不断地修复它们,我们能够保持我们的应用程序不会腐烂。Robert C.Martin称之为童子军规则。

童子军里有一个规定:“离开的时候,总要让露营地比你来的时候更干净。”应用于软件开发中就是:提交一个模块代码的时候,要让它比下载的时候更简洁一些,不论谁是这段代码的原作者。如果我们都遵循这个简单的规定我们的系统最终会变得越来越好,是整个团队照料整个系统,而非个人各自只关心他们那一小部分,这样就符合代码集体所有制原则,同时还可以培养团队成员的主人翁精神和责任感。

何时重构

Kent Beck提出了“代码坏味道”的说法,这种坏味道,就是发出了重构的强烈信息,在《重构》一书中提到了24类,在这里我们重点讨论以下几类:

1.神秘命名

猜谜这件事如果发生在阅读代码的时候,就不是一个好的体验。代码整洁最重要的一项就是好的命名,尽量做到见名知意。每个团队都有自己统一的命名规范,常见命名方法有驼峰命名法如userName,蛇形命名法如user_name,脊柱命名法如user-name等,不论哪一种,就是不要出现theList,var1这种写法。

在代码编写过程中,我们应该深思熟虑如何给函数、模块、变量和类命名,使他们能够清晰地表明自己的功能和用法。改名是最常用的重构手段,包括修改函数声明、变量改名、字段改名等,好的名字能够节省未来在猜谜上的大把时间。如果想不出一个好的名字,说明背后很可能潜在更深的设计问题,为一个名字所付出的纠结,常常能推动我们对代码进行精简。

2.重复代码

重复代码,顾名思义就是两段代码看上去几乎相同或者两段代码都是实现相同的功能。当程序中存在大量重复的代码,会造成代码长度过长,不易阅读,遇到相同或相似的代码段需要仔细分辨,如果需要修改某一处的时候,为了避免遗漏需要查找出所有的相同代码段进行修改,不易维护。

如果是同一个类的两个函数含有相同的代码,如文章开头的例子,这时候可以用提炼函数来提炼出重复的代码,然后让这两个地点都调用被提炼出的那段代码。如果重复代码只是相似而不是相同,可以先尝试用移动语句重组代码顺序,把相似的部分放在一起以便于提炼。

3.过长参数列表

函数通常都需要接收参数,然后去完成某些处理,在《代码整洁之道》中提出,一个函数的参数应该尽可能短,最好只有一个,其次是两个,如果出现三个以上的参数,就需要注意了。函数的参数过多不易于维护和修改,可读性也差,容易出错。

如果一些参数来自同一个对象,那么就不要单独取出这些数作为函数参数传递,而是直接将这个对象传递过去。如果某些参数值可以通过调用已知的一个方法得到,那么就要把这个参数退换为在方法体内调用取值的那个已知方法。还有参数不来自同一个对象,如果有必要,我们也要毫不犹豫的为这些参数新建一个不可变的类,强制将它们放在一起

4.过长函数

在编程早期,由于调用子函数需要产生额外的开销,所以大家都不喜欢小函数,一个函数动辄几百多行,鼠标的滚动条要滚好一会才能到方法末尾,更不用说一行一行的去阅读,去理解,可以想象别人来修改这段代码的时候他有多么痛苦。现代的开发环境已经完全免除了进程内的函数调用开销。所以要保证自己的函数短小精悍。通常一个函数长度的底线是要在一个屏幕内完全显示。

当然有时候一个函数开始的时候并不是那么长,只是随着每次需求的变更,每次一点点的加代码而没有注意重构,侥幸的认为一点点根本不算什么,积少成多最后终于不可收拾了。

过长函数应该积极的进行函数分解,提炼函数,找到函数中适合集中在一起的部分,把他们提炼出来形成一个新的函数。哪怕有时候是对一行代码进行这样的提取也是值得的行动,因为关键不在于函数的长度,而是在于函数做了什么。

5.全局数据

在开始学习编程的时候,老师应该讲过避免使用全局变量,因为它太不可控了,在代码的任何一个角落都可以修改它,而且没有任何机制能够探测出来到底哪段代码做出了修改。全局变量一次次造成的那种诡异bug,足够让你刻骨铭心。

对于全局数据要避免使用,函数内的就放在函数体内,代码段内的就放在代码段中。无处可放,需要单独存在的全局数据就将其封装在函数中,这样就可以找到在哪个地方进行了修改,还要将这个函数放在某个类中,限定那些方法可以使用它,让数据的修改过程可控可追溯。

6.注释

代码中如果出现了大段的注释用来解释代码的含义,而原因是代码写的太糟糕了,不得不依赖于注释,这就是一种坏味道。

当你感觉需要写注释的时候,可以先试试重构,试着让所有注释都变得多余。如果需要注释来解释一段代码做了什么,可以试试提炼函数;如果函数已经提炼出来,但是还是需要注释来解释做了什么,可以试试为函数声明改名;如果注释是说明某些系统的需求规格,试试引入断言。

不是提倡不要写注释,而是要写合适的注释,对于注释,我们应该遵循这样一条原则:“注释的使用不是为了说明这段代码能做什么而是应该说明为什么要这么做”。

7.死代码

死代码泛指在程序运行过程中执行不到的代码,或者执行的到但没有任何作用的代码,也就是无用代码。当程序中的变量变成不依赖于外部传过来的数据,被定义成常量时,便无法适应外界其他的变化,就会产生死代码。这些代码通常是由于需求变更或者代码修改,变得用不到了,如果发现,就及时清除它们。

写在最后

重构越晚,需要修改的代码越多,就会形成技术债务。除了上面提到的几类重构的场景,还有很多其他的场景,重构虽然不是包治百病的灵丹妙药,但是重构是非常有价值的,可以帮助你始终良好地控制自己的代码。尤其是作为敏捷开发团队,重构是团队成员应该熟练掌握的,任何团队都应建立重构技能。同时,Scrum培训师Stefan Wolpers表示,Scrum团队应该考虑将15%~20%的资源分配给每个Sprint周期的重构代码和修复错误。由此可见,重构这件事情是循序渐进的作为一项改进活动持续进行。

点击关注,第一时间了解华为云新鲜技术~

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

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

相关文章

Flink Forward Asia 2022 主论坛概览

2022 年 11 月 26-27 日,Flink Forward Asia(FFA)峰会成功举行。Flink Forward Asia 是由 Apache 软件基金会官方授权、由阿里云承办的技术峰会,是目前国内最大的 Apache 顶级项目会议之一,也是 Flink 开发者和使用者的…

使用nohup命令 或者 代码创建守护进程

目录 一、什么是守护进程? 1、守护进程的概念 2、为什么需要守护进程 二、理解进程组、会话、终端 三、创建守护进程的两种方式 1、nohup命令创建守护进程 2、代码创建守护进程 (1) 创建子进程,父进程退出 (2) 子进程创建新的会话 (3) 更改守护…

jsp美食共享平台系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 美食共享平台系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统采用mvc开发结构 serlvetdaobean模式,系统具有完整的源代码和数据库,系统主要采用 B/S模式开发。开发环境为TOMCAT7.0,Myecl…

二叉树链式结构-c语言实现

文章目录二叉树链式结构实现1. 链式二叉树结构2. 二叉树的遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历2.4 层序遍历3. 常见功能3.1 二叉树结点个数3.2 二叉树叶子结点个数3.3 第K层结点的个数3.4 二叉树的深度3.5 判断是不是树是不是完全二叉树3.6 在二叉树中查找值为x的结点3.7…

VM系列振弦采集读数模块的测量模式

VM系列振弦采集读数模块的测量模式 模块有连续测量和单次测量两种测量模式, 通过向测量模式寄存器 WKMOD.[0]写入 1 使模块工作于连续测量工作模式, 写入 0 使模块工作于单次测量工作模式。 WKMOD.[15]用来设置是否在模块“ 忙” 时禁用数字接口&#xf…

京东低代码平台:水滴表单联动可视化配置的实现与思考

TL;DR drip-form在0.9.0的alpha版支持了可视化配置联动的功能(仍在测试中)drip-form通过协议到代码的转换,尽可能降低常见联动配置的开发成本探讨:JSON diff动态生成常见联动和校验drip form的后续更新:v0.9.0是v0最后…

计算机组成原理-总线详细讲解(持续更新中)

总线概念与分类 定义 总线是一组能为多个部件分时共享的公共信息传送线路 共享是指总线上可以挂接多个部件,各个部件之间互相交换的信息都可以通过这组线路分时共享。 分时是指同一时刻只允许有一个部件向总线发送信息,如果系统中有多个部件&#xf…

React源码分析1-jsx转换及React.createElement

jsx 的转换 我们从 react 应用的入口开始对源码进行分析&#xff0c;创建一个简单的 hello, world 应用&#xff1a; import React, { Component } from react; import ReactDOM from react-dom; export default class App extends Component {render() {return <div>h…

科普下抖音的规则,为什么别人的内容很容易火,而我的很难?

今天给大家科普下抖音的规则&#xff0c;为什么别人的内容很容易火&#xff0c;而我的很难&#xff1f; 上一篇给大家讲了现在做抖音还来得及么&#xff1f;肯定的回答&#xff0c;一直都来得及。 既然来得及&#xff0c;那么我们怎么才能做好抖音呢&#xff1f; 在我看来&a…

Rust 基础(四)

十、泛型、Traits和生命周期 每种编程语言都有有效处理概念重复的工具。在Rust中&#xff0c;一个这样的工具就是泛型:具体类型或其他属性的抽象替身。我们可以表达泛型的行为&#xff0c;或者它们如何与其他泛型相关联&#xff0c;而不知道在编译和运行代码时它们的位置会是什…

[C++]C++入门--引用

​ &#x1f941;作者&#xff1a; 华丞臧 &#x1f4d5;​​​​专栏&#xff1a;【C】 博主Gitee 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎>在评论区指出。 推荐一款刷题网站 &#x1f449;LeetCode…

IPv6进阶:IPv6 过渡技术之IPv6 over IPv4 手动隧道

实验拓扑 R1-R3-R2之间的网络为IPv4环境&#xff1b;PC1及PC2处于IPv6孤岛。 实验需求 R1及R2为IPv6/IPv4双栈设备&#xff1b;在R1及R2上部署IPv6 over IPv4手工隧道使得PC1及PC2能够互相访问。 配置及实现 R3的配置如下 [R3] interface GigabitEthernet0/0/0 [R3-Gigabi…

【Java实战】工作中如何规范控制语句

目录 一、前言 二、控制语句规范 1.【强制】使用switch注意事项 2.【强制】当 switch 括号内的变量类型为 String 并且此变量为外部参数时&#xff0c;必须先进行 null 判断。 3.【强制】在 if / else / for / while / do 语句中必须使用大括号。 4.【强制】三目运算符高…

[附源码]计算机毕业设计springboot本地助农产品销售系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【C++】string详细介绍及模拟实现string类

【C】string详细介绍及模拟实现string类 文章目录【C】string详细介绍及模拟实现string类1.什么是string2.string常用接口介绍2.1string类对象的常见构造2.2string类对象的容量操作2.3string类对象的访问及遍历操作2.4string类对象的修改操作2.5string类非成员函数3.string类的…

移动跨平台开发跨家选型参考建议

从 iPhone 诞生至今&#xff0c;智能手机风靡全球已将近20年&#xff0c;智能手机操作系统 iOS 和 Android 也成为当仁不让的顶流般的存在&#xff0c;而作为其背后的灵魂&#xff0c;移动应用也随着技术的发展已经越来越丰富。如果从技术层面来讲&#xff0c;移动 App 也从最开…

Cloud-computing 实验镜像 chinaskills_cloud_iaas.iso chinaskills_cloud_paas.iso

Cloud-computing 实验镜像 最近因新项目再次进行云计算环境的搭建&#xff0c; 找这两个镜像&#xff08; 找chinaskills_cloud_paas.iso chinaskills_cloud_iaas.iso&#xff09;颇为费劲&#xff0c;用尽九牛二虎之力总算找到了&#xff0c;该大侠还分享了诸多系统镜像和完…

高衍射效率的偏振无关透射光栅的分析与设计

摘要 光栅&#xff0c;特别是具有与波长相当的特征尺寸的光栅&#xff0c;具有偏振相关的光学特性。 这使得设计的具有高衍射效率的光栅难以用于任意偏振。 根据文献[T. Clausnitzer, et al&#xff0c;Proc. SPIE 5252,174-182&#xff08;2003&#xff09;]中报道的概念&…

VMware-AD域控管理

目录 新建AD用户[ 以张三[zhangsan]、李四[lisi]为例 ] 2.用户信息-属性-管理-编辑&#xff1a; 3.将张三设置为AD域控管理员&#xff0c; 在wqd.com域下新建几个部门&#xff08;IT、HR、PRD&#xff09; 对从主机&#xff08;win7&#xff09;进行AD接管 修改win7计算机名称&…

MATLB|电动车智能充电模式及电力高峰需求预测

目录 0 写在前面 1 电动车 1.1 电动车&#xff08;EV&#xff09; 1.2 电动汽车充电 1.3 智能充电和车联网&#xff08;V2G&#xff09; 1.4 V2G 应用 1.5 可再生能源可用性 1.6 基于价格的收费 2 电动车智能充电 2.1 智能充电 2.2 实时电价 2.3 智能充电模式——算…