重构四要素:目的、对象、时机和方法
目录
1.引言
2.重构的目的:为什么重构(why)
3.重构的对象:到底重构什么(what)
4.重构的时机:什么时候重构(when)
5.重构的方法:应该如何重构(how)
6.思考题
1.引言
一些软件工程师对为什么要重构(why)、到底重构什么(what)、什么时候重构(when)应该如何重构(how)等问题的理解不深,对重构没有系统行认识、在面对质量不佳的代码时,这些软件工程师没有足够的重构技巧,不能系统地进行重构、为了让读者对有清晰的认识,我们先来了解一下重构的目的、对象、时机和方法。
2.重构的目的:为什么重构(why)
软件设计专家 Martin Fowler 给出的重构的定义:“重构是一种对软件内部结构的改善,目的是在不改变软件对外部的可见行为的情况下,使其更易理解,修改成本更低。”在这个定义描述中,我们需要关注一点:“重构不改变对外部的可见行为”。注意,这里提到的“外部”是相对而言的。如果我们重构的是函数,那么函数的定义就是对外部的可见行为;如果我们重构的是一个类库,那么类库暴露的 API就是对外部的可见行为。在了解了重构的定义之后,我们探讨一下为什么要进行代码重构。
首先,重构是保证代码质量的有效手段,可有效避免代码质量下滑。随着技术的更新、需求的变化和人员的流动,代码质量可能存在下降的情况。如果此时没有人为代码的质量负责那么代码就会变得越来越混乱。当代码混乱到一定程度之后,项目的维护成本高于重新开发-套新代码的成本,此时再去重构就不现实了。
其次,高质量的代码不是设计出来的,而是迭代出来的。我们无法完全预测未来的需求也没有足够的精力和资源提前实现“未来可能需要实现的需求”,这就意味着,随着产品的选代、项目的推进和系统的演进,重构代码是不可避免的。
最后,重构是避免过度设计的有效手段,可以兜底暂时不完善的设计。在代码的维护过程中,当遇到问题时,我们再对代码进行重构,这样能有效避免前期的过度设计。
实际上,重构对软件工程师的技术成长也有重要意义。重构是设计原则和设计模式,以及代码规范等理论知识的重要应用场景。重构的过程能够锻炼我们熟练使用这些理论知识的能力。除此之外,重构能力是衡量软件工程师编码能力的重要手段。作者听过这样一句话:“初级软件工程师开发代码,高级软件工程师设计代码,资深软件工程师重构代码”,这句话的意思是:初级软件工程师在已有代码框架下修改、添加功能代码;高级软件工程师从零开始设计代码结构,搭建代码框架;而资深软件工程师为代码质量负责,能够及时发现代码中存在的间题,有针对性地对代码进行重构,时刻保证代码质量处于可控状态。
3.重构的对象:到底重构什么(what)
根据重构的规模,我们可以将重构笼统地分为大规模高层次重构(以下简称“大型面构”)和小规模低层次重构(以下简称”小型重构”)。
大型重构是指对顶层代码设计的重构包括对系统、模块、代码结构、类之间关系等的重构,大型重构的手段包括分层、模块化、解耦和抽象可复用组件等。大型重构的工具包括之前介绍的设计原则和第设计模式。大型重构涉及的代码改动较多,影响因此,其难度较大,耗时较长,引入bug的风险较高。
小型重构是指对代码细节的重构,主要是针对类、函数和变量等级别的重构,如规范命名、规范注释、消除超大类或函数、提取重复代码等。小型重构主要是通过之间介绍的规范来实现。小型重构需要修改之处集中,过程简单,可操作性较强,耗时较短,引入bug风险较低。读者只要熟练掌握各种代码规范,就可以在小型重构时得心应手。
4.重构的时机:什么时候重构(when)
在代码“烂”到一定程度之后,我们才进行重构吗?当然不是。如果代码已经出现维护难、bug频发等严重问题,那么重构已为时晚矣。
因此,我们不提倡平时不注重代码质量,随意添加或删除代码,实在维护不了了就重构甚至重写的行为。我们不要寄希望于代码“烂”到一定程度后通过重构解决所有问题。我们须探索一个可持续、可演进的重构方案。这个重构方案就是持续重构。
我们要培养持续重构的意识。我们应该像把单元测试、CodeReview(代码评审)作为开发的一部分一样,把持续重构也作为开发的一部分。如果持续重构成为一种开发习惯,并在队内形成共识,那么代码质量就有了保障。
5.重构的方法:应该如何重构(how)
前面提到,按照重构的规模,我们可以将重构笼统地分为大型重构和小型重构。对于这两种不同规模的重构,我们要区别对待。
大型重构涉及的代码较多,如果原有代码的质量较差,耦合度较高,那么重构时往往牵一发而动全身,程序员本来觉得可以很快完成的重构,结果有可能代码越改问题越多,导致短时间内无法完成重构,而新业务的开发又与重构冲突,最终,重构只能半途而废,程序员无奈地撤消之前所有的改动。
因此,在进行大型重构时,我们要提前制订完善的重构计划,有条不素地分阶段进行。每个阶段完成一小部分代码的重构,然后提交、测试和运行,没有问题之后,再进行下一阶段的宣构,保证代码仓库中的代码一直处于可运行的状态。在大型重构的每个阶段,我们都要控制重构影响的代码的范围,考虑如何兼容旧的代码逻辑,必要的时候提供实现兼容的过渡代码只有这样,我们才能让每一个阶段的重构都不会耗时太长(最好一天就能完成),不与新功能的开发冲突。
大型重构一定是有组织的、有计划的和谨慎的,需要经验丰富、业务熟练的资深工程师主导,而小型重构的影响范围小,改动耗时短,因此,只要我们愿意并且有时间,随时都可以进行小型重构,实际上,除利用人工方式发现代码的质量问题以外,我们还可以借助成熟的代码分析工具(如Checkstyle、FindBugs和PMD等)自动发现代码中存在的问题,然后有针对性地进行重构。
在项目开发中;资深软件工程师、项目管理者要担负重构的责任,经常重构代码,保证代码的质量处于可控状态,避免引发“破窗效应”(只要一个人向项目中随意添加质量不高的代码,就会有更多的人往项目中添加更多质量不高的代码)。除此之外,我们要在团以内都营造一种追求代码质量的氛围,以此来驱动团队成员主动关注代码质量,进行持续重构。
6.思考题
在重构代码时,你们遇到过哪些问题?在代码重构方面,读者有什么经验教训?
相关文章:
重构四要素:目的、对象、时机和方法
目录 1.引言 2.重构的目的:为什么重构(why) 3.重构的对象:到底重构什么(what) 4.重构的时机:什么时候重构(when) 5.重构的方法:应该如何重构(how) 6.思考题 1.引言 一些软件工程师对为什么要重构(why)、到底重构什么(what)、什么时候重构(when)应该如何重构(how)等问题的…...
基于Echarts的大数据可视化模板:服务器运营监控
目录 引言背景介绍研究现状与相关工作服务器运营监控技术综述服务器运营监控概述监控指标与数据采集可视化界面设计与实现数据存储与查询优化Echarts与大数据可视化Echarts库以及其在大数据可视化领域的应用优势开发过程和所选设计方案模板如何满足管理的特定需求模板功能与特性…...
Python3 笔记:Python的常量
常量(constant):跟变量相对应,指第一次赋予值后就保持固定不变的值。 Python里面没有声明常量的关键字,其他语言像C/C/Java会有const修饰符,但Python没有。 Python中没有使用语法强制定义常量,…...
【Linux】自动化构建工具make/Makefile和git介绍
🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12625432.html 目录 前言 Linux项目自动化构建工具-make/Makefile 举例 .PHONY 常见符号 依赖关系…...
C语言—关于字符串(编程实现部分函数功能)
0.前言 当我们使用这些函数功能时,可以直接调用头文件---#include<string.h>,然后直接使用就行了,本文只是手动编写实现函数的部分功能 1.strlen函数功能实现 功能说明:strlen(s)用来计算字符串s的长度,该函数计数不会包括最…...
picoCTF-Web Exploitation-Trickster
Description I found a web app that can help process images: PNG images only! 这应该是个上传漏洞了,十几年没用过了,不知道思路是不是一样的,以前的思路是通过上传漏洞想办法上传一个木马,拿到webshell,今天试试看…...
SSH 免密登录,设置好仍然需要密码登录解决方法
说明: ssh秘钥登录设置好了,但是登录的时候依然需要提供密码 查看系统安全日志,定位问题 sudo cat /var/log/auth.log或者 sudo cat /var/log/secure找到下面的信息 Authentication refused: bad ownership or modes...(网上的…...
【斑马打印机】web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印
web前端页面通过BrowserPrint API连接斑马打印机进行RFID条形码贴纸打印 在现代物流、仓储和零售行业中,RFID和二维码技术发挥着至关重要的作用。这些技术不仅提高了效率,还增强了追踪和管理的能力。本文将介绍如何使用JavaScript和斑马打印机的BrowserPrint API来打印RFID二…...
DigitalOcean 应用托管更新:应用端到端运行时性能大幅改进
DigitalOcean 希望可以为企业提供所需的工具和基础设施,以帮助企业客户加速云端的开发,实现业务的指数级增长。为此 DigitalOcean 在 2020 年就推出了App Platform。 App Platform(应用托管) 是一个完全托管的 PaaS 解决方案&…...
c/c++对于char*的理解(联合string容器)
在C和C中,char*是一个指向字符(char)的指针。它经常被用来处理C风格的字符串,这种字符串是以空字符(\0)结尾的字符数组。以下是关于char*的一些关键点: C风格的字符串: C风格的字符…...
Web前端三大主流框架是什么?
Web前端开发领域的三大主流框架分别是Angular、React和Vue.js。它们在Web开发领域中占据着重要的地位,各自拥有独特的特点和优势。 Angular Angular是一个由Google开发的前端框架,最初版本称为AngularJS,后来升级为Angular。它是一个完整的…...
一个基于servlet的MVC项目-登录验证
一、MVC的概念 MVC是Model、View、Controller的缩写,分别代表 Web 应用程序中的3种职责1 模型:用于存储数据以及处理用户请求的业务逻辑。 2视图:向控制器提交数据,显示模型中的数据。 3控制器:根据视图提出的请求,判断将请求和数据交给哪个…...
Windows 11 下 kafka 的安装踩坑
安装 windows系统kafka小白入门篇——下载安装,环境配置,入门代码书写(推荐) kafka在windows下安装和使用入门教程 问题1 参考链接 运行kafka集成的zookeeper时,命令:bin\windows\zookeeper-server-star…...
二维数组:行列互换/求最大值及其所在位置/求各行各列的和/矩阵乘积/深入理解二维数组
二维数组 1.定义 只有行号可以省略,初始化 全部初始化/部分初始化/不初始化 2.元素引用 3.存储形式 :顺序存储 按行存储 4.深入理解二维数组 #include<stdio.h> #include<stdlib.h>#define M 2 #define N 3int mian() {int a[M][N] {{1,2,3},{4,5,6}}…...
The Onion Router-洋葱
目录 Tor的运作原理 Tor挑战和局限性 Tor,即The Onion Router(洋葱路由器),是一个用于匿名通信的开放网络,它旨在增强用户的隐私和安全。Tor的名字源自其设计原理,类似于将信息包装在多层“洋葱”中&…...
自动化工具 Ansible:playbooks 剧本编写
目录 前言 一、playbooks 剧本概述 1、playbooks 剧本概念 2、playbooks 剧本组成部分 3、playbooks 剧本特点与优势 二、ansible-playbook 命令 三、playbooks 剧本简单实例 1、编写 apache 的 yum 安装部署脚本 2、编写 nginx 的 yum 安装部署剧本 四、playbooks 定…...
AttributeError: module ‘flask.app‘ has no attribute ‘route‘
秒解方法一: # 未引入Flask app Flask(__name__)秒解方法二: AttributeError: ‘module’ object has no attribute ‘route’错误描述: 这个错误通常发生在使用 app.route 装饰器时,表示 Flask 无法找到 route 属性。 解决方法…...
在云计算与人工智能中,7ECloud扮演着什么样的角色
数据驱动的时代,云计算和人工智能已成为推动现代科技进步的两大引擎。作为一家专注于云计算的公司,7ECloud正是在这个领域发挥自己的力量,力图为企业提供一站式解决方案,并拥有来自厂家的源头支持,用极其低的价格助力企…...
视频推拉流EasyDSS视频直播点播平台如何优先展示正在直播的直播间?
视频推拉流EasyDSS视频直播点播平台集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务,在应用场景上,平台可以运用在互联网教育、在线课堂、游戏…...
JavaEE之线程(4)——线程安全、线程安全的原因,synchronized关键字
前言 在本栏的前面的内容中,我们介绍了线程的创建、Thread 类及常见方法、线程的状态,今天我们来介绍一下关于线程的另一个重点知识——线程安全。 一、线程安全 基本概念: 线程安全的确切定义是复杂的,但我们可以这样认为&…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
