他山之石:InfoQ采访Spinellis---如何有效地调试软件
Diomidis Spinellis是《代码阅读与代码质量》一书的作者。在GOTO阿姆斯特丹2016大会上,他就如何有效地调试软件和预防错误做了演讲。InfoQ采访了Spinellis,内容涉及发现和修复软件中的错误、软件调试的原则、如何提高调试效率、如何编写出不怎么需要调试的代码以及管理人员如何为错误预防和处理提供支持。
InfoQ:是什么让软件错误的发现和修复如此困难?
Diomidis Spinellis:如果你认为编写代码困难,那就尝试下代码调试吧。你编写了一个新的函数或方法,并加上一些语句形成某个只是貌似正确的东西。当你调试一个程序的时候,你要面对数千或数百万行貌似正确的代码,并设法找出其中的错误。这必定要困难许多。然后,你还要应对各种系统和层次之间的复杂交互、每秒执行数十亿次的CPU指令、难以再现的Bug以及来自生产环境系统的压力。
而且,课堂上很少教调试;从一切可能出错的东西辛苦得来的经验很难压缩到一次演讲中。此外,由于系统失败的方式各不相同,你必须不断地改进和调整你所用的工具和方法。你可以从观察开始,继之以数据分析,然后做一些试验,最后推断出Bug的原因。没有什么标准的初学者技能。
InfoQ:软件调试有什么一般原则吗?
Spinellis:很遗憾,由于软件会出现各种难以想象的错误情况,我不认为有什么可以在软件调试过程中遵循的一般原则。退而求其次,我归纳出了三大类方法:
高级策略,比如由故障特征推断出原因,或者确保某些代码满足了其前提条件;
方法和实践,比如确保Bug可以有效地再现,或者着重突出故障的影响;
通用工具,比如Unix命令行工具、跟踪(考虑下strace、dtrace和systemtap)工具和版本控制系统。
InfoQ:程序员做什么能够提高调试效率?
Spinellis:首先要为调试成功做好准备。让自己相信问题将会得到解决,留出足够的时间用于调试,不要分心,要坚持不懈,必要的时候,留待第二天解决。重要的是,要不断地在环境、工具和知识上投入。购买高效工作所需的软件和硬件。例如,如果软件生成大量的调试日志文件,你就应该有足够的磁盘空间、CPU处理能力和带宽,以便可以高效地处理它们。在调试的过程中,你很容易遇到千奇百怪的问题,因此,花些精力管理和优化自己的环境和工具配置。这包括按键绑定、别名、辅助脚本、快捷方式和工具配置;所有这些都可以显著地提高调试生产力。
InfoQ:有什么技术或方法可以编写出不怎么需要调试的代码吗?
Spinellis:当然!编写可维护的代码——可读、稳定、易于分析和修改的代码——带来的Bug也比较少。此外,像单元测试、代码审查这样的方法以及使用断言都有助于最小化进入生产环境的错误。
在设计时使用高级抽象(例如使用一个框架的算法或容器数据结构,而不是选择自己开发一种方案)可以减少代码和错误。另外,让程序易于调试也很重要。这包括为详细地记录日志提供便利,当出现内部错误时报告丰富的上下文信息,并将问题及崩溃的详细信息发送到一个中央存储库。
InfoQ:管理人员如何为组织里的错误预防和处理提供支持?
Spinellis:设定基本的过程有助于确保软件错误不会失控。部署并采用一个问题跟踪系统,用它把要处理的问题分类并排定优先级。将软件变更恰当地记录在进一个运作良好的版本管理系统里,并将它与问题跟踪系统联系起来;我经常仅仅通过仔细研究一个文件的历史和变更就修复了Bug。在软件建设方面,推广单元测试的应用,把软件的构建性能分析、静态分析和动态分析包含进来,并维护一个快速、精益、均衡的构建-测试周期。这有助于帮助开发人员尽早捕获Bug,并迅速修复。最后,在运维方面,逐步部署软件,允许新旧版本对比,努力确保所使用的工具和所部署的环境的多样性,并有组织地升级工具和库。
转自:http://lf.lnu.edu.cn/detail.jsp?id=55243