调试和优化遗留代码

news2025/1/24 5:00:08

1. 认识调试器

1.1 含义

一个能让程序运行、暂停、然后对进程的状态进行观测甚至修改的工具。
在日常的开发当中使用非常广泛。(PHP开发者以及前端开发者除外)

1.2 常见的调试器

  • Go语言的自带的 delve 简写为 “dlv”
  • GNU组织提供的 gdb
  • PHP Xdebug
  • 前端浏览器debug 调试

1.3 调试器实现原理

本质上讲:硬件上和操作系统层面早就已经帮我们预留了口子去实现调试功能。

1.3.1 中断

中断interrupt 字面意思是"打断"、“阻止”。其实计算机领域的意思和它的字面意思一样,就是打断现在CPU或者进程的执行状态。

在这里插入图片描述

为了减少对正在运行的进程的影响,中断处理就要尽可能的快速执行,但是介于中断处理程序在进行响应中断时,有排他性,这就导致一个中断在处理完成之前,其他中断均不能进行响应,倘若一个中断处理的时间过长,则会导致其他中断不能够及时接收到信息甚至中断丢失,为了处理这个问题;操作系统将中断分为两部分:上半部硬中断 和 下半部软中断

上半部分就是快速接收中断,下半部分会开启中断处理线程延迟处理上半部接收到的中断。

CPU中预留了寄存器(中断寄存器interrupt register),来帮我们实现硬中断,操作系统层面提供了系统调用来帮我们实现软中断。

中断其实是计算机系统中的一种异步事件的处理机制,可以提高系统的并发处理能力。

1.3.2 编译型调试器实现原理

系统中存在一个中断向量表,记录中断信号编码与中断处理程序的对应关系(程序入口地址)
在这里插入图片描述
CPU在执行完指令后,都会去check一下是否需要中断了, 如果不需要中断,则继续执行PC寄存器(CS、IP)的下一条指令,如果需要中断,则根据中断向量表,把向量表中的处理程序的入口地址的指令压入PC寄存器,执行中断程序处理。

在中断向量表中有一个int3 指令,是计算机硬件和操作系统支持的调试中断信号。

debug调试器会直接更改当前程序中打断点的位置代码指令并将原来代码存储到寄存器,让其触发int3中断信号,系统在触发中断异常后,debug调试程序捕获中断异常从而让程序停在断点处,如果断点去掉,则会将之前在存储器的原来代码恢复。

所以,其实用其他中断信号,也可以制作调试器,不一定非得int3

1.3.3 解释型调试器实现原理

解释型的语言无需了解CPU中断机制和系统调用,但是实现思路是类似的,就是插入一段代码来断住,且支持环境数据的查看,然后断点放开后就继续执行。

例如:js的 V8 引擎本身就支持debug能力,对外提供了很多接口,以socket 暴露出去,信息格式为 v8 debug protocol

2. 人人都会犯错,正确认识bug

只要程序还是人在写,就会有bug。人无完人,不能因为一个“幼稚”、“低级”的bug把一个人一棒子打死,认为他不是个优秀的程序猿,这种看法实际在一定程度上忽视了人类犯错的复杂性和影响因素的多样性。

2.1 时间因素:

很多项目需要赶进度,抢占蓝海市场,则把软件工期压缩的很短,这样一来就只考虑了开发的效率而忽视了开发的质量;导致代码中出现很多bug

2.2 系统的迭代:

假如将软件系统比作建房子,没有哪一个建筑,能够经得起如此频繁和多的修改,也不可能有人能够在房屋设计之前,就预料到未来需要设计成什么样,每一次的修改和迭代会慢慢破坏软件设计的完整性,直到最后,可能因为一个很小的点,就要修改大量之前的逻辑,如果修改不全,则就会引入bug;

2.3 程序的复杂性:

绝大多数的代码维护程序猿总是在没有完整了解系统整个全貌的情况下去做一些建议的修改,这是非常不可取的,因为如果系统足够大,如果修改掉很多当前看似“怪异”的逻辑,可能会导致引入更多修补的补丁。

2.4 怎么做?

对于一个团队,我们需要思考如何提供一种机制,去减少bug的发生,而不是埋怨犯错的人,否则会破坏团队风气,降低整体研发效率。

团队:

开发者对代码进行严格的测试,写单测。
把单元测试流程化。
代码评审。
测试人员测试。

3. 如何写出好的代码

意识上:

1.改掉马马虎虎得过且过的心态,认认真真写出每一行代码,形成风气,以防破窗理论(此理论认为环境中的不良现象如果被放任存在,会诱使人们仿效,甚至变本加厉。以一幢有少许破窗的建筑为例,如果那些窗不被修理好,可能将会有破坏者破坏更多的窗户。最终他们甚至会闯入建筑内,如果发现无人居住,也许就在那里定居或者纵火。一面墙,如果出现一些涂鸦没有被清洗掉,很快的,墙上就布满了乱七八糟、不堪入目的东西;一条人行道有些许纸屑,不久后就会有更多垃圾,最终人们会视若理所当然地将垃圾顺手丢弃在地上。这个现象,就是犯罪心理学中的破窗效应。)

2.欲速则不达,磨刀不误砍柴工,不求最快,但求最好。先了解项目和需求,不要总想着抢时间;

3.less is more (变量、函数、模块设计、代码量等等)

4.设计上遵循 SOLID原则、KISS原则、DRY原则、YAGNI原则、迪米特法则

5.提高表达力;无论是写代码也好,还是文字描述问题也好,最终都是要给人去看的,核心就是文字和语言表达能力。(不要怕为程序表达而浪费时间,例如花时间起名字)

3.1 保持一致的代码风格

驼峰命名法。CamelCase
蛇形命名法。snake_case
串式命名法。kebab-case
匈牙利命名法。分为 标识符 + 驼峰命名;标识符用来表示数据类型或者用途,例如 IAccountNum ,标识符为"I",表示 long;rwPosition,rw 表示 row。微软产品中广泛使用,目前不推荐。

3.2 代码格式

保持自上而下的垂直风格的阅读;代码格式关乎沟通,而沟通是专业开发者的头等大事

相同思路的代码不用空格,不同思路的代码用空行隔开
为读代码方便,避免一个函数跳到另外一个函数,最后找不到原来函数的尴尬局面,最好是将关系密切概念的代码相互靠近。相关函数:相互调用的函数放到一起,而且调用者应该尽可能放在被调用者上面
变量声明:放到函数顶部。实体变量:放到类的顶部
代码行宽度:80~ 120个字符为最佳,不然看起来费劲,函数最好是70行
团队规则:每个程序员都有自己喜欢的格式规则,但如果在团队中工作,就是团队说了算

3.3 变量名

名副其实,字如其意,避免误导。提供有意义、让人看得懂的线索。

不做无意义的区分:a1,a2,a3… 以及 product 和 productInfo
避免留下误导本意的线索。例如:userList 那就得是一个数组,不是单个对象。
避免硬编码。
使用能够读得出来的词儿,避免自己造词儿。
特殊场景可以写一些大家潜移默化达成“共识”的词儿,例如:循环的场景 i,j,k 单个字母名称一般都用作循环计数器
加前缀增加有意义的语境。例如:firstName 改为 addrfirstName
保持尽量的简短

3.4 类名

纯名词儿。User、Account等

3.5 方法或者函数名

动词或者动词短语。createAccount、save

对象暴露行为,隐藏属性。

3.6 函数

函数第一规则是少、其次是专。少而精,专心只做一件事。

参数是入口,return是出口,保持自上而下的阅读顺序,不要做过多的分流,goto能不用就不用
能写出短小的switch语句很少,switch少用,可以转用其他方式:例如 多态。
函数参数要少,最好是没有,其次是1个、两个,最多三个,不能再多了。(参数读起来很费劲,测起来费劲,试想,一件事情,一个因素的影响好判断,还是十个因素呢?需要十个因素排列组合…)
无副作用。函数中不要引用全局变量、引用类型的数据结构也要注意
写防御性的代码,函数中错误处理要完善。

3.7 注释

正确看待注释,注释固然好,但最多也只能算是一种对代码表达不善的补充说明。如果代码有足够的表达能力,那么注释也许根们不需要。注释要有三个原则:准确(不要出错)、必要(多余注释会显得代码臃肿和浪费时间)、清晰(注释最好格式清晰明了,不要太混乱)。

法律信息。 /* Copyright 2022 xxxxxx. All Rights Reserved. */
参数和函数返回信息注释。
不要吝惜代码,代码注释了就删了,别留着
注释现阶段中英文都可以,方便就好
待完善的部分最好是用 todo 注释写清楚 (IDE目前也支持)
切勿喃喃自语,随便写,想清楚如何表达,别人如何看清楚,再写。

3.8 避免过度设计

有人问 阿里P12 多隆,如何做架构设计?

多隆说淘宝的技术发展到今天,无他,“简单够用”即可——在淘宝只有100万交易量的时候,就支持100万交易量;在淘宝有1个亿交易的时候,就支持1亿交易量;在淘宝过千亿的时候,就支持千亿成交。因此,淘宝的技术基本上是跟着商业需求在走,找到最快实现或者最合用的解决方案

识别核心需求,无需一步到位。

  1. 什么是必须做的?
  2. 什么是现在必须做的?

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

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

相关文章

DNS投毒

定义 DNS缓存投毒又称DNS欺骗,是一种通过查找并利用DNS系统中存在的漏洞,将流量从合法服务器引导至虚假服务器上的攻击方式。与一般的钓鱼攻击采用非法URL不同的是,这种攻击使用的是合法URL地址。 DNS缓存中毒如何工作 在实际的DNS解析过程中,用户请求某个网站,浏览器首…

English Learning - L3 作业打卡 Lesson1 Day6 2023.5.10 周三

English Learning - L3 作业打卡 Lesson1 Day6 2023.5.10 周三 引言🍉句1: The expression was first used in America at the beginning of the twentieth century .成分划分弱读连读爆破语调 🍉句2: It probably comes from the fact that many babies…

分享一组有意思的按钮设计

先上效果图&#xff1a; 一共16个&#xff0c;每个都有自己不同的样式和效果&#xff0c;可以用在自己的项目中&#xff0c;提升客户体验~ 再上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

非Autosar软件手动集成XCP协议栈

文章目录 前言XCP发送XCP接收Xcp初始化Xcp主函数Xcp Event总结前言 最近项目由于各种原因没有直接采用基于Autosar工具生成的代码。只使用了NXP的MCAL。Demo需求实现XCP功能。本文记录手动集成XCP协议的过程,基于CAN总线。集成的前提过程是已有了XCP的静态代码和配置代码。可…

数据结构pta第一天: 堆中的路径 【用数组模拟堆的操作】

这道题其实就涉及两个堆操作&#xff0c; 一个是插入&#xff0c;一个是通过从底到根的遍历 堆的插入&#xff1a;其实就是从下面往上&#xff0c;一个一个比较&#xff0c;&#xff08;因为上面的节点里的值越来越小&#xff0c;如果插入的值比上面的节点小那么就要向上推&am…

基于AT89C51单片机的电子时钟设计与仿真

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87779867?spm1001.2014.3001.5503 源码获取 主要内容&#xff1a; 使用DS1302芯片作为计时设备&#xff0c;用6个7段LED数码管或者LCD162作为显示设备&#xff0c…

【软考七】面向对象技术--UML、设计模式(分数重,刷题刷题)

建议UML和设计模式去听听课&#xff0c;内容多&#xff0c;还需要记。这一部分内容较多&#xff0c;下半年的考生可以慢慢看&#xff0c;上半年的就去刷题吧。 该博客不适合学习UML和设计模式&#xff0c;只适合考试。要学的不要在这浪费时间&#xff0c;切记切记 在5月13号忽然…

MD-MTSP:孔雀优化算法POA求解多仓库多旅行商问题(提供MATLAB代码,可以修改旅行商个数及起点)

一、多仓库多旅行商问题 多旅行商问题&#xff08;Multiple Traveling Salesman Problem, MTSP&#xff09;是著名的旅行商问题&#xff08;Traveling Salesman Problem, TSP&#xff09;的延伸&#xff0c;多旅行商问题定义为&#xff1a;给定一个&#x1d45b;座城市的城市集…

Midjourney8种风格极其使用场景

目录 ​编辑 引言 等距动画 场景 分析性绘图 场景 着色书 场景 信息图画 场景 双重曝光 场景 图示性绘画 场景 二维插图 场景 图解式画像 场景 总结&#xff1a; 八种风格箴言&#xff1a; 引言 我相信大家都或多或少玩过Midjourney&#xff0c;但是要形…

linux系统sed编辑器

sed编辑器 sed编辑器sed基础语法sed查询sed删除sed 替换sed 插入 sed编辑器 sed是文本处理工具&#xff0c;依赖于正则表达式&#xff0c;可以读取文本内容&#xff0c;工具指定条件对数据进行添加、删除、替换等操作&#xff0c;被广泛应用于shell脚本&#xff0c;以完成自动…

我所了解的老板

我所了解的老板 修心篇以名命物 扰我心良心的本来如此 是我心不要全挑剔别人 既是我因 受我之果长久之爱 美女养眼 贤妻养心 调研篇深度思考确定趋势确定时机预测筹划生存资料 做事篇做短视频心态&#xff0c;也是创业的心态做销售冠军的心态&#xff0c;也是创业的心态 修心篇…

【Python--定时任务的四种方法】

定时任务 前言while True&#xff1a;sleep()优点缺点 threading.Timer定时器多线程执行优点缺点 Timeloop库执行定时任务调度模块schedule优缺点 前言 当每隔一段时间就要执行一段程序&#xff0c;或者往复循环执行某一个任务&#xff0c;这就需要使用定时任务来执行程序。应…

【Unity项目实战】手把手教学:飞翔的小鸟(7)障碍对象池

承接上一篇&#xff1a;【Unity项目实战】手把手教学&#xff1a;飞翔的小鸟&#xff08;6&#xff09;添加障碍&#xff0c;我们已经生成了一个障碍物柱子&#xff0c;并且使得小鸟在越过柱子之后自动获得一分&#xff0c;接下来将继续讲解障碍物的随机生成。 一.脚本控制 障…

Centos7设置静态IP

Centos7设置静态IP及修改后不能联网问题解决方式 虚拟机外部配置1、打开Vmware选择虚拟网络编辑器菜单2、获取管理员权限&#xff0c;选择VMnet8&#xff0c;并点击还原默认设置&#xff0c;弹窗选择“是”。3、修改VMnet8的参数4、NAT设置5、确认虚拟机为NAT模式 虚拟机内部配…

数据流图(DFD)

目录 第十二章、数据流图&#xff08;DFD&#xff09;1、数据流图基本概念2、数据字典3、数据平衡原则4、数据流图试题解题技巧4.1、试题一4.2、试题二 第十二章、数据流图&#xff08;DFD&#xff09; 1、数据流图基本概念 数据流图是用于表示系统逻辑模型的一种工具。从数据…

【Swift】Swift和Objective-c混编

1.介绍 Swift和Objective-C都是苹果公司的编程语言&#xff0c;它们可以在同一个项目中同时使用。这种混编方式被称为“混合编程”&#xff08;Mixed Programming&#xff09;。 在混合编程时&#xff0c;我们需要用到一个桥接文件&#xff08;Bridging Header&#xff09;&a…

AfxMessageBox的两种用法

1 函数简介 函数声明如下&#xff1a; int AfxMessageBox(LPCTSTR lpszText,UINT nType MB_OK,UINT nIDHelp 0 ); int AFXAPI AfxMessageBox(UINT nIDPrompt,UINT nType MB_OK,UINT nIDHelp (UINT ) -1 );1.1 参数 lpszText 将显示在消息框的字符串。 nType 消息框…

使用Selenium模拟百度登录

前言 前面我已经安装好了Selenium并模拟成功了一下打开百度页面并进行查询&#xff0c;让我这个python初学者信心倍增&#xff0c;今天再来试一试百度登录 正文 把打开百度的代码放到构造方法中 ps:那个文件目录是用于后面滑块验证图片保存的。 def __init__(self):driver w…

Python实战基础8-列表

一、列表的基本使用 1.列表的格式 定义列的格式&#xff1a;[元素1&#xff0c;元素2&#xff0c;元素3&#xff0c;...&#xff0c;元素n] 变量tmp的类型为列表 tmp [XiaoChen,180,66.0] 列表中的元素可以是不同类型的 2.使用下标获取列表元素 namesList [XiaoChen,Xia…

上海AI lab提出VideoChat:可以与视频对话啦

夕小瑶科技说 原创 作者 | 小戏、ZenMoore 视频相比语言、图像&#xff0c;是更复杂更高级的一类表征世界的模态&#xff0c;而视频理解也同样是相比自然语言处理与计算机视觉的常见工作更复杂的一类工作。在当下大模型的洪流中&#xff0c;自然而然的想法就是大规模语言模型…