代码调试的专业姿式

程序员

 1、概要web

 

欢迎收藏。当你遇到很是难缠的Bug时,不妨回来这里看看…编程

编程原本是一项很是优雅的工做,而程序员,也理应是那种如艺术家通常,不断写出极具观赏性和创造力的做品的职业。 然而自从工做以后,却发现身边的程序员大多深陷赶迭代出口修复紧急Bug的泥潭。常常能够看到下面这些场景:服务器

修复了一个Bug,却引入了更加致命的Bug
不停的修改代码,重启服务器,Bug依然没有修复
补丁打上去后,Bug依旧存在,定位了好久,最后发现是补丁打错地方了
虽然咱们应该尽量保证提交上去的代码里Bug越少越好,可是当Bug真的出现时,咱们每每十分慌乱,像一只无头苍蝇同样,调试的过程毫无章法并发

直到最近偶然看到了这本书——《调试九法》,这是我看到的第一本讲调试方法论的书,回想本身以前在解决Bug时的常常遇到的手足无措,像无头苍蝇通常四处乱撞,最后瞎猫碰上死耗子般地解决了Bug,我绝不犹豫地买下这本书。app

这是一套系统的调试理论。框架

但愿本文介绍的这套调试学的知识,可以帮助你在从此遇到Bug时,思路更加清晰,心情更加淡定,从容不迫地去解决问题。webapp

编程语言

 2、调试法则总览微服务

 

这套方法论能够总结成一句话:

调试是一门科学,任何不懂原理就进行的操做都是耍流氓。

这句话能够分为两个步骤进行实践:

准备工做:

若是你要调试这个系统,首先你必须先理解它。
在开始调试以前,检查一下“插头”,别由于一些简单的问题而瞎忙活半天。
肯定“插头”没有问题以后,你须要重现Bug。
寻找缘由并解决Bug:

  • 不要认为你猜想的缘由是对的,要去观察,验证你的猜想。

  • 采用分而治之的方法,定位多模块的系统问题和修复由多个子问题引起的问题。

  • 一次只修改一个地方

  • 作好修改记录

  • 若是正向调试走不通,不妨试一下反向调试法

  • 最后一招:求助他人

下面对这些法则逐一进行详细地介绍。

 3、理解系统

 

理解系统是定位Bug的前提条件。

我以前遇到程序抛出异常时,常常就把异常信息贴到网上搜,而后把网上的解决方案执行一遍,有时work了,就大吉大利,可大多数时候,是不work的,缘由很简单,也许对方的JDK版本跟你的不同,也许大家俩只是报错信息相同,可是抛异常的缘由不一样,更大的可能,对方的解决方案原本就行不通。
这就能理解为何理解系统是定位Bug的前提了,若是你在定位一个JDK异常,那么至少你要掌握Java SE吧,若是你能掌握JVM的垃圾回收原理、类加载机制,天然更好;而若是你在定位一个支付系统为何没有把帐打到客户的帐户,那么你得了解支付的流程吧。

总之,在开始调试以前,咱们得弄清楚,调试是一门科学,而不是一门几率学,你须要理解整个系统,才可以进行调试。有如下方法能够帮助你理解这个系统:

  • 阅读手册:阅读需求设计文档、产品文档、使用手册等

  • 仔细阅读手册的每个细节:说不定解决Bug的方案就在某个段落里

  • 掌握基础知识:最后你老是要看源码的,至少你要掌握相应的编程语言把

  • 了解工做流程:从总体的角度来观察,而不是作井底之蛙

能够说,理解系统的最终目的就是为了了解工做流程,了解了工做流程,你才可以从总体的角度来观察,否则就像井底之蛙,觉得问题必定出在本身这个模块,而其实问题是在上游的某个模块里。这一点,和《程序员的思惟修炼》中提到的,“专家从总体进行思考”的观点不谋而合。

 4、检查插头

 

这里固然不是让你去问人家插头插了没,插头在这里是泛指一切让产品正常运行的基本要求。这些基本要求一般咱们都认为理所固然是正常的,可事实有时并不是如此。

好比你的一个系统,须要在配置界面配置白名单,否则上游的请求就会被拒绝,那么当出现问题时,你应该首先去检查一下这个白名单配置了没,由于对方有多是个新手。

甚至当出现一些不可理喻的错误时,你要去软件的运行目录下,好比Tomcat的webapps目录,看看软件包是否是完整。
当你替换新代码上去后,发现Bug依然存在时,不妨上去看看正在运行着的,是否是仍是旧代码。

书中把这条规则放到了倒数第三条,我这里把它放到第二条,缘由很简单,一般咱们在发现Bug或者别人跟本身说这里有Bug时,内心都会慌,都会紧张,因此不妨先检查一下插头,缓解一下本身紧张的心情,同时也强迫你从总体的视角进行观察,不会局限在一个小模块里。

 5、重现失败

 

这几乎是一个下意识的动做,就算你以前没读过这本书,在遇到Bug时,你也会去尝试重现它,缘由很简单:

  • 重现失败让你能够观察失败发生时的上下文信息,进而找到失败的缘由

  • 重现失败让你能够判断是否已经修复了问题

有些问题很好重现,而有些呢,倒是要在特定的输入的状况下才会出现的。
咱们犯的绝大多数错误是在重现的方式上,做者对重现提出了两条原则:

  • 模拟失败发生的条件,可是不要模拟失败的机理,由于你认为的致使失败的机理极可能是错误的。举个例子,你认为是高并发致使的bug,因而你模拟了高并发的环境,问题重现了,而后你就说是高并发致使的,其实呢,只不过是高并发提升了问题发生的概率。

  • 只影响错误发生的频率,不影响错误发生的方式。其实高并发的环境能够用来提升错误发生的频率,只不过你要在问题重现时,要找到相应的日志信息,而后定位出问题发生的缘由,而不是直接认为就是并发致使的。

 6、不要猜,要观察

 

如今咱们能够重现Bug了,直觉告诉我要在那个地方进行一个字符串编码的转换,且慢,在进行这个武断的尝试以前,先来看看《福尔摩斯》是怎么说的:

主观臆断的人,老是为了套用理论而扭曲事实,而不是用理论来解释事实。

猜想只是为了肯定搜索的重点,可是在开始修复以前要观察确认你的猜想。因此在咱们修改代码以前,仍是看一下发生错误时的日志信息,还能够调试一下代码,在必要的时候打开源码深刻研究一下,肯定确实是字符串编码的问题,再去修改代码。

有人说,那我直接改代码,而后看结果不就知道是否是字符串编码的问题了。固然不是,要知道一个问题的产生多是由多处地方的代码引发的,也许解决完这个字符串编码的问题,还须要解决另外一个问题,才能把整个问题解决呢?若是你在修改前就没进行观察,就会认为此次修改毫无心义,这样整个调试过程就会陷入死局。

记住,调试是一门科学,任何不懂原理就进行的操做都是耍流氓

 7、分而治之

 

系统一般都是由不少个模块组成的,这也就要求咱们要检查不少个模块的日志才可以肯定问题发生的缘由。尤为是如今流行的微服务框架,一笔业务出现问题,你须要到不少个服务的机器上去找日志。

可是,若是你的业务执行是线性的,也就是说若是节点A执行失败,那么节点A以后的也都会执行失败,那么你就能够采用二分法的方式来定位了。要知道,在1到100里猜一个数字,最多也就须要7次。
采用二分法的方式,你将逐步缩小嫌疑的范围,最终找到问题的根因。

固然,若是问题是由多个子问题引发的,那么记住,找到一个,消灭一个,这就是所谓的分而治之

 8、一次只修改一个地方

 

经过观察,你认为你的修改方法会起做用,但若是实际上你修改完代码以后,并无起到任何做用,那么请你立刻改回去,以避免这个修改引入了新的Bug。

 9、作好修改记录

 

把你调试过程当中的操做和结果按顺序所有记录下来,方便你在发现作了那么多处修改依然没有解决问题时,进行回溯,反思本身的操做有没有不对的地方。

 10、反向调试法

 

上面的调试规则,都是从问题出发,去寻找犯错的代码。但有时候反过来也许会更好。

你能够找到最新一个能够正常运行的版本,而后对比如今这个版本和那个版本之间的差异,经过分析改动的代码,来分析是哪块代码致使的问题。

 11、求助他人

 

有时候问题比较紧急,这时候不妨问一下专家,正如《程序员的思惟修炼》中提到的,专家依靠直觉,他们每每会一针见血的给你指出问题的地方。

若是你对系统有必定理解的状况下,能够上软件供应商的官网、谷歌、StackOverflow等网站寻找相关的资料。
在求助的过程当中,你只须要描述问题的症状,若是对方没有要求,那么不要给他讲本身的理论,以避免将对方带入本身的思惟定式。
而在给他人描述问题的同时,你本身可能也会获得启发。

 12、总结

 

以上就是我看完《调试九法》这本书以后总结的一套调试方法论,固然仍是建议你们看一下原著,说不定会有新的收获。不过书中列举了大量的例子,多的让我感受有些冗余,建议你们看的时候,先看每一章节的开头,和每章结尾的小总结,看完以后有不理解的,再去看每章中间的案例。

本书的例子虽然大多数都是关于工程技术的,可是里面的一些想法仍是能够借鉴到生活中去。好比,夫妻吵架了,表面看上去是由于丈夫不肯意洗碗,可是若是你能从全局的角度去观察,你就知道,实际上是由于丈夫情人节时没有给夫人买礼物。

回过头来看这些规则,其实咱们在工做和生活中时不时都会用到,可是咱们以前一直没有一个系统的理论体系,在掌握了书中介绍的调试规则以后,咱们在从此定位错误根源时,会更加层次分明,从容不迫。

最后必须说一句,专业人士应该在开发时就尽量地保证软件的质量,而不是常常靠调试来弥补缺陷。完善而充分的单元测试是保证代码质量的关键。当你发现Bug时,也就说明你的测试用例不全,在修复完Bug以后,要及时补上测试用例。

相关文章
相关标签/搜索