译者按: Debug也要三省吾身!

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

你是否发现:有时候,当某个BUG被我们修复之后,却又发现一个由该BUG引发的另一个BUG,或则由于修复算法的缺陷引入新的BUG?因此,每一次修复BUG,我都会问自己三个问题来确保我考虑周全。你也可以使用同样的方法来提高代码的质量。

这些精心设计的问题的核心思想是:每一个BUG都是某个隐藏的核心问题的表象。你需要解决这些表面症状,但如果只是治标,那么终究会在其它地方复发,没有治本;你需要发现导致这个BUG的核心问题,并且纠正它。导致出现BUG的核心问题一般不会随机而无法控制,只要你理解了它为什么会出现以及什么原因导致它出现。

在你对自己提出这三个问题之前,你需要克服自己的惰性,仔细地去分析产生BUG的原因。通过从出现BUG的代码位置开始,一步一步问自己为什么会错,往回倒着查看程序执行步骤,直到你找到出现这个BUG的模式。往往和同事一起Debug会有助于你证实你的假设。

程序异常是因为下标变量J越界了
为什么呢?
数组的长度为10,下标最大为9,但是下标J已经是10了
为什么呢?
J是整个数组的长度,但是可索引的下标为9。

在寻找BUG原因的过程中,同时检查一下关键变量的值,看看能否解释在此情况下,变量值为何如此。

为什么name是null?
为什么会打印出一条错误信息?

你需要知道程序到底发生了什么,也就是说要将这些信息度都记录下来方便分析。

现在我们来看是看这三个问题。

1. 这个失误在其它地方有犯过么?

看看代码中其它地方有没有使用过类似的编程方法,通过适当的发散思维也有助于寻找类似的BUG。

  1. 其它地方有没有使用数组的长度作为下标?
  2. 所有的数组都是源自同一个原始数组吗?
  3. 如果数组长度为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

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/08/23/three-questions-about-each-bug-you-find/

三问助你Fundebug的更多相关文章

  1. 三问助你Debug

    译者按: Debug也要三省吾身! 原文: Three Questions About Each Bug You Find 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版 ...

  2. 【GDI+编程】--从三问开始

    一. GDI+三问 1.1 GDI+是什么? GDI+是GDI(Graphics Device Interface)的后继者,是一种图形设备的接口,它构成了Win XP操作系统的子系统的API. 1. ...

  3. RESTful三问

    我觉得学习一个技术,其实就是要弄明白三件事情:是什么(what),为什么(why),怎么用(how).正是所谓的三W方法. 所以打算总结一个"三问"系列.为了自己学习,也分享给别人 ...

  4. 别人 echo 、你也 echo ,是问 echo 知多少?-- Shell十三问<第三问>

    别人 echo .你也 echo ,是问 echo 知多少?-- Shell十三问<第三问> 承接上一章所介绍的 command line ,这里我们用 echo 这个命令加以进一步说明. ...

  5. 【JavaScript】ESlint & Prettier & Flow组合,得此三神助,混沌归太清

    Flow Flow的意义 Flow是faceBook开源的一个JavaScript静态类型检查工具,作用类似TypeScript,但是它不像TS那样是一门独立的语言,而是作为一个babel-plugi ...

  6. mysql.user细节三问

    一.如何拒绝用户从某个精确ip访问数据库假如在mysql.user表中存在用户'mydba'@'192.168.85.%',现在想拒绝此用户从某个精确ip访问数据库 # 创建精确ip用户,分配不同的密 ...

  7. 不同角度看Handler——另类三问

    之前有一章节介绍了Handler的常见面试题,今天就来说说另类的,可能你没关注的其他问题,一起看看吧. 系统为什么提供Handler 这点大家应该都知道一些,就是为了切换线程,主要就是为了解决在子线程 ...

  8. 虚拟dom?diff算法?key?Vue原理的核心三问?打包教你搞定。

    为什么需要虚拟DOM 先介绍浏览器加载一个HTML文件需要做哪些事,帮助我们理解为什么我们需要虚拟DOM.webkit引擎的处理流程,如下图所示: 所有浏览器的引擎工作流程都差不多,如上图大致分5步: ...

  9. Kafka 入门三问

    目录 1 Kafka 是什么? 1.1 背景 1.2 定位 1.3 产生的原因 1.4 Kafka 有哪些特征 消息和批次 模式 主题和分区 生产者和消费者 broker 和 集群 1.5 Kafka ...

随机推荐

  1. 探讨npm依赖管理之peerDependencies

    引言 想必前端同学对npm的devDependencies和dependencies都比较熟悉,但是对peerDependencies可能就有点陌生,尤其是没有写过npm包插件的同学,比如之前使用gr ...

  2. Python面向对象6:抽象类和自定义类

    抽象类- 抽象方法: 没有具体实现内容的方法成为抽象方法- 抽象方法的主要意义是规范了子类的行为和接口- 抽象类的使用需要借助abc模块 import abc - 抽象类:包含抽象方法的类叫抽象类,通 ...

  3. Python遍历List集合四种方法

    这篇文章主要介绍了Python 列表(List) 的四种遍历方法实例 详解的相关资料,需要的朋友可以参考下 分别是:直接遍历对象 通过索引遍历 通过enumerate方法 通过iter方法. 使用Py ...

  4. pm2日志管理pm2-logrotate介绍

    先来看两个问题 问:pm2-logrotate是什么? 答:pm2-logrotate可以理解为是一个pm2的插件,它扩充了pm2本身没有功能:日志管理,所以它的运行需要依靠pm2,想用它必须先安装p ...

  5. C# 结合 using 语句块的三种实用方法

    一.简介 阅读 Abp 源码的过程中,自己也学习到了一些之前没有接触过的知识.在这里,我在这儿针对研究学习 Abp 框架中,遇到的一些值得分享的知识写几篇文章.如果有什么疑问或者问题,欢迎大家评论指正 ...

  6. 如何配置React Native真机调试-iOS

    说在前面,本教程是建立在项目已经成功在模拟器上运行的基础上,如果你是还未配置好环境的新手,建议先从官网快速入门开始:官网英文版 . 中文版 ok, 切入正题,当你已经完成好环境配置,在模拟器上成功的运 ...

  7. NodeJS学习笔记 - Apache反向代理集成实现

    初学,简单的实现,为进行优化. 1. 假设NodeJS服务端监听3000端口 2. Apache反向代理设置 a. 在httpd.conf配置文件中开启代理模块 LoadModule proxy_mo ...

  8. Vue : Expected the Promise rejection reason to be an Error

    在vue项目中添加ESLint,new 一个 Promise 一直显示错误 :Expected the Promise rejection reason to be an Error 正常来说new ...

  9. 利用 ELK 搭建 Docker 容器化应用日志中心

    利用 ELK 搭建 Docker 容器化应用日志中心 概述 应用一旦容器化以后,需要考虑的就是如何采集位于 Docker 容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 ...

  10. mysql 开发进阶篇系列 49 表的数据导出(into outfile,mysqldump)

    一.概述 在数据库的日常维护中,表的导入和导出是很频繁的操作,本篇讲解如何使用导入功能,并以案例为演示.某些情况下,需要将表里的数据导出为某些符号分割的纯数据文本,而不是sql语句,比如:(1)用来作 ...