第10条:高效地重现程序中的问题
要想高效地调试程序问题,一个关键的因素就是要能够可靠且方便地重现它。这么说有三个理由。首先,如果我们总是能做到只按一个按钮就可以重现问题,那么自然能够专心地去寻找问题的原因,而不用再浪费时间去研究怎样才能把这个问题重现一遍。第二,如果我们可以方便地重现问题,那么也就能够同样方便地把问题描述出来,以寻求外人的帮助(参见第2条)。第三,修复错误之后,我们可以把重现问题所需的步骤执行一遍,如果程序这次没有出现故障,那就证明我们对其所做的修复是正确的。
创建短小的范例或测试用例(test case),以便重现问题,这对于提升调试的效率来说是很有帮助的。我们要遵守最小范例(minimal example)准则,这是一条黄金标准,它要求我们写出可以重现问题的最短范例。还有一条名为SSCCE的准则(参见第1条),可以称为铂金标准,它要求我们不仅要写出短小的(short)范例,而且还要把它写成自足(self-contained)且正确无误(correct,也就是可以编译、可以运行)的范例(example)。有了这种最小范例之后,我们就不用再花时间去研究那些可以忽略的代码分支了,而且我们所要创建及查看的日志文件与追踪信息,也不会变得过于冗长。此外,这种短小的范例,执行起来也要比那些较长的范例更为迅速,这其中一个重要原因在于调试模式所需的开销相当大。
为了缩短范例的长度,可以考虑自上而下与自下而上这两种办法(参见第4条),我们需要根据具体情况来决定应该采用哪种办法。如果代码中的依赖关系比较多,那么自下而上的方法或许会好一些,因为这样可以使我们在刚开始调试的时候,无需面对过多的依赖关系。如果不理解导致问题发生的真正原因,那就应该创建自上而下的测试用例,以帮助我们缩小可能包含错误的代码范围。
自下而上地进行调试时,要先对问题的原因给出一个假设,例如,我们认为是由调用某个API所引发的,然后,构建测试用例来演示这个问题。有一次笔者遇到一个用来处理输入文件的程序,这个程序的代码比较复杂,一共有200行,而且运行得相当缓慢。在查看了程序所调用的系统操作之后,我猜想问题可能与调用tellg函数有关,在读取文件的时候,这个函数可以返回当前位置在文件流中的偏移量。笔者在运行了下面这个简短的代码片段之后,确认自己的假设是正确的(参见第58条),而且这个代码片段还有利于我对该问题的权宜解决方案(也就是使用包装类)进行测试。
例如,上面那条命令可能会输出:
如果你在用旧代码构建软件时想要精确地重现当时的境况,那么别忘了把影响最终发行成果的所有元素全都纳入版本控制系统之下,如编译器、系统程序库、第三方程序库以及构建软件时所用的规范文件(如Makefile或IDE的项目配置文件)。最后,如果你需要把工具及运行时环境所带来的各种变化因素全都去掉,那么可以参考本书第52条的建议。
要点
- 如果能够准确重现程序中的问题,那么我们的调试过程就会得以简化。
- 创建一个简短且自足的范例,以便重现程序中的问题。
- 设法创建一套可以制作副本的执行环境。
- 采用版本控制系统给特定的软件版本打上标记,以便根据此标记来获取与之对应的代码。
文章知识点与官方知识档案匹配,可进一步学习相关知识云原生入门技能树首页概览8932 人正在系统学习中 相关资源:JSky3.5.1.905(企业破解版-最好用web扫描工具的)- 络安全工具类…
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!