老程序员解 Bug 的通用套路

2017-06-30 13:51:00
admin
转贴 2393
摘要:大家都知道,程序员是写代码的。但是现实情况却是,写代码仅仅占了程序员日常工作的一小部分,大部分时间都在干嘛? 解 Bug !当然也有例外,比如初创公司的起始阶段,比如一个全新的项目从无到有的过程,这些阶段是程序员集中编码阶段,在 Coding 上花费的时间大概与 Debug 的时间相当,或者略大于 Debug 的时间。

大家都知道,程序员是写代码的。但是现实情况却是,写代码仅仅占了程序员日常工作的一小部分,大部分时间都在干嘛? 解 Bug !

当然也有例外,比如初创公司的起始阶段,比如一个全新的项目从无到有的过程,这些阶段是程序员集中编码阶段,在 Coding 上花费的时间大概与 Debug 的时间相当,或者略大于 Debug 的时间。

很多的公司,尤其是大公司,都有着非常成熟的产品,除了一些全新加崭新的项目,程序员很少需要把软件项目从 0 做起,都是在之前的版本上加以改进,完善和迭代,同时还需要对老版本进行维护。

所以,解 Bug ,很多时候,成了我们工作的重中之重。能不能快速地定位 Bug,解决 Bug,也是检验程序员新手与老手的一种方式。

那么,程序员老手是怎么解 Bug 呢?

其实都是有套路的,且听我慢慢道来。



经验预判

测试人员报过来一个 Bug, 首先可以根据经验判断一下,这到底是不是真的是一个 Bug。

千万不要相信,测试说有一个 Bug,这真的就一定是个 Bug。

根据测试的 “Bug” 描述,先看一下:

1. 是不是测试用的软件版本不一致?因为有的时候,这个 Bug 已经在代码库中 Fix 了,但是测试人员并没有及时获取到这个信息,用的还是老的软件版本。

2. 是不是测试工具的问题?遇到结果不对,并不一定是你软件的问题,有的时候还有可能是测试工具的问题。

3. 是不是测试环境没有设置对?测试环境的软硬件是否匹配?软件版本与测试工具之间是否匹配?环境变量与测试脚本设置对了没有?测试用例用的对不对?

4. 是不是一个已知而又暂时不好解决的 Bug?比如这个 Bug 跟一个已知的硬件 Bug 相关,而这个硬件 Bug 一时半会也解决不了。

5. 是不是以前也遇到过类似的 Bug ? 而针对这个 Bug,已经有了解决方案,但是还没来及提交进代码库。

6. 是不是别的开发人员已经遇到过这个问题? 可以适当询问一下比自己有经验的同事,以前有没有遇到过这个 Bug。说不定这就是个别人已经踩过的坑,那么知道了这个信息,你就没有必要把这个坑再踩一遍。


猜测解决方案

这一点其实还是属于经验预判。

当你确定这真的是一个 Bug,而根据 Bug 的描述,又可以八九不离十猜测出 Bug 的出错原因的时候,可以试着修改代码,把修改后的代码让测试人员拿去测试,看一下能否解决这个 Bug。

这一招是用在你对这个修改方案很有信心的时候。可以避免本地复现 Bug 的时间和精力消耗,因为有的时候,搭建个能够复现 Bug 的环境,还是很繁琐的。

但是,切忌把你胡乱猜测的修改拿去让测试人员测试,这一点对测试人员也不负责任。


本地复现 Bug

凭着自己的经验,没法一眼看出问题所在,那么就只有动手先把 Bug 在本地复现了再说吧。

前面说了,复现 Bug,搭建测试环境,有的时候是一个很繁琐的过程。涉及到软件、硬件的匹配,测试工具的匹配,测试用例的匹配,还有各种环境的配置都要匹配。

所以这也是为什么我建议大家,不要一上来就急着搭建测试环境,复现 Bug,可以凭自己的经验先行判断的原因。当然,一些简单的很好复现 Bug 的场合除外。

复现 Bug, 除了搭建测试环境比较繁琐以外,还有一个很令人头疼的地方,那就是随机性。

同样的测试环境,只有在测试人员机器上 Bug 才会出现,而在你机器中,就是好的,你说是不是很邪门? 你还别不相信,这种情况真的时有发生,鬼知道 Bug 经历了些什么!

随机性 Bug,还有一个恶心的地方,就是不是 100% 可以重现。有的时候测试用例跑个 100 遍,Bug 才出现那么一两次,程序员守在电脑前,等待个 Bug 重现,像是等待彩票开奖一样,这心情,只有经历过的人才懂。

前面说这么多,只是想说明,复现 Bug 有的时候,是多么繁琐,多么痛苦。


开始调试

假如有幸复现了 Bug,那么接下来进入正经调试阶段。

1. 查看 Log。大型软件项目里面,都会有一些调试信息,会生成一些 Log,可以首先查看一下 Log 里面有没有错误信息,这是排错最直观的方法。

2. 用调试工具单步跟踪代码进行调试。看一下程序在运行的时候,代码里面发生了什么,跟踪一下代码逻辑执行步骤,有没有发生逻辑错误,是不是执行到了异常代码处理区,函数输入和输出值是多少,临时变量,全局变量,结构体的值又分别是多少。

3. 打印程序输入、输出参数、临时变量,缓冲区和内存空间。把这些变量存在文件中,用 Notepad++ 查看一下,是不是跟预期的一致,有没有明显错误的地方,需要的话,再进一步查看它们的十六进制码。

4. 在任意需要的地方添加打印。有的时候,单步跟踪不是很方便的情况下,或者在多线程情况下怕影响时序,可以在代码里面逐行添加打印,把你想要的东西打印在文件里,这样方便查看。


修改代码

经过前面的调试,你一定有了值得怀疑的目标。接下来尝试修改你怀疑的代码段。

这个过程不是一蹴而就的,需要经过不断的修改、添加、删除代码。

1. 改正要害。经过调试,假如你已经确定了错误的原因,那么可以直击要害,一下改正。

2. 增删代码。只是怀疑,还不确定,可以尝试一下把你怀疑的代码段注释掉,看一下是不是就好了,接下来,进一步缩小注释范围,直到聚焦到某一行代码,那么这一行代码应该就是导致 Bug 的原因。但是这种还是比较理想的情况,有些问题比较复杂,你可以自己手动添加一些便于调试的代码进去。

这一过程本身需要不断尝试,改着改着,试着试着,就发现问题所在了。


解决问题

假如说前面的一切工作是为了发现问题,那么接下要做的是解决问题。

个人感觉解 Bug 的过程,最难的不是怎么解决问题,Fix Bug,而是前面定位 Bug ,找 Bug 的过程。可以说,找到了 Bug,解决方案就呼之欲出了。

定位到了 Bug 的原因,能自己解决的就自己解决,自己解决不了的申请资源,让相关人员 (stakeholder)跟自己共同解决。

当然,还是有些情况,发现了问题所在,Bug 并没有那么好解决。

最后,修改了代码,解决了 Bug,在 commit 之前,别忘记多测几遍,看一下这个 Bug 是不是真没有了,再做一遍回归测试,看一看会不会引起新的 Bug。

多做几遍本地测试,嗯!

做完测试,就开始走流程,提交代码吧。

提交完代码,老天保佑,集成测试不会有问题,先让我忐忑几天。


发表评论
评论通过审核后显示。
博客分类