《Effective Debugging:软件和系统调试的66个有效方法》——第20条:开始调试之前与调试完毕之后都要把程序清理干净

第20条:开始调试之前与调试完毕之后都要把程序清理干净

如果你要调试的软件有10个地方可能出错,那么这些错误就会有上千种(2的10次方)表现形式,如果有20个地方可能出错,那么表现形式就会高达一百多万种(2的20次方)。因此,在调试的时候,应该优先关注当前区域中最容易解决的那些问题。例如:

  • 能够借助工具而找到的问题(参见第51条)。
  • 程序在运行时所产生的警告(例如,可恢复的断言失败)。
  • 读起来比较费解,而且与你要调试的bug有所关联的那些代码(参见第48条)。
  • 标有XXX、FIXME及TODO字样,或是注释中写有“它应该会……”(should)、“我想它会……”(think)以及“它必定……”(must)等托词的可疑代码。
  • 其他一些已知但是却容易忽略的小bug。

如果连一个相对无错的环境都没有搭建好,就匆忙地去调试那些棘手的问题,那么很可能要遭受惨痛的失败。

有人也可以举出理由来反对这种做法。首先,这种做法与“东西没坏就别修”(If it ain’t broke, don’t fix it)的理念不相符。其次,由于我们可能只是用比较新的写法,修改了系统代码中的某一部分,因此,整个代码的风格或许会显得有些失调。面对这些理由,你需要做出自己的判断。如果你认为清理代码肯定能帮助自己调试某个难以捕获的bug,那就应该承担这种风险;反之,若是代码本身就很脆弱,而且你也明明知道自己能够直接找到这个bug,那就没有必要去冒险清理代码了。

找到并修复程序错误之后,不要急着去做其他事情,因为你还有两项任务没有完成。第一,要在代码中寻找类似的错误,并将其修复(参见第21条)。第二,要把寻找问题时所做的那些修改整理好(参见第40条)。有时我们为了凸现错误效果,可能会临时改动一些代码,这些改动现在应该予以还原。如果你是在版本控制系统里面,单独用一个分支来进行调试的(参见第26条),那么还原起来应该很方便。此外,我们在修改过程中所添加的一些代码,以后有可能还要用到,因此要把这些代码清理干净并提交上去,例如,断言、log语句以及新的调试命令等。

要点

  • 在开始调试重大的bug之前,先要确保代码能够达到一定的整洁程度。
  • 调试完毕之后,要把调试过程中对代码所做的临时改动还原回去,并且要把那些有用的代码提交到代码库。
时间: 2024-09-30 16:10:17

《Effective Debugging:软件和系统调试的66个有效方法》——第20条:开始调试之前与调试完毕之后都要把程序清理干净的相关文章

《Effective Debugging:软件和系统调试的66个有效方法》——导读

前 言 我们在开发软件或对运行软件的系统进行管理的时候,经常会遇到故障.有些故障是因代码问题而引发的编译错误,这种故障可以在短时间内修复:还有一些故障则会使大型系统停机,这将给公司带来每小时数百万的损失(具体货币单位依情况而定).要想成为一名优秀的专业人士,你就必须在发生故障时迅速找出背后的原因并加以修复.这正是调试的意义所在,也是本书所要谈论的主题. 本书是写给有一定经验的开发者看的,而不是一本介绍性质的读物.它假设读者能够理解用各种编程语言所写成的代码片段,并且会使用高级的GUI编程工具以及

《Effective Debugging:软件和系统调试的66个有效方法》一导读

前 言 我们在开发软件或对运行软件的系统进行管理的时候,经常会遇到故障.有些故障是因代码问题而引发的编译错误,这种故障可以在短时间内修复:还有一些故障则会使大型系统停机,这将给公司带来每小时数百万的损失(具体货币单位依情况而定).要想成为一名优秀的专业人士,你就必须在发生故障时迅速找出背后的原因并加以修复.这正是调试的意义所在,也是本书所要谈论的主题. 本书是写给有一定经验的开发者看的,而不是一本介绍性质的读物.它假设读者能够理解用各种编程语言所写成的代码片段,并且会使用高级的GUI编程工具以及

《Effective Debugging:软件和系统调试的66个有效方法》——第11条:修改完代码之后,要能够尽快看到结果

第11条:修改完代码之后,要能够尽快看到结果 调试通常是一种循序渐进的过程.在每一轮中,我们都要花时间去构建并运行软件,而且要看着它发生故障,这些环节会占用很多时间,而且这些时间并没有用来解决软件中的问题.因此,我们要提前进行准备,设法缩短每一轮调试所花费的时间. 首先从软件的构建入手.我们应该能通过一条命令(如make或mvn compile)或一个按键(如F5)把发生故障的软件迅速构建出来.构建过程应该能够记录文件之间的依赖关系,使得我们在修改了某处代码之后只有少数几个文件需要重新编译.能够

《Effective Debugging:软件和系统调试的66个有效方法》一第15条:查看第三方组件的源代码,以了解其用法

第15条:查看第三方组件的源代码,以了解其用法 我们所要调试的代码之所以会出bug,通常并不是由于它使用的第三方程序库或应用程序本身有问题(参见第14条),而是因为它使用这些第三方组件时所采取的方式有误. 这种情况并不令人惊讶,由于这些软件本身是作为黑盒来与你所写的代码进行集成的,因此,你不太可能在它们之间相互协调.对于这类问题来说,有一个很有用的办法,就是去查看第三方程序库.中间件甚至是底层软件的源代码. 首先,如果想查明某个API为什么没有像你所期望的那样运作,或是想查明某条奇怪的错误消息是

《Effective Debugging:软件和系统调试的66个有效方法》一第4条:从具体问题入手向上追查bug,或从高层程序入手向下追查bug

第4条:从具体问题入手向上追查bug,或从高层程序入手向下追查bug 要想确定问题的来源,通常有两种办法.一种是从问题的具体表现入手,向上追查其来源,还有一种是从应用程序或系统的顶层入手,逐步向下探查,直至找到其根源.对于某种类型的问题来说,其中一种方法的效果通常要比另一种更好,但是如果你在采用某个方法时遇到了困境,那么不妨试试另一个方法.如果问题表现得很明确,那我们就应该从发生问题的地方入手,向上追查bug.这可以分成三种情况.第一种情况是程序崩溃.在这种情况下,为了便于排查问题,我们通常可以

《Effective Debugging:软件和系统调试的66个有效方法》一第6条:使用软件自身的调试机制

第6条:使用软件自身的调试机制 程序是一种很复杂的东西,因此它们通常都包含内置的调试机制.(至于怎样给自己正在开发的软件里面添加这样的机制,请参见第40条.)这种机制有很多好处,其中包括:我们可以通过禁用后台执行或多线程执行等特性来简化程序的调试工作.我们可以有选择地执行其中某一部分功能,以便通过测试用例来精确地再现相关的故障.程序可以给我们提供与性能有关的报表及其他信息.程序可以把更多的信息记录在日志文件中.因此,我们应该花一些时间,看看自己要调试的这款软件内置了哪些调试机制.想要了解这些机制

《Effective Debugging:软件和系统调试的66个有效方法》一第8条:把工作焦点放在最为重要的问题上

第8条:把工作焦点放在最为重要的问题上 许多大型软件系统都含有数量极其众多的bug(有一些是已知的bug,还有一些则尚未发现).要想高效地进行调试,就必须把应该受到关注的bug与可以忽略的bug明智地区分开.这样做不是为了单纯地缩减事务清单中的未决事务,而是为了帮助我们开发出稳定.易用.可维护而且效率较高的软件,毕竟这才是公司给我们支付薪水的原因.为此,我们要通过事务追踪系统来设定各项事务的优先级(参见第1条),从而使自己能够把工作重心汇聚在优先级较高的那些事务上,并把优先级较低的事务忽略掉.下

《Effective Debugging:软件和系统调试的66个有效方法》一第9条:相信自己能够把问题调试好

第9条:相信自己能够把问题调试好 软件通常是极其复杂的.机械表的移动机制,仅由100多个部件组成:而整个房屋中的各种器械,其部件总数也只是简单组件的几倍而已.这与典型的软件系统有很大区别,后者很容易就包含成千上万行复杂的代码.我们可以在这两个领域中各举一个较为精密的例子来做比较:A380客机有400万个物理组件,而Linux内核的代码行数则是900万.因此,我们必须在思想上做好充分的准备,才能应对如此复杂的软件.首先,你要确信自己一定能够找到问题并将其修复.你的心理状态会对调试的结果造成影响,专

《Effective Debugging:软件和系统调试的66个有效方法》一第11条:修改完代码之后,要能够尽快看到结果

第11条:修改完代码之后,要能够尽快看到结果 调试通常是一种循序渐进的过程.在每一轮中,我们都要花时间去构建并运行软件,而且要看着它发生故障,这些环节会占用很多时间,而且这些时间并没有用来解决软件中的问题.因此,我们要提前进行准备,设法缩短每一轮调试所花费的时间.首先从软件的构建入手.我们应该能通过一条命令(如make或mvn compile)或一个按键(如F5)把发生故障的软件迅速构建出来.构建过程应该能够记录文件之间的依赖关系,使得我们在修改了某处代码之后只有少数几个文件需要重新编译.能够达