去年十一月份, 写过一篇blog, 讲了一些自己平时进行代码调试的观点, 列了21条

关于代码调试de那些事

上周多看上买了这本书, 花了两小时读完, 做下笔记, 发现很多观点其实是类似的.

这本书是九条原则, 即方法论, 了解和学习, 在实践中遵守, 有利于提升自己调试的效率:)

debug-rules

1. 理解系统

你必须掌握系统的工作原理以及它是如何设计的。在某些情况下,还要知道为什么这样设计。如果你没有理解系统中的某个部分,那么这通常就是出问题的地方。(这不仅仅是“墨菲定律”的问题,如果你不能理解你所设计的系统,你的工作可能会变得一团糟。)

理解是怎么设计的, 机制, 原理, 需求等等, 面对的东西才是一个白盒.

理解系统的基本方法就是阅读手册

手册, 手册, 很多时候, 我们并不能抑制住自己, 去编码, 去调试, 去解决问题, 而忽略了一些重要的东西, 例如: 文档, 我们总以为自己了解一切, 很多时候很诡异的问题查查文档, 才发现, 原来文档有说明:)

或者, 跳过去看源码也是不错的选择

理解了你自己的系统后,还会获得一个额外的好处。当你找到bug时,必须在不破坏其他地方的前提下修复它们。理解系统行为是不破坏系统的第一步。

有个段子, 修了一个, 结果改出了3个bug...只有对系统足够了解, 才能修复而不破坏

人们在调试的时候,通常都不会彻底地阅读系统手册。他们采取跳读的方式,查看他们认为重要的一些章节,但问题的线索可能就隐藏在被略过的那些章节中

有时是这样的, 但是可能时间有限, 这个没法子, 只能在闲时, 多多阅读, 例如, 隔段时间回去浏览一遍

知道什么是正常的

什么是正常的, 什么是异常的?

知道工作流程, 当你尝试寻找bug时,必须知道要查找的路线

不多说, 捞数据, 追数据, 基本功

了解你的工具

要修车, 有趁手的工具才能更高效地解决问题

2. 制造失败

关键是在发生失败的时候要看到它

日志, 现场, 栈等

“当你发现一个故障时该怎么办?” “试着让它再次发生。”

复现

仔细观察你做了什么,然后再做一次,并且记下你做的每个步骤。然后,按照你自己所写的步骤去做,确定这样做确实导致了错误。

复现的步骤

要引发失败, 而不是模拟失败......如果你猜测失败机理,模拟往往不会成功。原因通常有两个,要么你的猜测是错误的;要么测试改变了条件,模拟的系统可以正确工作,或者更糟,发生新的错误,因而分散了你对正在查找的问题的注意力......注意,不要用一个看似完全相同(而实际上不同)的环境来代替并希望看到相同的错误

关注问题本身, 不要错误的转移到了猜测的东西

仔细观察失败

仔细观察失败! 仔细观察! 仔细....

是已修复bug,还是仅仅由于运气好,它不再发生了

你必须确认这一点

永远不要丢掉调试工具

调试工具, 不要当成一次性的工具用完即仍, 可能是错误的

3. 不要想, 而要看

亲眼看到底层的失败是非常重要的。如果你猜测失败是如何发生的,那常常会修复一些根本不是bug的问题。这样的修复不仅不会解决问题,而且还会浪费时间和金钱,甚至会破坏其他地方。请记住,不要这样做。

不要猜测

观察是很难的

的确很难

你必须仔细观察,找到足够多的问题细节,才能调试它......如果你不能留意实际情况发生的全过程,那么你极有可能曲解很多问题。你猜测某个地方出了问题,于是修复它,但实际上错误发生在另一个地方......一定要亲眼看到实际错误是如何发生的。观察往往比猜测能够更快地找到问题。因为猜测虽然看起来是捷径,但这条捷径并不会带你找到问题的根源。

观察而不是猜测

在停下来思考问题之前,对细节的观察应该到什么程度才合适呢?简单的答案是:“一直观察,直到把问题的原因锁定在几种可能性之内。”

海森堡测不准原理: 换言之,测试工具影响了被测系统......。任何插装都可能对系统造成影响,只是程度不同而已

插装, 类似于工具的调试模式, 会影响系统, 所以要注意

4. 分而治之

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

二分法

确定范围...你必须知道搜索范围,而且必须知道在一端一切正常,而在另一端出现了问题.....从有问题的支路开始查找问题......

原则

如果同时出现了多个问题,当你确实查明了其中的一个问题时,应该立即修复它,然后再查找其他问题......有时修复了一个问题,另一个问题也解决了,两个问题实际上是同一个bug

是有这种情况

5. 一次只改一个地方

使用步枪,而不要用散弹枪......一次只改一个地方......此外,如果你真的看到了错误,应该只修复这个地方

这点很重要

如果你在两个测试之间更改了很多代码,或者为两个测试设置了不同的环境,那么这两个测试将很难对比。它们之间有很多差别并不是由bug引起的,而你必须不断地解释这些差别。你必须把它们之间的差别减少到只与bug有关。排除其他的干扰因素

自从上一次能够正常工作以来你更改了什么......有时,正常的系统和错误的系统之间的区别是由于一项更改造成的。做了更改之后,正常的系统开始出现故障。一种非常有效的办法是找出第一个导致系统出错的版本,尽管这可能需要连续测试原来的版本,直到找到没有故障的版本

大部分问题都是出现在最近一次修改

6. 保持审计跟踪

有时看起来最不起眼的事情实际上却是导致发生bug的关键......因此,你必须记录下每一件事情,不起眼的事情可能会很重要

细节, 步骤

记下你的每步操作、顺序和结果

还是步骤

魔鬼隐藏在细节中

细节

在细节方面,永远都不要相信你的记忆,而要把它写下来。如果你相信你的记忆,将会制造很多麻烦。你会忘掉一些你认为不重要的细节,当然,这些细节将会被证明是非常重要的。你会忘掉一些在你看来不重要的细节,而这些细节对于后来解决另一个不同问题的人可能很重要。除了口头表述以外,你无法将信息传递给别人,而这会浪费所有人的时间。

7. 检查插头

怀疑自己的假设......当我们看到一个问题时,通常在某个特定位置看到了问题,但导致这个问题的原因却在上游或者是一个基础性的问题。系统不具备正确操作的条件,于是出现了非常奇怪的行为。当你看到完全来自另一个世界的问题时,应该停下来,看看你是不是还在地球上

从头开始检查

8. 获得全新观点

寻求帮助: 向别人寻求帮助至少有3个原因(还不算把整个问题甩给别人):获得全新观点、专业知识和经验。而且,人们通常很愿意帮忙,因为这给了他们一个证明自己很聪明的机会

事实上,有时向别人解释问题也会使你有全新的认识,之后你自己就解决了问题

小黄鸭调试法

报告症状, 而不是理论: 让他提出自己的观点。他们的观点可能与你的观点相符,也可能全然不同,而这正是你想要的

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

检查问题确实已被修复

bug 从来不会自己消失