三问助你Debug
译者按: Debug也要三省吾身!
原文: Three Questions About Each Bug You Find
译者: Fundebug
为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。
你是否发现:有时候,当某个BUG被我们修复之后,却又发现一个由该BUG引发的另一个BUG,或则由于修复算法的缺陷引入新的BUG?因此,每一次修复BUG,我都会问自己三个问题来确保我考虑周全。你也可以使用同样的方法来提高代码的质量。
这些精心设计的问题的核心思想是:每一个BUG都是某个隐藏的核心问题的表象。你需要解决这些表面症状,但如果只是治标,那么终究会在其它地方复发,没有治本;你需要发现导致这个BUG的核心问题,并且纠正它。导致出现BUG的核心问题一般不会随机而无法控制,只要你理解了它为什么会出现以及什么原因导致它出现。
在你对自己提出这三个问题之前,你需要克服自己的惰性,仔细地去分析产生BUG的原因。通过从出现BUG的代码位置开始,一步一步问自己为什么会错,往回倒着查看程序执行步骤,直到你找到出现这个BUG的模式。往往和同事一起Debug会有助于你证实你的假设。
程序异常是因为下标变量J越界了
为什么呢?
数组的长度为10,下标最大为9,但是下标J已经是10了
为什么呢?
J是整个数组的长度,但是可索引的下标为9。
在寻找BUG原因的过程中,同时检查一下关键变量的值,看看能否解释在此情况下,变量值为何如此。
为什么name是null?
为什么会打印出一条错误信息?
你需要知道程序到底发生了什么,也就是说要将这些信息度都记录下来方便分析。
现在我们来看是看这三个问题。
1. 这个失误在其它地方有犯过么?
看看代码中其它地方有没有使用过类似的编程方法,通过适当的发散思维也有助于寻找类似的BUG。
- 其它地方有没有使用数组的长度作为下标?
- 所有的数组都是源自同一个原始数组吗?
- 如果数组长度为0,是否会出问题?
尝试描述这段代码应当遵循的逻辑,有BUG的代码会违反该逻辑。
数组起点的初始值加上数组的长度并减去1就是最后一个数组元素的下标。如果数组的长度为0,则不满足。
如果每次修改一个BUG的同时修复了几个其它潜在BUG,将大大提高你的工作效率。尝试将问题用更加抽象的角度去描述将有助于你理解整个程序,以防止引入新的BUG。
2. 在这个BUG后面是否可能隐藏着另一个BUG?
当你已经弄清楚如何修复这个BUG,可以预想BUG修复后的程序行为。BUG代码行之后的语句也可能隐藏着BUG,只是程序以前因为BUG崩溃而没有执行到这一步;或则由于修复可能返回其它值,而以前没有考虑。可以试试向自己提如下问题:
接下来的语句可以成功执行吗?
当你在查看程序的控制流的时候,你可以弄清楚有哪些代码还没有执行过。
我是否测试过这些属性的组合
检查各种属性可能性的组合并不会花费太多工作精力,而且往往会发现很多情况开发者都没有考虑到!
我可以测试出所有错误信息吗?
要注意一个地方的改动可能导致其它地方出现BUG。在局部对一个变量的更改也许会违背之前的一些假设。
如果我只是将J减去1,如果数组的长度为0,那么下一行代码会尝试操作数组中位于-1位置的元素。
如果你已经对程序做了很多修改,每一次都要仔细考虑做法是否正确,甚至需要重新设计和实现这部分代码。
3. 我应该如何做来避免类似的BUG?
你需要尝试寻找方法从根源上解决问题。使用新的方法和工具往往可以直接消除该类型的所有BUG,而不是一个一个去发现和解决。
要找到BUG是什么时候引入的,是否可以在开发阶段避免?
设计没有问题;我在写代码的时候引入了BUG
仔细检查BUG发生的原因,理清BUG发生的代码逻辑,然后看看如何纠正。
定义新的不同的类型来区分数组的索引和长度可以在编译时发现这个错误。(索引类型可以限定索引的最大长度)
每一个数组元素输出的时候都输出对应的下标的计算方法,这样我就可以很快找到问题。
假设你对产生某一个BUG的理由是“变量太多,我只是忘记了”,那么你需要做的是如何改进来保证你不需要记住很多变量。
版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/08/23/three-questions-about-each-bug-you-find/
三问助你Debug的更多相关文章
- 三问助你Fundebug
译者按: Debug也要三省吾身! 原文: Three Questions About Each Bug You Find 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版 ...
- 【GDI+编程】--从三问开始
一. GDI+三问 1.1 GDI+是什么? GDI+是GDI(Graphics Device Interface)的后继者,是一种图形设备的接口,它构成了Win XP操作系统的子系统的API. 1. ...
- RESTful三问
我觉得学习一个技术,其实就是要弄明白三件事情:是什么(what),为什么(why),怎么用(how).正是所谓的三W方法. 所以打算总结一个"三问"系列.为了自己学习,也分享给别人 ...
- 别人 echo 、你也 echo ,是问 echo 知多少?-- Shell十三问<第三问>
别人 echo .你也 echo ,是问 echo 知多少?-- Shell十三问<第三问> 承接上一章所介绍的 command line ,这里我们用 echo 这个命令加以进一步说明. ...
- Jmeter学习(三十三)调试工具Debug Sampler
一.Debug Sampler介绍: 使用Jmeter开发脚本时,难免需要调试,这时可以使用Jmeter的Debug Sampler,它有三个选项:JMeter properties,JMeter v ...
- 【JavaScript】ESlint & Prettier & Flow组合,得此三神助,混沌归太清
Flow Flow的意义 Flow是faceBook开源的一个JavaScript静态类型检查工具,作用类似TypeScript,但是它不像TS那样是一门独立的语言,而是作为一个babel-plugi ...
- mysql.user细节三问
一.如何拒绝用户从某个精确ip访问数据库假如在mysql.user表中存在用户'mydba'@'192.168.85.%',现在想拒绝此用户从某个精确ip访问数据库 # 创建精确ip用户,分配不同的密 ...
- 不同角度看Handler——另类三问
之前有一章节介绍了Handler的常见面试题,今天就来说说另类的,可能你没关注的其他问题,一起看看吧. 系统为什么提供Handler 这点大家应该都知道一些,就是为了切换线程,主要就是为了解决在子线程 ...
- 虚拟dom?diff算法?key?Vue原理的核心三问?打包教你搞定。
为什么需要虚拟DOM 先介绍浏览器加载一个HTML文件需要做哪些事,帮助我们理解为什么我们需要虚拟DOM.webkit引擎的处理流程,如下图所示: 所有浏览器的引擎工作流程都差不多,如上图大致分5步: ...
随机推荐
- Open系列相关概念汇总
最近接触了Android OpenGL ES 和 OpenCL ES,然后就很想知道除了这两个之外到底还有几个Open系列的API集.搜集的结果如下(纯为自己科普): 1. OpenGL(OpenGr ...
- PHP新特性Trait
Trait是PHP 5.4引入的新概念,看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么:提供模块化实现.Trait ...
- 数字(Number)类型(一)
多行语句 Python 通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠(\)来实现多行语句,例如: total = item_one + \ item_two + \ item_three ...
- 比较empty()与 isset()d的区别
比较empty()与 isset()的区别 注意:empty()在PHP5.5之前只能检测变量 isset()只能检测变量 两者之间的联系:empty($var) 等价于 !isset($var)|| ...
- Python中变量的基本使用
变量的基本使用 程序就是用来处理数据的,而变量就是用来存储数据的 目标 变量定义 变量的类型 变量的命名 01. 变量定义 在 Python 中,每个变量 在使用前都必须赋值,变量 赋值以后 该变量 ...
- 【ABP杂烩】Extensions后缀扩展方法
1.Extensions介绍 扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用 ...
- 使用 SharpZipLib 打包数据到 ZIP 文件
SharpZipLib 是一个优秀的开源的第三方压缩库,可以通过这个库将一些导出的文件打包到一个 ZIP 文件当中供用户下载. GitHub 地址:https://github.com/icsharp ...
- linux取IP的几个方法
ifconfig eth0|grep " inet add"|cut -d":" -f2|cut -d " " -f1 ifconfig e ...
- EL表达式jsp页面double小数点后保留两位
EL表达式jsp页面double小数点后保留两位,四舍五入 <fmt:formatNumber type="number" value="${member.logi ...
- [java核心篇02]__内部类
前言 其实我们在前面已经初步接触到内部类了,但是我们去对它的作用并不胜了解.只是简单的知道了类的定义也是可以嵌套的,定义在一个类里面的类就是内部类. class out{ private String ...