调试和优化遗留代码

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. 什么是现在必须做的?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

English Learning - L3 作业打卡 Lesson2 Day8 2023.5.12 周五

English Learning - L3 作业打卡 Lesson2 Day8 2023.5.12 周五 引言🍉句1: The color green is natural for trees and grass.成分划分弱读语调 🍉句2: But it is an unnatural color for humans.成分划分弱读连读语调 🍉句3: A person who h…

1.SpringBoot基础篇

SpringBoot 文档更新日志 版本更新日期操作描述v1.02021/11/14A基础篇 前言 ​ 很荣幸有机会能以这样的形式和互联网上的各位小伙伴一起学习交流技术课程,这次给大家带来的是Spring家族中比较重要的一门技术课程——SpringBoot。一句话介绍这个技术,…

自学软件测试,从10K到40K的技术路线,也就是这些东西...

如果有一天我从梦中醒来时,发现自己的几年自动化测试工程师经验被抹掉,重新回到了一个小白的状态。我想要重新自学自动化测试,然后找到一份自己满意的测试工作,我想大概只需要6个月的时间就够了,如果比较顺利的话&…

头部企业走入无人区,国产数智化厂商挑大梁

本文转自数智前线 文|石兆 编|游勇 央国企数智化与信创化双重需求叠加,国产厂商挑大梁,助力企业升级数智化底座,实现价值化国产替代。 4月,在北京用友产业园的数智剧院里,近千位来自30个行业…

uniapp实现微信小程序横屏适配问题demo效果(整理)

使用VMIN进行布局 先了解css3的两个属性vmax和vmin vmax 相对于视口的宽度或高度中较大的那个。其中最大的那个被均分为100单位的vmax vmin 相对于视口的宽度或高度中较小的那个。其中最小的那个被均分为100单位的vmin竖屏布局的时候,750rpx就是竖屏布局屏幕的宽度…

Golang每日一练(leetDay0062) BST迭代器、地下城游戏

目录 173. 二叉搜索树迭代器 Binary Search Tree Iterator 🌟🌟 174. 地下城游戏 Dungeon Game 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 …

ASEMI代理LT8609AJDDM#WTRPBF原装ADI车规级芯片

编辑:ll ASEMI代理LT8609AJDDM#WTRPBF原装ADI车规级芯片 型号:LT8609AJDDM#WTRPBF 品牌:ADI /亚德诺 封装:DFN-10 批号:2023 安装类型:表面贴装型 引脚数量:10 工作温度:-40C~125C 类型…

python基础语法

一、配置python环境 (1)设置环境变量 path添加 C:\Program Files\Python3_11 C:\Program Files\Python3_11\Scripts (2)了解pip 什么是pip? pip是pyton包管理器,pypi(Python Package Ind…

前端开发之Echarts 图表渐变两种实现方式和动态改变图表类型

前端开发之Echarts 图表渐变两种实现方式 前言效果图一、echarts中存在两种渐变方式1、color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{},{},{}])简单案例 2、{type: linear,x: 0,y: 0,x2: 0,y2: 1, [{},{},{}]}案例 二…

Codeforces Round 872 (Div. 2)

Problem - D2 - Codeforces 思路: 我们设good点到所有k点的距离和为dis。 假设good点不止一个,那么我们good点的dis应该都是相等的(废话)。设当前点u是good点,如果他往儿子v移动,儿子有w个点属于k&#…

怎么把mkv格式改成mp4?不妨试试这几种方法吧!

怎么把mkv格式改成mp4?mp4是一种多媒体封装格式,不过我们通常会将它说成是视频格式,它可以在一个文件中容纳无限数量的视频、音频、图片或字幕轨道,mp4格式也是被我们每个人所熟知,因为我们每个人几乎每天都会接触或者…

美团太细了,HashMap可以存null,ConcurrentHashMap不可以,为什么?

△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 420 篇原创分享 作者 l Hollis 来源 l Hollis(ID:hollischuang) 我们知道,ConcurrentHashMap在使用时,和HashMap有一个比较大的区别,那就是HashM…

springboot 多模块项目

比起传统复杂的单体工程,使用Maven的多模块配置,可以帮助项目划分模块,鼓励重用,防止POM变得过于庞大,方便某个模块的构建,而不用每次都构建整个项目,并且使得针对某个模块的特殊控制更为方便。…

Java系统环境变量配置

PATH环境变量 PATH环境变量用于保存一系列命令(可执行程序)的路径,每个路径之间以分号分隔。当在命令行窗口运行一个命令时,操作系统首先会在当前目录下查找是否存在该命令对应的可执行文件,如果未找到,操作…

模糊PID(重心法解模糊梯形图FC)

模糊PID的模糊化请参看下面的博客文章: 博途PLC模糊PID三角隶属度函数指令(含Matlab仿真)_plc 模糊pid_RXXW_Dor的博客-CSDN博客三角隶属度函数FC,我们采用兼容C99标准的函数返回值写法,在FB里调用会更加直观,下面给大家具体讲解代码。常规写法的隶属度函数FC可以参看下…

使用auto-gpt来写一篇技术文章(如何部署autogpt+遇到的问题+如何使用)

文章目录 前言一、autogpt本地部署1.clone代码2.启动虚拟环境3.运行项目 二、使用aotogpt生成文章1.人设描述2.设置目标3.文章的生成过程4.文章的生成内容 总结 前言 最近AI技术的发展非常迅猛,尤其是和GPT相关的技术,备受瞩目。近日,Autogp…

IPv6有哪些优势?

现有的互联网是在IPv4协议的基础上运行的。IPv6是下一版本的互联网协议,也可以说是下一代互联网的协议,它的提出最初是因为随着互联网的迅速发展,IPv4定义的有限地址空间将被耗尽,而地址空间的不足必将妨碍互联网的进一步发展。 为…

视频创作教程-蜜蜂剪辑软件

视频创作教程-蜜蜂剪辑软件 作者介绍 一、视频剪辑软件二、蜜蜂剪辑软件使用1.视频比例选择2.添加视频素材3.视频分割4.添加文字5.转场滤镜6.其它 三、创作实例四、软件分享 作者介绍 熊文博,男,西安工程大学电子信息学院,2020级硕士研究生&…

Vue3 基础语法

文章目录 1.创建Vue项目1.1创建项目1.2 初始项目 2.vue3 语法2.1 复杂写法2.2 简易写法2.3 reactive(对象类型)2.4 ref(简单类型)2.5 computed(计算属性)2.6 watch(监听) 3.vue3 生命周期4.vue3 组件通信4.…

RabbitMQ (HelloWord 消息应答 持久化 不公平分发 预取值)

文章目录 HelloWord工作队列工作线程代码启动两个工作线程工作队列(生产者代码)工作队列(结果成功) 消息应答自动应答手动消息应答multiple的解释消息自动重新入队手动应答代码消息手动应答(生产者)消息手动…