介绍

译者序
有人说调试是一门艺术,这不无道理,但本书作者认为它并不仅仅是艺术,更多的是科学,调试人员也不仅仅是艺术家,还是科学工作者。遵循本书所讲的9条规则,就可以把调试艺术转化为科学。
本书翻译到一半的时候,我已经钦佩不已。它绝对称得上调试领域的经典之作,但显然,在某种程度上它并没有引起国内业界的注意。常言道“千里马常有,而伯乐不常有”,虽然用千里马来形容一本书多少有些不恰当,但我确实觉得本书被埋没了,我想我们应该感谢人民邮电出版社图灵公司,把这样一本好书发掘出来,让国人有机会分享这位拥有二十多年实践经验的调试高手的知识和经验。
把书写厚了容易,写薄了却难,我想这一点大家都会认同。作者正是用这么薄薄的一本 书讲述了适用于软件、硬件、工程领域的9条基本调试规则。这些规则甚至还适用于我们的 日常生活,例如解决汽车和房屋问题。仔细揣摩,我们会学到不少生活知识,这也是阅读本 书的一个额外的好处。

这是一本调试领域权威的书籍,虽然其中的内容可能有些过时,但其中的思想是恒久不变的。

这是一本超薄的小书,只有短短的 142 页,可以说阅读起来毫无压力。

调试规则

  • 规则1 理解系统
  • 规则2 制造失败
  • 规则3 不要想,而要看
  • 规则4 分而治之
  • 规则5 一次只改一个地方
  • 规则6 保持审计跟踪
  • 规则7 检查插头
  • 规则8 获得全新观点
  • 规则9 如果你不修复bug,它将依然存在

书中给出的调试规则,可以快速地帮助你获得调试的整体认知,从而系统地解决问题。

书中的其他所有内容都是对于这些规则的解释与阐述,帮助你理解与应用这些规则。

理解系统

当你尝试寻找bug时,必须知道要查找的路线。开始时,你需要猜测在哪里把系统分隔开,以便隔离问题,这种猜测完全取决于你对系统功能划分的了解。你至少要大体上知道所有的模块和接口都是做什么的。如果你的烤箱把面包烤焦了,你需要知道哪个黑色旋钮是用来控制烤制时间的。

我在 Unity 接入 Android、iOS SDK 时对这一点深有感悟,只有在完全理解了不同系统之间是如何交互的,才能正确地编写桥接代码接入 SDK,才能在出 Bug 的时候正确地确定查找方向,否则就跟无头苍蝇一样乱飞。

制造失败

如果可以查找到 Bug 复现的条件并控制这些条件稳定复现 Bug,那么这就意味着很容易修复它。

印象最深刻的是项目在升级到 Unity 2017.2 版本后出现打开关闭聊天界面时会随机崩溃,由于 Bug 并不是必现,处理起来较为困难。因此建议同事采用制造失败的方法找到 Bug 并制作了一个复现 Bug 最简单的工程:只要打开工程运行后几秒内 Unity 就会崩溃。将工程以 Bug 形式提交给 Unity,过了一段时间后 Bug 终于在 Unity 2017.3 中反馈修复成功。

不要想,而要看

如果你不能留意实际情况发生的全过程,那么你极有可能曲解很多问题。你猜测某个地方出了问题,于是修复它,但实际上错误发生在另一个地方。由于你没有看到一个字节发生了改变,导致用错误的参数调用了一个子例程,或者一个队列溢出,而你却去修复了一个完全没有发生错误的地方。这样,你不仅没有修复问题,而且还可能改变了时序,因此把问题隐藏起来了,这会使你误认为已修复问题。更糟的是,你可能会破坏其他地方。

一定要明确,猜测很难解决问题,只有观察到问题才能真正修复问题。

“不要想,而要看”并不意味着不能做任何猜想。事实上猜测是好事,特别是当你理解了系统之后。你的猜测可能很接近事实,但猜测只是为了确定搜索的重点。在尝试修复问题 之前,仍需要再次看到失败,以便确认你的猜测是正确的。

猜测是用来渐近地确定搜索范围,但是依然无法替代观察。

分而治之

你可能已经注意到,在查找问题时,“分而治之”实际上是第一条需要使用的原则。事实上,在查找问题时它也是唯一需要应用的规则。所有其他规则都只是帮助你遵循这条规则。分而治之是调试的核心,很多人都知道它,但很多人都没有遵守它,这也正是我写本章的原因。

缩小查找问题的范围很重要,可以避免大量无用的工作。

有时候你发现解决问题的时候完全没有思路,如果你使用了版本控制,那么恭喜你,可以快速地回滚到正确的版本然后进行二分查找。Git 甚至内置了 bisect 这个二分查找命令。

一次只改一个地方

我们在生活中要有一点先见之明。如果你所做的更改没有起到预期的作用,那么就把它改回来。它们可能会产生无法预料的影响。

有时候可能会因为测试过程较长而偷懒同时改动几个地方。但这么做很容易引入另外的错误,要避免这种“节省时间”的捷径,因为这有可能会浪费大量的时间。

保持审计跟踪

魔鬼隐藏在细节中
假设你记录你的食物过敏日志,但你只记下了吃过的食物,而没有记录你突发荨麻疹,那么医生也将束手无策。关键是在记录调试跟踪或日志的同时,也要把那些没在日志中出现的所有条件和症状记录下来。

建议在记录 Bug 时将相关的日志也保留下来,在搜索时不断尝试日志中不同的关键词,这个方法帮了我大忙,解决了很多之前忽视的细节导致的问题。

检查插头

永远不要相信自己的假设,特别是当这些假设在一些无法解释的问题中是核心因素的时候。应该问自己一个古老的、看似愚蠢的问题:“插头插上了吗?”虽然这个问题看上去很愚蠢,但它经常发生。你可能费尽周折检查调制解调器软件为什么不工作了,事实证明你只是把电话线踢掉了。

如果出现问题了,建议从头开始检查,因为很有可能不是某个地方出 Bug 了,而是配置之类的出错了。

获得全新观点

有时会卡住,陷入僵局,这时你需要其他人的观点。

报告症状,而不是理论
之所以要从别人那里获得全新的观点,就是因为你的理论起不到任何作用。如果你找了一个人,把你的理论告诉他,那么也会把他拉到你原来的思维定式中。同时,你很有可能会把一些需要让他知道的关键细节隐藏起来了,因为你自己有偏见,认为这些细节不重要。

这一点真是太重要了,如果想要获得不同的观点,一定不要报告自己的理论。

如果你不修复bug,它将依然存在

检查问题确实已被修复 如果你遵守了“制造失败”这条规则,就会知道如何验证你确实已经修复了问题。那么应该立即验证!不要假设问题已被修复,而要测试它。无论问题和修复看起来多么明显,你都无法保证修复是有效的,直到做了测试。

这就是字面意思,如果你在做了什么事情之后导致 Bug 消失了,如果你没验证,其实你并没有真正地修复它。

一定要从根本上解决问题,否则问题会在它根本不应该出现的时候出现,这就是墨菲定律。

评价

这本书在豆瓣的评价非常高,达到了 9.0 分,这在技术书籍中是非常少见的高分。

推荐先去豆瓣看一下书籍目录,里面列出了大量工作中会遇到的问题,看看你自己会不会感兴趣。

也建议仔细阅读下豆瓣读者的评论,写得都非常真实。

购买方式

不得不说,这本书已经绝版了,如果想买纸质版本,只能去二手网站淘了。但是二手价格实在是太贵了,在孔夫子二手书网站上大概要 ¥200。

但是好在还有电子版本可以购买。之前在阅读 Kindle mobi 版本时,发现经过重排后整本书会有五百多页,在不同的设备上页码与总页数都会发生变化(因为 mobi 格式会重新排板),而且在阅读时由于缺失了样式,很难找到重点。建议购买 PDF 版本,对比 mobi 版本来说,完整地保留了书籍原有的样式,看起来更赏心悦目。

网上虽然有盗版 PDF 下载,但那是扫描版的,字非常不清楚,而且还无法搜索。而只需要花费 ¥12 就可以在图灵社区官网购买到正版文字版 PDF:

如果你还是很喜欢阅读纸质版,可以在购买图灵的 PDF 版本后到淘宝上找店家打印成纸质版,甚至还可以要求店家增加彩色封皮、去除书页下方的数字水印。

参考资料

书籍的英文官方网站