重构四要素:目的、对象、时机和方法
目录
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 类及常见方法、线程的状态,今天我们来介绍一下关于线程的另一个重点知识——线程安全。 一、线程安全 基本概念: 线程安全的确切定义是复杂的,但我们可以这样认为&…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
