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

第8条:把工作焦点放在最为重要的问题上

许多大型软件系统都含有数量极其众多的bug(有一些是已知的bug,还有一些则尚未发现)。要想高效地进行调试,就必须把应该受到关注的bug与可以忽略的bug明智地区分开。这样做不是为了单纯地缩减事务清单中的未决事务,而是为了帮助我们开发出稳定、易用、可维护而且效率较高的软件,毕竟这才是公司给我们支付薪水的原因。为此,我们要通过事务追踪系统来设定各项事务的优先级(参见第1条),从而使自己能够把工作重心汇聚在优先级较高的那些事务上,并把优先级较低的事务忽略掉。下面给出一些与排定事务优先级有关的建议。
下列几类问题应该赋予较高的优先级。
数据丢失:数据之所以会丢失,可能是因为本身受到了损坏,也可能因为程序在可用性方面遇到了问题。用户把他们的数据托付给你的软件,你就应该维系这份信任感。如果数据丢失,那你就违背了他们的信任,要想再重新获得其信任,是很困难的。
数据安全:这种问题可能会影响软件数据的保密性与完整性,也可能会影响软件所在系统的完整性,或软件所提供服务的可用性。此类问题通常是由于恶意人士对软件进行攻击而引发的,它会给公司带来巨大的资金和名誉损失,此外,还会引来监管机构的注意,或招致勒索。因此,安全问题必须尽快解决。
服务的可用性降低:如果软件是用来提供某种服务的,那么当这项服务无法使用时,公司就会遭受资金损失(有时甚至是以百万元为单位的损失),此外,还会令公司失去信誉、迫使经理在半夜愤怒地打电话给你,而且也会使服务人员忙得不可开交。这些都是应该尽量避免的事情。
使用安全:此类问题可能导致用户伤亡,使财产丢失或受损,或令环境遭到破坏。前面那几类问题所造成的后果,同样有可能出现在这一类问题上面。如果软件可能会在这一方面发生故障,那就应该用一种比这份清单更加严谨的流程来指导你的行动。
程序崩溃或冻结:这可能导致数据丢失或服务下线,而且此类问题可能与底层的安全问题有关。在程序崩溃或失去响应之后,我们通常可以通过事后分析技术(参见第35条)来对其进行调试。这种问题自然不应该赋予较低的优先级。
代码质量(code hygiene):我们要把编译器所给出的警告信息和断言失败信息,以及未处理的异常与内存泄漏等问题清理干净。总之,由于各种低质量的代码会滋生并掩藏一些严重的bug,因此,我们不能允许这类问题继续存在并积累下去(参见第20条)。
下面几类问题的优先级可以设置得低一些。这并不是说它们本身不重要或不值得关注,而是说为了解决更为紧迫的问题,我们可以把这些问题先放在一边。
对遗留事物的支持:能够支持过时的硬件、API或文件格式,这固然是好的,然而从商业角度来看,这样做不会有太大意义,因为使用这些东西的人已经越来越少了。
向后兼容:这一类问题的优先级没有较为明确的结论。如果你在软件的发展过程中,总是把原来的用户抛开不管,那就会失去顾客对你的信赖。有些公司,如Nikon,通过对向后兼容性的维护而获得了良好的口碑,他们的新产品能够与很多代之前的旧产品相兼容,例如,当前的高端Nikon相机,依然那可以使用20世纪70年代的Nikkor(尼克尔)镜头。与之相对,某些成功的软件公司以其决绝的做法而知名,他们毫不犹豫地放弃对旧软件与旧服务的支持。有时我们确实应该停止对旧特性的支持,以便把精力更好地放在未来的发展上面。
美观问题:这些问题很难处理得十分恰当,而且经常容易遭人忽视。例如,就算弹出式帮助信息没有完整地显示出来,客户也不太可能因为这个而抛弃你的产品,可是当你要修复这个小问题的时候,却会发现它处理起来相当麻烦,因为你得根据屏幕的分辨率设置来动态地调整帮助面板的尺寸。
已经有了临时解决方案的问题:有些bug调试起来比较复杂,为了避免在这些问题上面消耗时间,我们可以先给用户提供一种临时的解决方案,以便暂时绕过这些问题。例如,笔者在打开自己家的电视之后,想试着用电视的遥控器去操作媒体播放机,然而却看到了一条提示信息:“请再试一次”。我怀疑这个小问题修复起来相当麻烦,于是厂商就先给出了这个权宜的办法。
很少有人会用到的特性:当软件中的某一个较为奇怪,而且很少有人用到的特性出了问题时,我们与其花时间去解决这个问题,还不如直接把该特性删掉(并把由此引发的一些小状况处理好)。通过收集软件的使用数据,我们可以更为容易地确定出这些罕用的特性,并据此做出决策。
请注意,如果你决定忽略某个优先级比较低的问题,那就应该把这个态度明确地表达出来。你可以在事务追踪系统里面表明自己“不打算解决”该问题,并将其关闭。这样做可以把自己的决策记录下来,使得其他人以后不会再提出类似的问题,从而减轻管理方面的工作量。
要点
并不是所有的问题都值得解决。
修复优先级较低的问题可能会耽误你的时间,使你无法拿出更多时间去处理那些更为紧迫的事务。

时间: 2024-10-28 18:45:51

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

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

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

《Effective Debugging:软件和系统调试的66个有效方法》——第7条:试着用多种工具构建软件,并将其放在不同的环境下执行

第7条:试着用多种工具构建软件,并将其放在不同的环境下执行 有时我们可以通过改变环境来锁定一些难以捕获的bug.例如,我们可以用另外一款编译器来构建这个软件,也可以切换到其他的运行时解释器.虚拟机.中间件.操作系统或CPU架构上.由于那些环境可能会更加严格地检查输入数据,或能通过其结构来凸现程序中的错误(参见第17条),因此可以帮助我们发现原来很难找到的一些bug.如果程序不够稳定.总是发生无法重现的崩溃问题,或移植起来不太顺利,那就应该试着把它放在另外一种环境下进行测试,这使得我们能够使用更为

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

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

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

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

《Effective Debugging:软件和系统调试的66个有效方法》——第10条:高效地重现程序中的问题

第10条:高效地重现程序中的问题 要想高效地调试程序问题,一个关键的因素就是要能够可靠且方便地重现它.这么说有三个理由.首先,如果我们总是能做到只按一个按钮就可以重现问题,那么自然能够专心地去寻找问题的原因,而不用再浪费时间去研究怎样才能把这个问题重现一遍.第二,如果我们可以方便地重现问题,那么也就能够同样方便地把问题描述出来,以寻求外人的帮助(参见第2条).第三,修复错误之后,我们可以把重现问题所需的步骤执行一遍,如果程序这次没有出现故障,那就证明我们对其所做的修复是正确的. 创建短小的范例或

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

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

《Effective Debugging:软件和系统调试的66个有效方法》——第19条:使调试任务自动化

第19条:使调试任务自动化 我们或许会找到很多个与程序错误有关的因素,但是却没有办法轻易推断出究竟哪一个因素才是致使程序出错的真正原因.为了把这个原因找出来,我们可以编写一小段例程或脚本,把有可能使程序出错的所有情况全都搜索一遍.如果待搜索的情况比较多,不便于手工进行搜索,但是却能够通过循环来进行遍历,那么就可以考虑对其加以自动化.例如,如果想遍历的是500个字符,那么可以通过自动化的脚本来实现,然而如果要把用户可能会输入的所有字符串全都尝试一遍,那么采用自动化脚本就不太合适了. 下面举一个例子

《Effective Debugging:软件和系统调试的66个有效方法》——第16条:使用专门的监测及测试设备

第16条:使用专门的监测及测试设备 调试嵌入式系统及系统软件的时候,我们可能要对从硬件到应用程序的整个计算栈进行分析.调试工作一旦深入硬件层面,我们就需要关注电流的微小变化以及磁矩的对齐情况等细节.在大多数情况下,可以通过强大的IDE以及一些追踪软件与日志记录软件来探查这些问题,然而有的时候,就连这些工具也帮不上忙.这通常发生在软件与硬件有所接触的场合,也就是说,虽然你认为你所写的软件能够像预期的那样运作,但是硬件却有着它自己的处理方式.例如,你把正确的数据写入磁盘,再将其读取出来,却发现这些数

《Effective Debugging:软件和系统调试的66个有效方法》——第18条:从自己的桌面计算机上调试那些不太好用的系统

第18条:从自己的桌面计算机上调试那些不太好用的系统 Jenny和Mike在谈论各自的调试经历.Jenny说:"我不喜欢在客户的计算机上面工作,要用的工具都没装,浏览器里也没有我收藏过的书签.这真是太麻烦了.我访问不了自己的文件,计算机上的按键绑定和快捷键,设置得也都不对."Mike惊讶地看着她说:"快捷键?你还有快捷键可用,这都算不错的了.我调试的那台计算机,连键盘都没有!" 如果你在工作时无法使用自己配置好的这台计算机,那么工作效率确实会大幅降低.除了Jenny

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

第20条:开始调试之前与调试完毕之后都要把程序清理干净 如果你要调试的软件有10个地方可能出错,那么这些错误就会有上千种(2的10次方)表现形式,如果有20个地方可能出错,那么表现形式就会高达一百多万种(2的20次方).因此,在调试的时候,应该优先关注当前区域中最容易解决的那些问题.例如: 能够借助工具而找到的问题(参见第51条). 程序在运行时所产生的警告(例如,可恢复的断言失败). 读起来比较费解,而且与你要调试的bug有所关联的那些代码(参见第48条). 标有XXX.FIXME及TODO字