如何进行代码重构

article/2025/8/14 19:10:57

当我们梳理自己或别人的代码时,很可能遇到如下情况:

当然不会如此夸张,但当程序员遇到类似的代码时大概率会抓狂,由此会想到代码重构,但当到最后一步时就没必要重构了,需要重写了。

何为重构?

代码重构(Code refactoring)重构就是在不改变软件系统外部行为的前提下,改善它的内部结构。

简单来说重构就是将原来混乱如麻的代码梳理清除并通过封装、解耦等一系列操作使其变得条理清晰起来,同时不影响原功能的运行。

何种情况下需要进行代码重构及解决方法?

1、变量方法、类等命名不规范时

一个较好的命名应做到见名知意,即通过命名就知道该变量(方法、类)是用来做什么的,而不是随意命名。常用的命名方式有三种:

1、小驼峰命名法(camei)

 第一个单词以小写字母开始;第二个单词的首字母大写,例如:myFirstName、myLastName

2、大驼峰命名法(Upper Camel Case)

    每一个单词的首字母都采用大写字母,如:MyFirstName、MyLastName,常用于类名的命名

3、匈牙利命名法

基本原则是:变量名=属性+类型+对象描述

属性部分:

g_ 全局变量  c_ 常量 m_ c++类成员变量   s_ 静态变量

类型部分:

数组 a   指针 p   函数 fn   无效 v  句柄 h   长整型 l   布尔 b    浮点型(有时也指文件) f

双字 dw   字符串  sz   短整型  n    双精度浮点 d    计数 c(通常用cnt)   字符 ch(通常用c)

整型 i(通常用n)   字节 by   字 w   实型 r   无符号 u

描述部分:

最大 Max   最小 Min   初始化 Init   临时变量 T(或Temp)   源对象 Src    目的对象 Dest

举例

hwnd : h 是类型描述,表示句柄, wnd 是变量对象描述,表示窗口,所以 hwnd 表示窗口句柄;

pfnEatApple : pfn 是类型描述,表示指向函数的指针, EatApple 是变量对象描述,所以它表示指向 EatApple 函数的函数指针变量。

g_cch : g_ 是属性描述,表示全局变量,c 和 ch 分别是计数类型和字符类型,一起表示变量类型,这里忽略了对象描述,所以它表示一个对字符进行计数的全局变量。 上面就是HN命名法的一般规则。

2、重复代码

当一段代码重复多次出现在不同地方实现相同的代码逻辑时就应该考虑了代码重构了,可将重复的代码提取为 一个公共方法,删除源代码的同时并在原来的位置调用。

3、函数过长

有大佬曾讲过,但凡是一个函数如果超过50行以上的代码,就应该开始考虑进行重构它。

当函数过长时函数的复杂度会变高,导致影响代码的可读性,会造成维护时的困难程度增高。

故而应将过长的函数进行拆分,将相对独立的逻辑拆分出去,但不能将函数拆分的过于细碎,这反而会导致复杂度的增高。

4、函数参数过多

当封装或声明一个函数时可能会遇到需要传入参数过多的情况,这可能会导致未来在调用此函数时因为参数顺序不对产生一些问题,此时我们要做的是是将多个参数合并为一个对象,通过传递对象来减少函数需要传递的参数。

5、过多的循环语句

在许多业务场景中,循环语句都是不必要的,故尽量减少for循环的使用,可通过filter、map、forEach等方法来代替循环,当一个函数中循环嵌套过多时时间复杂度会显著增加,如若必须使用则可通过breakcontinue关键字中断循环,也可通过return关键字直接中断函数的调用减少循环次数。

6、过多的if...else(switch)分支

在一个系统或功能的开发过程中,刚开始自己写的代码很简洁,逻辑清晰,函数精简,没有一个 if-else,可随着代码逻辑不断完善和业务的瞬息万变:比如需要对入参进行类型和值进行判断;这里要判断下变量是否为空;不同类型是否要执行不同的流程。这时大概率就会选用if...else语句来进行逻辑判断,但随着时间延长,原来单一的if...else语句会变得分支越来越多, 复杂度越来越高,代码可读性越来越低,这就造成了屎山代码的堆积,后期维护就变得困难起来。所以就应该避免该情况的发生。

该如何避免此种情况呢?

在进行if...else语句的书写时要做到仅出现在主干代码之中,避免嵌套过深。解决的具体方案有:合并条件表达式、减少嵌套(分支数)、条件取反判断、移除或减少临时变量

合并条件表达式

/*重构前*/
function test (num) {if(num<0) return 0;if(num>12) return 0;if(num==9) return 0;
}/*重构后*/function test (num) {if(num<0 || num>12 || num==9) return 0;
}

减少嵌套(分支数)

/*重构前*/
switch (month) {case 1:case 3:case 5:case 7:case 8:case 10:case 12: {return [moment(`${year}-${month}-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-${month}-31 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),];}case 4:case 6:case 9:case 11: {return [moment(`${year}-${month}-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-${month}-30 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),];}case 2: {if ((year % 4 === 0 && year % 100 != 0) || year % 400 === 0)return [moment(`${year}-02-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-02-29 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),];else {return [moment(`${year}-02-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-02-28 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),];}}}/*重构后*/
let monthTypeObj = {big: [1, 3, 5, 7, 8, 10, 12],normal: [4, 6, 9, 11],};let monthDateValueObj = {big: [moment(`${year}-${month}-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-${month}-31 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),],normal: [moment(`${year}-${month}-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-${month}-30 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),],};for (const monthTypeObjKey in monthTypeObj) {if (monthTypeObj[monthTypeObjKey].includes(month)) {return monthDateValueObj[monthTypeObjKey];}}if ((year % 4 === 0 && year % 100 != 0) || year % 400 === 0)return [moment(`${year}-02-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-02-29 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),];else {return [moment(`${year}-02-01 00:00:00`, 'yyyy-MM-DD 00:00:00'),moment(`${year}-02-28 23:59:59`, 'yyyy-MM-DD 23:59:59').hour(23).minute(59).second(59),];}

7、减少三目运算符的使用

当分支逻辑简单,条理清晰时,三目运算符是可以清晰的完成需求的,担当条件逻辑复杂时就不要使用三目运算符了,这时使用三目运算符会使代码不好理解且难于维护,如下:

if ( !aup || !bup ) {return a === doc ? -1 :b === doc ? 1 :aup ? -1 :bup ? 1 :sortInput ?( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :0;
}

具体的代码重构方法还有很多,在此就不再赘余了,一切的代码重构都是基于项目和具体情况的,要按照具体的情景实行相应的代码重构,不符合情景时就不要进行代码重构了。


http://chatgpt.dhexx.cn/article/jCJCgOrx.shtml

相关文章

代码重构常用的技巧

一、前言 重构(名词)&#xff1a;对软件内部结构的一种调整&#xff0c;目的是在不改变软件可观察行为的前提下&#xff0c;提高其可理解性&#xff0c;降低其修改成本。 重构(动词)&#xff1a;使用一系列重构手法&#xff0c;在不改变软件可观察行为的前提下&#xff0c;调…

代码重构,最佳实践,你真的会代码重构吗?

WHAT&#xff1a;什么是重构&#xff1f; Martin Fowler&#xff1a;重构是一种对软件内部结构的改善&#xff0c;目的是在不改变软件的可见行为的情况下&#xff0c;使其更易理解&#xff0c;修改成本更低。 大型重构 对象&#xff1a;对系统、模块、代码结构、类与类之间的关…

代码重构有什么意义?为什么重构有用?

点击上方“武培轩”&#xff0c;选择“设为星标” 技术文章第一时间送达&#xff01; 所谓重构就是在不改变代码外在行为的前提下&#xff0c;对代码进行修改&#xff0c;以改进程序的内部结构。本质上说&#xff0c;重构就是在代码写好之后改进它的设计。 前几个月完成了一个模…

代码重构之路 --我的2022年总结

2022年是我正式参加工作的第10个年头&#xff0c;也是我在CSDN上写博客的第11个年头。在这10余年的时间里&#xff0c;虽然在工作上遇到了各种情况&#xff0c;但我一直坚持输出、坚持分享&#xff0c;一共在CSDN上发表了530多篇原创博文。在这些文章中&#xff0c;大部分都是与…

java代码重构的思路Java代码重构的几种模式

Java代码重构的几种模式 Java代码的重构模式主要有三种&#xff1a;重命名方法重构模式、引入解释性变量重构模式、以查询取代临时变量重构模式重命名方法重构模式建议执行如下的步骤来完成&#xff1a;1.建立一个具有新名称的方法2.将旧方法的方法体复制进新方法3.讲旧方法的方…

java 代码重构

几天前的一次上线&#xff0c;脑残手抖不小心写了bug&#xff0c;虽然组里的老大没有说什么&#xff0c;但心里面很是难过。同事说我之所以写虫子是因为我讨厌if/else&#xff0c;这个习惯不好。的确&#xff0c;if/else可以帮助我们很方便的写出流程控制代码&#xff0c;简洁明…

代码重构终极指南!!

&#x1f447;&#x1f447;关注后回复 “进群” &#xff0c;拉你进程序员交流群&#x1f447;&#x1f447; 作者丨Alex Omeyer译者丨弯月出品丨CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;原文链接&#xff1a; https://medium.com/swlh/the-ultimate-engineers-gu…

如何进行代码重构?

作为一个程序员&#xff0c;大部分时候&#xff0c;如果不是一个人承包整个项目&#xff0c;那么有1/3的时间在写代码&#xff0c;1/3的时间在看别人写的代码&#xff0c;剩下的1/3的时间在摸鱼。 那么如何提高摸鱼的时间&#xff1f;看别人写代码十分头疼&#xff0c;分分钟想…

代码重构学习

一、代码重构是什么 用重构手法去重构代码 二、为什么需要代码重构 1.方便维护。为了在修改代码时&#xff0c;添加的地方有个切入点&#xff0c;减少bug。 2.有利于理解设计思想和代码。 三、代码重构怎么做&#xff08;养成习惯&#xff09; 思想&#xff1a; 1.修改一…

代码重构技巧:如何将烂代码变成好代码?

这是本文的目录 前言重构入门1. 格式化代码2. 注释3. 废弃的代码4. 变量命名5. 常量命名6. 负值条件的重构7. {} 作为单独的一行8. 变量定义和使用距离太远 重构进阶1. 重复代码2. 函数参数3. 变量多余4. 缺少变量5. 复杂条件 老旧代码的重构利用工具总 结零基础Python学习资源…

代码重构新手教程:如何将烂代码变成好代码?

作者 &#xff5c; 王莉敏 策划 &#xff5c; 蔡芳芳 作为有几年工作经验的程序员&#xff0c;都会对 bad code 不满意。如何将烂代码变成好代码&#xff0c;本文将由浅入深、一步步带你理解重构的奥秘&#xff0c;让你对重构有个基本的了解。本文基于文章《The Simple Ways to…

常见代码重构技巧(非常实用)

你已选中了添加链接的内容点击上方“芋道源码”&#xff0c;选择“设为星标” 管她前浪&#xff0c;还是后浪&#xff1f; 能浪的浪&#xff0c;才是好浪&#xff01; 每天 8:55 更新文章&#xff0c;每天掉亿点点头发... 源码精品专栏 原创 | Java 2020 超神之路&#xff0c;…

hue执行workflow工作流出现直接FAILED

场景&#xff1a; 执行以下任务流的时候就出现了直接失败的情况 在第一次执行并且数据完善的情况下测试的&#xff0c;状态是成功的 但是第二次是在第一次基础上测试的&#xff0c;基础数据有所缺失 日志为&#xff1a; Failing Oozie Launcher, Main class [org.apache.oo…

Git Workflow工作流示意图

来自&#xff1a;http://blog.osteele.com/posts/2008/05/my-git-workflow UPDATE: git pretty 来自: http://justinhileman.info/article/git-pretty/full/ from: http://iccm.cc/git-workflow/

使用Python开源库Couler编写和提交Argo Workflow工作流

Python 是用户在 Kubernetes 上编写机器学习工作流的流行编程语言。 开箱即用时&#xff0c;Argo 并没有为 Python 提供一流的支持。相反&#xff0c;我们提供Java、Golang 和 Python API 客户端[1]。 但这对大多数用户来说还不够。许多用户需要一个抽象层来添加组件和特定于…

SharePoint 2013 Nintex Workflow 工作流帮助(八)

博客地址 http://blog.csdn.net/foxdave 工作流动作 15. Complete Workflow Task&#xff08;User interaction分组&#xff09; 此工作流动作将完成任何进行中的任务&#xff0c;它将处理足够的单独任务来达到选择的结果&#xff0c;接下来工作流引擎会依据工作流的设置处理…

工作流(Workflow) -- 实现简单工作流程

工作流(activiti) 工作流简介 业务过程的部分或整体在计算机应用环境下的自动化 工作流就是多个参与者,按照某种预定义的规则,传递业务信息,进行审核的功能一个框架(activiti) 核心 23张表 ACT_RE_*:RE’表示repository。 这个前缀的表包含了流程定义和流程静态资源 (…

wf工作流java_WF Workflow 状态机工作流 开发

概述 工作流是对业务流程的建模&#xff0c;当我们设计工作流的时候&#xff0c;我们首先要分析业务处理过程中要经历的步骤。然后&#xff0c;我们就可以利用WF创建工作流模型来模拟业务的处理过程。 我们知道&#xff0c;WF包含两种类型的工作流&#xff1a;顺序工作流和状态…

Mendix 9.6 - Workflow(工作流)基础设计

一 概述 Workflow(工作流)是Mendix 9版本中新增的一种可视化语言功能模块&#xff0c;我们可以用它来构建可扩展的流程。此外它还与其他可视化语言完全集成&#xff0c;例如微流编辑器和页面编辑器。 在公司我们往往需要填写许多表单&#xff0c;包括行政、人事、IT等方面的&a…

workflow工作流(三):画流程图工具对比

一、总结 我所用过能画工作流的工具有2个&#xff1a;1.eclipse插件&#xff0c;2.flowable官方网页版&#xff0c;结论是eclipse插件好用&#xff0c;后者要上传下载&#xff0c;还容易丢数据 注意事项&#xff1a;eclipse插件画出来的bpmn文件的schama是activiti&#xff0…