绿林网

《调试九法》经典读后感有感

《调试九法》经典读后感有感

《调试九法》是一本由David J.Agans著作,人民邮电出版社出版的平装图书,本书定价:35.00元,页数:142,特精心收集的读后感,希望对大家能有帮助。

《调试九法》读后感(一):我就不信这个软件没bug

书里面讲的案例都很有共鸣,其实调试方法软硬件是通用的. 就拿我一直在用的windows 10 insider Preview 来说吧. 我明知道这是一个埋伏着各种bug的系统, 但仍然是用的乐此不疲. windows 新系统现每个月至少更新一次, 频繁的时候三五天就更新一版(MIUI开发版也差不多, 正常情况下, 工作日周一到周四一周更新四次), 每次都要下载一个2.6G左右的大包, 光下载就得半小时一小时的. 在早期的升级包下载时, 总是很慢, 甚至有好多次无法下载成100%就断了, 这时候, 就出现了错误提示, 但提供的错误码在KB上找到的信息都没用, 只能自己摸索, 基本上就是网络链接错误, 我记得去年有一个版本, 我连续更新了十几次都下载不了完整的更新包, 最后我是挂着VPN下载完成的. 终于 Windows 10出了正式版之后, 这个问题得到了改善, 但最近最近半年来改进的有些矫枉过正了, 每次我发现打开网页非常卡, 甚至打开视频网站都播放不畅的时候, 我就预感到 windows insider新版在更新了, 去Update一查, 果然, 系统正在一条道跑到黑的全速下载, 根本不管你正常上网的死活, 而且还不能暂停, 有时候我实在有事, 要联网, 又不想重启, 在设置里面把 fast 改成 slow , 禁用了windows update 服务,才得以喘息. 还有一个版本,每次更新都是到76%就停住了, 而且还没有任何提示,我睡一觉等着它以为 windows 自己能扛过去,但终究是迈不过这道坎, 试了好几次, 根据我自己的猜测, 每次都修改一处, 可能是杀毒软件, 或者我个人文件太多了, 导致处理缓慢, 最后还是没猜到, 最后忍无可忍, 重新安装了一遍, 后来在论坛里面发现, 是因为 non-unicode 设置的问题, 如果改回en-us就能顺利升级了, 而这个bug, 在微软官方的已知bug列表里面是没有的, 折磨了我三天. 当然, 这个bug在后来的版本里面修复了. 上几个版本还出现了不兼容腾讯软件的问题, 游戏全面不能玩了, 甚至QQ都用不了了, 看起来像是腾讯公司写了一堆病毒, 在新版windows里面失效了. 而且巧的是, 迅雷也用不了, 会在马上下载到100%之前准时崩溃, 所有任务都失败, 这些软件公司都干了些什么啊. 说到游戏, 有个版本对 Xbox 手柄的支持出了问题, 摇杆一摇就崩溃, 方向键就没问题, 后来那一个多星期我是用方向键跑完了好几把赛车. 每次发现bug, 自己能找到bug触发的准确条件, 像是发现了宝一样, 兴奋至极, 当然, 如果我自己能把这些 bug 都修复了, 那就更完美了. 在论坛里面大家有时候都不是在问, 新的测试版有什么新特性, 而是再问, 新版有什么新 Bug 吗? 为什么成天抱着找 Bug 的想法在用软件. 也许是强迫症, 也可能是因为真的很闲吧.

《调试九法》读后感(二):程序调试界的独孤九剑 - 《调试九法》读书笔记

一、调试九大规则

1. 理解系统

2. 制造失败

3. 不要想,而要看

4. 分而治之

5. 一次只改一个地方

6. 保持审计跟踪

7. 检查插头

8. 获得全新观点

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

二、九大规则的具体解释

1. 理解系统

简单来说,就是要熟悉业务。这条规则最重要。

更具体点,你必须知道系统的工作原理以及它是如何设计的,某些情况下,还要知道为什么这样设计。

你需要做到以下:

- 阅读手册。阅读相关文档

- 仔细阅读每个细节

- 掌握基础知识

- 了解工作流程。知道所有的模块和接口都是做什么

- 了解工具。花时间学习与工具的一切,同时要了解工具的局限性

- 查阅细节。不应盲目相信自己的记忆,养成良好的查阅习惯

2. 制造失败

简单来说,就是复现 bug 。

试着让 bug 重现有一下3个原因:

- 可以观察它

- 可以专心查找原因。准确地知道在什么条件发生,有助于集中精力查找原因

- 可以验证是否已修复问题

怎么制造失败(重现):

- 从头开始。试着从一个已知的状态出发

- 引发失败。尽量自动化

- 但不要模拟失败。要模拟导致失败的条件,而不是模拟识别机制本身

- 处理间歇性失败(偶现 bug )。改变能控制的条件,直到失败发生

- 记录每件事。让系统尽可能多的输出信息,并记录到日志

- 如果得到足够多的信息,需要确定哪些与 bug 有关

- 用好调试工具

3. 不要想,而要看

凭空想象,问题可能有几千条原因,而实际的原因只有去看了才能发现。

- 观察失败。仅靠猜测某个地方出了问题就修复它,不仅没修复问题还可能把真正问题隐藏起来,还误以为修复了问题

- 查看细节。一直观察,直到把问题原因锁定在几种可能之内

- 植入插装工具。其实就是用工具调试,并记录日志

- 不要害怕深入研究

- 注意海森堡效应。测试工具可能影响被测系统

- 猜测只是为了确定搜索的重点。但不要过分依赖猜测以免被引入歧途

4. 分而治之

其实就是排除法,逐步逼近,这是调试的核心

- 确定问题范围

- 逐步逼近缩小搜索范围

- 从有问题的一边开始搜索。不要把精力花费在没问题的地方

- 修复探索过程中的已知bug

- 消除干扰因素

5. 一次只改一个地方

不要乱改,为验证问题,一次只改一个地方

- 隔离关键因素,别改出了其它问题

- 一次只改一个测试

- 与正常情况进行比较。这样才能发现问题所在

- 确定自从上一次正常工作以来你改变了什么

6. 保持审计跟踪

- 记下你所做的事、做事的顺序,以及发生的结果,写下来

- 任何细节都可能是重要的

- 把时间关联到一起

- 检查代码关联工具看是否是那一次修改引入了 bug

- 把 bug 修复过程记录下来,形成自己的 bug 修复集

7. 检查插头

一些显而易见的假设往往是错误的。

- 质疑你的假设

- 从问题开始观察

- 对工具进行测试,工具本身也可能有 bug

8. 获得全新观点

要想重新理清一个案子的头绪,最好的方法就是把它讲给别人听。 - 福尔摩斯

如果问题没有头绪,不妨休息下,听听别人的看法

- 寻求帮助。人们通常很愿意帮忙,因为这给了他们一个证明自己很聪明的机会

- 向别人解释问题会让你对问题有全新的认识。小黄鸭调试法

- 咨询专家,获取专业知识

- 借鉴别人的经验。如果有人出现过类似问题,不妨找他们了解下

- 放下面子。bug 发生了,以除掉 bug 为自豪,而不要非得已自己除掉 bug 才为自豪

- 寻求帮助时,报告问题发生现象,而不是自己的猜测,以免误导他人

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

- 验证问题确实已被修复。不要假设它已被修复,要测试它

- 验证确实是你的修复措施解决了问题。而不是自己在修复过程中误操作

- bug 从来不会自动消失。也许当时复现不了,当它终会出现

- 从根本上解决问题

- 对过程进行修复

三、当你的用户发现了 bug

实际上很多时候 bug 是通过用户发现的,他不一定了解这些专业知识

- 不能全信用户的观点

- 多依赖日志

- 要让发生问题的用户告诉你他们做了什么

- 不要假设用户如何使用你的产品。对所有的事情都要进行确认

- 如果问题再次复现了,让用户联系你

《调试九法》读后感(三):每天看看作者遇到的各种疑难杂症,收获满满的心灵慰藉

掌握基础知识:必须掌握系统的工作原理以及它是如何设计的。在某些情况下,还要知道为什么这样设计。如果你没有理解系统中的某个部分,那么这通常就是出问题的地方。 阅读手册:我们应该首先阅读手册,而不是等到所有办法都不管用之后才去读它。而且要逐字阅读整个手册。应用书名通常不仅描述了系统是如何工作的,而且专门给出先前已发生过的问题。常见错误的警告具有难以置信的价值。 了解工作流程:当你尝试寻找bug时,必须知道要查找的路线。开始时,需要猜测在哪里把系统分隔开,以便隔离问题。 了解工具:通常,查明系统行为的关键,是你的调试器设置得怎样,或者是否正确触发了分析器。越是精通工具,越容易查明系统中发生了什么事情。同时必须了解工具的局限性。走查源码可以显示逻辑错误,单无法显示时序和多线程问题。

重现问题的好处:我们可以观察它;可以专心查找原因(准确知道问题在什么条件下回发生,有助于集中精力查找原因);可以判断是否已修复问题。 调试故障的时候,如果需要手工执行很多步骤,那么是这个过程自动化会很有帮助。 引发失败和模拟失败两者之间存在非常大的差别。模拟那些导致失败发生的条件而不是模拟失败机理本身。 间歇性失败的关键问题在于,并没有完全弄清楚失败是如何发生的。你知道做了什么,单并不知道完整的、准确的条件。还要其他没注意到或无法控制的因素,例如初始条件、输入数据、时序、外部过程、电子噪声、温度、震动、网络流量等。如果你能控制所有这些条件,那么久可以一直使错误发生。一旦想到了有哪些条件可能影响你的系统,必须大量尝试与这些条件相符的各种形式。记录没见事情,并找到间歇性bug的特征。是已修复bug,还是仅仅由于运气好,它不再发生了,这样需要运行足够多的测试样本,来做统计。

亲眼看到底层失败是非常重要的。如果猜测失败是如何发生的,那常常会修复一些根本不是bug的问题。 观察就算不是永远也是常常比你想象的要复杂得多。 在停下来思考问题之前,对细节的观察应该到什么程度才合适呢?简单的答案是:一直观察,直到把问题的原因锁定在几种可能性之内。

通过反复地把问题分成好的一半和坏的一半,来缩小搜索范围,然后进一步研究有问题的那一半。

隔离关键因素:如果你在检查日照时间的影响,就不要改变灌溉方案。 用双手抓住黄铜杆:如果你在不知道具体发生了什么问题的情况下就试图去修理核潜艇,肯恩购汇引发一次水下的切尔诺贝利爆炸。 确定自从上一次正常工作以来你改变了什么地方。

有事看起来最不起眼的事情却是导致发生bug的关键,在测试人员看来不重要的细节可能对于bug修复人员很重要。因此,你必须记录下每一件事情。 要记下你的每部操作、顺序和结果。而且要知道,任何细节都可能是重要的。并且要把事件关联到一起。

质疑你的假设。是不是燃气用完了?插头是否已插好?对工具进行测试:燃料油表是否被黏住了?量表是不是没电了?

寻求帮助:获得全新观点(有事想别人解释问题,也会是你有全新的认识;其他人会从一个无偏见的角度看问题);询问专家:咨询专家来了解需要快速掌握哪些知识,专家知道查找问题的大致路线图;借鉴别人的经验:周围的人以前见过类似的情况,有些系统给提供了故障维修指南。 到哪里寻求帮助:同时;wiki;供应商; 报告症状,而不是结论:在寻求帮助时,描述观察到的一切,以及条件,告诉什么是间歇发生,什么事情不是。但不要告诉他认为问题的原因是什么。及时有些不是十分肯定的事,也可以提出来。

当你认为已经修复了一个设计问题时,取消这个修复,确定系统再次失败。然后再应用这个修复,再次验证问题已修复。 如果一个硬件设备失败了,不要以为它是无缘无故坏掉了。如果在某种条件下有零件会损坏,那么更换这个零件也只能是为你换来很短的时间,然后新的零件也会损坏。你必须找到真正的失败之处。 对过程进行修复:不要只是擦掉地上的油,而要纠正设计机器的方式。

《调试九法》读后感(四):调试是个技术活

一般当工程师把一个东西称为艺术甚至玄学的时候,说明这个东西难度很大,没有太多规律可以遵循,调试就属于此列。几乎每个程序员都有被bug搞到死去活来的经验,有时候颠来倒去,问题似乎解决了,但也不知道为什么,就把它当作不可解释的玄学现象,最烦人的一种bug是偶尔出现难以复现的,学名海森堡bug。

不过毕竟软件还是属于科学技术的范畴,调试也应当是门技术活。《调试九法》是一本少见的讲调试技术的书,九个普遍性的原则不仅适用于软硬件开发维护,甚至还能运用到日常生活,为了找到这本书我也是费了点神,幸好图灵社区还有正版的电子书卖。

说实话,作者举的很多例子偏硬件,所以理解起来有点隔膜,但是九个原则确实很实用,在我以前的开发调试经历中可能也不自觉的总结过一些,但是看了本书,还是有拿到武功心法的感觉。看过之后,下面再把九个原则遍历一下,加深理解。

1 理解系统

这是最重要的一条原则,要分析bug,自然要理解系统是如何运作的,这就需要学习掌握一些基本原理,对具体的类库、工具、技术都需要认真的去读相关文档。我最近几年才养成了认真读官方文档的习惯,搜索引擎的发达,使得我们养成了面向google编程的习惯,面对问题,总是想一蹴而就的解决,结果往往是走了很多弯路,因为舍不得花时间看路标。本书还特别强调“逐字逐句”读手册,简直是对浮躁的人当头棒喝。不理解系统就开始调试和不理解原理就写代码是一脉相承的,俗称“面向巧合编程”。

2 制造失败

这条原则讲的是复现bug的重要性与方法,一个bug,肯定是在某个特定的条件下发生的,抽丝剥茧找到这个特定的条件,就成功了一半。以我的硬件维护经验来看,发现bug的人如果能详细的记录整个过程是非常有帮助的。有很多bug出现的条件比较苛刻,所以程序员的口头禅之一就是“在我这里没问题啊”。针对这类bug,首先最好能找到模拟方法,比如加快软件运行交互的速度,进行压力测试等,其次就是在软件内部能有详细合理的bug记录机制,便于从内部找到复现的条件。

3 不要想,而要看

这一条强调的是观测的重要性,面对现实比胡思乱想重要。语言影响思考,所以遇到bug的口头禅应该是“我看看“而不是”我猜可能是因为“。我们应该想尽办法去看清楚出bug的细节,所以成熟的程序中都应该有用于调试的基础设施,个人经验至少日志是必不可少的,初级程序员习惯于完全靠打断点调试,问题是断点本身会改变程序执行的流程(尤其是多线程的情况下)。当然,猜测依然是有用的,可以帮我们缩小观察的范围,或者至少拟定一个观察的优先级,这样经验就能发挥作用,但是不管怎样,经验不能替代观测。

4 分而治之

二分查找法可以把查找的时间复杂度从线性变成对数,不仅是程序中的查找算法,也是调试时的方法论,一个系统有了这个意识后,关键是如何划分系统,又回到了原则1。至少在打断点调试时,要找到出bug的位置,也是可以用二分法的,或者插入日志记录时也可以应用这个原则。另外,书中还提到了bug间相互影响的现象,我觉得甚至又bug跷跷板的现象,解决之道是一个都不要放过。调试bug时发现代码质量实在太差,重构一下有时候也是有必要的,否则浮沙之上筑不了高台啊,甚至经过有效的重构,bug很自然的就发现并消除了。

5 一次只改一个地方

这条原则类似实验科学中的对照原则,一次只考察一个变量,比对正常情况和异常情况,一定不能忽略任何一个测试条件的差异。上一条说bug一个都不放过,但也得一条条过,重构的时候也要注意不要对不懂的代码乱改一气,很多代码的危险性在于牵一发而动全身,我觉得这也是修复bug时的最大风险,往往是消除一个bug同时增加几个bug,还是回到原则1,要理解系统。不过有时候,理解前人的代码谈何容易,这也启示我们写代码时要多积德,不要以为代码就是给编译器看的,而应该是给以后维护我们代码的人看的。

6 保持审计跟踪

这条原则讲的是记录的重要性与方法,我想这就像医生问诊一样,需要问合适的问题,给出具体的有效答案。我的个人经验是一旦开始调试bug,可能整个人就彻底陷进去出不来,通过记录的方式可以把自己从思维的泥潭中抽身出来,不断修正调试bug的计划与方法。对一些专用系统软件,需要培训软件的使用者如何用有效的语言来记录出现bug的情况,如果没有记录,那么调试的人就需要用适当的问题帮助使用者唤醒记忆。此外,我觉得半夜调不出的bug需要睡一觉,让发散思维自动起作用,一般早上就解决了。

7 检查插头

这条原则大概说的是所谓”低级失误“了,类似我妈跟我说电脑音箱不响了,我首先得问电源开了没这种。又比如把main函数写成mian函数,有一次我打断点调试就是不进断点,后来发现是因为有两段代码比较类似,我断点打错地方了。根据场景和经验,问问自己是否犯了该场景下常见的低级失误,往往针对能立竿见影的解决很多问题,就像很多电器设备说明书的故障FAQ中,也会强调检查插头。可以说,低级失误低级的是难度,而不是频度。

8 获得全新观点

这条原则说的是求助和交流,这里面很重要的是通过他人的观点来破除自己的思维定势,所以最好是只给别人详细描述现象,不要说自己的猜测,以免污染别人的判断。对程序员而言,这时候面向google编程的力量是惊人的,可能九成的问题都不需要你真正的再去提问,而是找到合适的搜索词去搜索即可,对中国程序员而言,用英文搜索是必须的技能,当然搜到东西后真正理解也是非常重要的,不能见到药就吃。如果遇到的问题google真的搜不出来,证明你层次稍微高了点,这时候可以上stackoverflow之类的社区提问。

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

这条原则说的是不要心存侥幸,不要因为bug只是闪现了一下就采取鸵鸟策略,该来的总会来,不是不报,时候未到。当然实际情况可能很复杂,软件工程本来就是时间、成本和质量的妥协体,但即使放过某些bug,也要分析出这样可能造成的后果,建立充分的防护机制,因此在很多软件认证体系中,都会有软件安全等级标准。这里还涉及bug复现和举一反三的问题,需要确认真正找到了bug的原因提供了有效的修复手段,并排查所有类似的问题。比如修复了一个内存泄露问题,就要修复所有导致这类泄露的代码。

附记:如何写出适合调试的代码

从调试的原则反观,对软件构建本身也很有帮助,毕竟调试只是查漏补缺的,最好还是写出来的代码少一些bug,为了调试的时候方便多预留一些手段。这里也简要总结一下个人经验,可能需要不断完善。

1.程序中应该提供日志机制,在程序的debug版便于输出调试信息,即使在release版,也要记录软件发生问题(如C#中抛出异常)时的详细情况;

2.要写出适合人类阅读的代码,否则后续维护的人看都看不懂,要如何调试?怎么写《代码大全》中说得最详细了,我觉得除了各种习惯写法之外将心比心也是很重要的;

3.使用各种类库或工具时,尽量弄懂原理,仔细的阅读官方文档,比如有些类库会详细说明如何防止内存泄露,如何应对多线程情况,看清楚再用,就会少种下祸根,至少不用等到调试的时候再无头苍蝇一样猜测原因;

4.写便于测试的代码,这样在调试时,容易剥离问题,或者使用二分法,这方面TDD编程实践讲得比较充分,我个人也需要加强。

《调试九法》读后感(五):找出问题和解决问题的思维《调试九法》

《调试九法》副标题是<软硬件调试之道>,列举了9条调试规则:

看完之后,发现在工作中经常违犯其中一到两条规则。比如总是没有事实依据地猜测问题发生的原因,问题出现的时候只是草草地记录,导致后面忘记诱发错误的条件等。

可能你是程序员,那么本书对你有直接的作用。但是从某种角度来说,凡是遇到问题的人,都可以从这本书介绍的思维中借鉴解决问题的方法。

比如遇到问题,首先要理解出现问题的整件事情前因后果,它不出现问题是怎样的。不靠猜想问题的诱因而要去观察它们,把这件事情分为好的部分和坏的部分,我们目的是解决问题,所以只关注坏的部分。通过不断二分,就能锁定问题环节。这其实是解决问题的一种套路思维,掌握它,我们可以有效地解决大部分问题。

将调试分为三个阶段总结一下,调试前去理解和审计,调试中要观察验证,调试后反思总结。

1.调试前

通过阅读手册等手段,了解系统的工作原理和工作流程,还要懂得调试工具的能耐。至少在撸起袖子动手前,要知道正常长什么样子。

更向前一步,编码的时候,预测容易出问题的地方,打下不同级别的日志,给BUG留下一条轨迹。

是否进行了审计跟踪,最好有自动编译脚本,一键构建任意版本及其运行环境,不必为了重现劳心费力。有了审计跟踪,至少可以回到上一次系统能成功运行的好时光。

审计跟踪的详细程度、严重程度要记录,每步操作、顺序和结果,症状关联到时间和人员,注明相关事件和影响,甚至你的推理,修复的时候记录下操作。

既然BUG已经出现,在解决它之前,就要让它在受控情况下复现。复现BUG,目的有三——观察错误,查找线索,确认修复。

从头开始一系列时序步骤,模拟那些导致失败发生的条件,而且要记录下来便于分析,解决BUG后故意地制造条件来验证BUG被修复了。

2.调试中

调试过程中,不要想当然,要亲眼看到底层的失败,看到故障发生的情况。不要想,而要看。经验是使你尽可能少地按错误的猜测行动,而没有观察基础的猜测会让你误入歧途。

观察细节,把问题的原因锁定在几种可能之内。二分法是一种高效率的问题定位方法,因为我们目的在于修复问题,去验证正确的事情是无益的,要从有问题的一侧开始搜索。如果猜测不对,就要回到猜测之前。

我们之所以这样猜想,是因为这个猜想的情况更容易出现,或者是因为这个猜想更容易验证,凭空猜想是浪费时间。同样要质疑假设,你对调试工具所做的假设也可能是错误的。

植入插装工具(调试日志)、添加外部插装工具(GDB)、隔离变量、消除干扰的因素、对比正常和有问题的记录、回到上一次正常工作再逐步加入更改、寻求帮助、通过解释给别人听来理清头绪都是问题解决的方法。要注意海森堡效应,不要让插装工具影响了系统。

寻求帮助的时候,客观地描述,不要把别人带进你的理论。修复已知的BUG,不要让它们相互庇护。一次只改一个地方,如果修改没有解决问题,应该立即把它改回来。

3.调试后

确定问题是修复措施解决的,取消这个措施将导致系统再次失败。有时候不要过于相信统计数据,谨防BUG不再发生是没有找到特定的时序去引发它。

进一步追踪导致问题的基本条件,要从根本上解决问题。至少在关键的地方添加注释和日志,保留调试工具,下一次在周围出现新问题,就不至于从头再来DEBUG。

阅读成长

延伸阅读:

本文由作者上传并发布(或网友转载),绿林网仅提供信息发布平台。文章仅代表作者个人观点,未经作者许可,不可转载。
点击查看全文
相关推荐
热门推荐