读书笔记-调试九法
去年十一月份, 写过一篇blog, 讲了一些自己平时进行代码调试的观点, 列了21条
上周多看上买了这本书, 花了两小时读完, 做下笔记, 发现很多观点其实是类似的.
这本书是九条原则, 即方法论, 了解和学习, 在实践中遵守, 有利于提升自己调试的效率:)
1. 理解系统
你必须掌握系统的工作原理以及它是如何设计的。在某些情况下,还要知道为什么这样设计。如果你没有理解系统中的某个部分,那么这通常就是出问题的地方。(这不仅仅是“墨菲定律”的问题,如果你不能理解你所设计的系统,你的工作可能会变得一团糟。)
理解是怎么设计的, 机制, 原理, 需求等等, 面对的东西才是一个白盒.
理解系统的基本方法就是阅读手册
手册, 手册, 很多时候, 我们并不能抑制住自己, 去编码, 去调试, 去解决问题, 而忽略了一些重要的东西, 例如: 文档, 我们总以为自己了解一切, 很多时候很诡异的问题查查文档, 才发现, 原来文档有说明:)
或者, 跳过去看源码也是不错的选择
理解了你自己的系统后,还会获得一个额外的好处。当你找到bug时,必须在不破坏其他地方的前提下修复它们。理解系统行为是不破坏系统的第一步。
有个段子, 修了一个, 结果改出了3个bug…只有对系统足够了解, 才能修复而不破坏
人们在调试的时候,通常都不会彻底地阅读系统手册。他们采取跳读的方式,查看他们认为重要的一些章节,但问题的线索可能就隐藏在被略过的那些章节中
有时是这样的, 但是可能时间有限, 这个没法子, 只能在闲时, 多多阅读, 例如, 隔段时间回去浏览一遍
知道什么是正常的
什么是正常的, 什么是异常的?
知道工作流程, 当你尝试寻找bug时,必须知道要查找的路线
不多说, 捞数据, 追数据, 基本功
了解你的工具
要修车, 有趁手的工具才能更高效地解决问题
2. 制造失败
关键是在发生失败的时候要看到它
日志, 现场, 栈等
“当你发现一个故障时该怎么办?” “试着让它再次发生。”
复现
仔细观察你做了什么,然后再做一次,并且记下你做的每个步骤。然后,按照你自己所写的步骤去做,确定这样做确实导致了错误。
复现的步骤
要引发失败, 而不是模拟失败……如果你猜测失败机理,模拟往往不会成功。原因通常有两个,要么你的猜测是错误的;要么测试改变了条件,模拟的系统可以正确工作,或者更糟,发生新的错误,因而分散了你对正在查找的问题的注意力……注意,不要用一个看似完全相同(而实际上不同)的环境来代替并希望看到相同的错误
关注问题本身, 不要错误的转移到了猜测的东西
仔细观察失败
仔细观察失败! 仔细观察! 仔细….
是已修复bug,还是仅仅由于运气好,它不再发生了
你必须确认这一点
永远不要丢掉调试工具
调试工具, 不要当成一次性的工具用完即仍, 可能是错误的
3. 不要想, 而要看
亲眼看到底层的失败是非常重要的。如果你猜测失败是如何发生的,那常常会修复一些根本不是bug的问题。这样的修复不仅不会解决问题,而且还会浪费时间和金钱,甚至会破坏其他地方。请记住,不要这样做。
不要猜测
观察是很难的
的确很难
你必须仔细观察,找到足够多的问题细节,才能调试它……如果你不能留意实际情况发生的全过程,那么你极有可能曲解很多问题。你猜测某个地方出了问题,于是修复它,但实际上错误发生在另一个地方……一定要亲眼看到实际错误是如何发生的。观察往往比猜测能够更快地找到问题。因为猜测虽然看起来是捷径,但这条捷径并不会带你找到问题的根源。
观察而不是猜测
在停下来思考问题之前,对细节的观察应该到什么程度才合适呢?简单的答案是:“一直观察,直到把问题的原因锁定在几种可能性之内。”
海森堡测不准原理: 换言之,测试工具影响了被测系统……。任何插装都可能对系统造成影响,只是程度不同而已
插装, 类似于工具的调试模式, 会影响系统, 所以要注意
4. 分而治之
缩小搜索范围……在查找问题时,“分而治之”实际上是第一条需要使用的原则。事实上,在查找问题时它也是唯一需要应用的规则。所有其他规则都只是帮助你遵循这条规则。分而治之是调试的核心,很多人都知道它,但很多人都没有遵守它,这也正是我写本章的原因。
二分法
确定范围…你必须知道搜索范围,而且必须知道在一端一切正常,而在另一端出现了问题…..从有问题的支路开始查找问题……
原则
如果同时出现了多个问题,当你确实查明了其中的一个问题时,应该立即修复它,然后再查找其他问题……有时修复了一个问题,另一个问题也解决了,两个问题实际上是同一个bug
是有这种情况
5. 一次只改一个地方
使用步枪,而不要用散弹枪……一次只改一个地方……此外,如果你真的看到了错误,应该只修复这个地方
这点很重要
如果你在两个测试之间更改了很多代码,或者为两个测试设置了不同的环境,那么这两个测试将很难对比。它们之间有很多差别并不是由bug引起的,而你必须不断地解释这些差别。你必须把它们之间的差别减少到只与bug有关。排除其他的干扰因素
自从上一次能够正常工作以来你更改了什么……有时,正常的系统和错误的系统之间的区别是由于一项更改造成的。做了更改之后,正常的系统开始出现故障。一种非常有效的办法是找出第一个导致系统出错的版本,尽管这可能需要连续测试原来的版本,直到找到没有故障的版本
大部分问题都是出现在最近一次修改
6. 保持审计跟踪
有时看起来最不起眼的事情实际上却是导致发生bug的关键……因此,你必须记录下每一件事情,不起眼的事情可能会很重要
细节, 步骤
记下你的每步操作、顺序和结果
还是步骤
魔鬼隐藏在细节中
细节
在细节方面,永远都不要相信你的记忆,而要把它写下来。如果你相信你的记忆,将会制造很多麻烦。你会忘掉一些你认为不重要的细节,当然,这些细节将会被证明是非常重要的。你会忘掉一些在你看来不重要的细节,而这些细节对于后来解决另一个不同问题的人可能很重要。除了口头表述以外,你无法将信息传递给别人,而这会浪费所有人的时间。
7. 检查插头
怀疑自己的假设……当我们看到一个问题时,通常在某个特定位置看到了问题,但导致这个问题的原因却在上游或者是一个基础性的问题。系统不具备正确操作的条件,于是出现了非常奇怪的行为。当你看到完全来自另一个世界的问题时,应该停下来,看看你是不是还在地球上
从头开始检查
8. 获得全新观点
寻求帮助: 向别人寻求帮助至少有3个原因(还不算把整个问题甩给别人):获得全新观点、专业知识和经验。而且,人们通常很愿意帮忙,因为这给了他们一个证明自己很聪明的机会
事实上,有时向别人解释问题也会使你有全新的认识,之后你自己就解决了问题
小黄鸭调试法
报告症状, 而不是理论: 让他提出自己的观点。他们的观点可能与你的观点相符,也可能全然不同,而这正是你想要的
9.如果你不修复bug, 它将依然存在
检查问题确实已被修复
bug 从来不会自己消失