《调试九法》的读后感大全
《调试九法》是一本由David J.Agans著作,人民邮电出版社出版的平装图书,本书定价:35.00元,页数:142,特精心从网络上整理的一些读者的读后感,希望对大家能有帮助。
●短小精悍,对测试方法进行了原则化抽象,让你知其然之气所以然,读书笔记:http://fromwiz.com/share/s/3s8xMU1t1A3-24KyE72dCK-x2i6pLL2fg4PX2oV3Uf2FoPNo
●薄,风趣
●程序调试领域被忽视的作品,翻译不太好,书中例子时代久远偏硬件领域,作者是个福尔摩斯迷
●这本书写的好啊 首先 看到别人调过那么多奇葩bug 再看自己手头的东西感觉太弱了 第二 从根本上解决了面对bug时候的无力感和神秘感
●对于有较多经验的人来说,更多的是引起共鸣,但是没感觉有多少新东西
●很多都是工作中自己总结的。系统性地看一下并且时常提醒自己要注意这些。有时候,debug所要遵从的rule就是这么简单明了。当然,不同level的工程师能做到的程度也不一样。但是只要深耕其中一段时间,就一定能成为professor
●看看这本传奇的书籍 时隔半年重读这本书,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、从头开始。是否正确地对内存进行了初始化?是否按了除草机上的“primer bulb”按钮?开关是否已打开? 修车工需要知道汽车车窗在被冻结之前你洗过车。
6、引发失败但不要模拟失败。用喷水管向漏雨的那扇窗子喷水,但不要向另一扇不同的、“类似的”窗子喷水。
7、查找不受你控制的条件,记录每件事情,并找到间歇性bug的特征。
8、不要过于相信统计数据。绑定问题看起来与时间段有关,但实际年轻人占用了电话线路
9、要认识到“那”是可能会发生的。甚至冰淇淋的口味也会影响汽车的发动。
10、永远不要丢掉一个调试工具。自动击球板可能在某一天就会派上用场。
11、凭空想象问题可能有几千条原因,而实际的原因只有去看了才能发现。捷径只不过是试图找出问题所在:“一定是…因为只是在我开启…的时候它才出故障“;“我运行了一个模拟测试,它工作良好,因此问题肯定不会出在那里”;在内存问题中,“时间的设计很差。我们重新设计整个电路,这样问题就解决了。”
12、植入插装工具。使用源代码调试器、调试日志、状态消息、信号灯和臭鸡蛋的气味。
13、添加外部插装工具。使用分析器、示波器、量表、金属检测仪、心电图仪和肥皂泡。
14、不要害怕深入研究。虽然它是软件成品,但它出问題了,你必须打开并修复它。
15、注意海森堡效应。不要让仪器影响了系统。
16、猜测只是为了确定搜索的重点。大胆地猜测内存时序发生了错误,但在修复之前应该先査看它。
17、通过逐次逼近缩小搜索范围。猜测1~100内的一个数字,只需7次。确定范围,位于bug的哪一侧。
18、易于査看的测试模式。从有问题的一端开始搜索。从有问题的地方开始,然后向后追查原因。
19、修复已知bug。bug互相保护,互相隐藏。因此一旦找到,立即修复它们。
首先消除噪声干扰。注意那些导致系统问题的干扰因素。但对一些无足轻重的问题不要过于极端,也不要为了追求完美而去修改所有地方。
20、要有先见之明。如果更改没有起到预期的作用就把它改回来。可能会产生无法预料的影响。
21、一次只改一个测试。如果你在检查日照时间的影响,就不要改变灌溉方案。确定自从上一次正常工作以来你改变了什么地方。保持审记跟踪。在检査某问题时,要记下你所做的事、做事的顺序,以及发生的结果每次都要完成这些记录。你是在检测测试步骤,就像检测软硬件一样。必须清楚毎一个步骤和每步执行的结果。而且,“发出噪声,从21:04:53开始,持续4秒”比仅仅说“发出噪声”要好得多。
22、用双手抓住黄铜杆。如果你在不知道具体发生了什么问題的情况下就试图去修理核潜艇,可能会引发一次水下的切尔诺贝利爆炸。
{心理医生会尝试提取你生活的“审计跟踪记录”(发生了什么事情你对这些事有何感想),以便査明你是否有心理障碍。事实上,对一位精神病患者进行调试几乎是不可能的,因为你的“插装工具”不起作用,他会遗忘、隐瞒和撒谎,你无法进入他的身体修复问题,而只能靠谈话来引导他进行自我修复。}
23、一些显而易见的假设往往是错误的。假设错误通常是最容易修复的错误。置疑你的假设。是否运行了正确的代码?是不是燃气用完了?插头是否已插好?
24、对工具进行测试。是否运行了正确的编译器?燃料油表是否被粘住了?量表是不是没电了
获得全新观点
不管怎样,你都需要休息一下,喝杯咖啡。
征求别人的意见。甚至一个不说话的人体模特也能帮助你认识到你先前没有注意到的事情。
获取专业知识,听取别人的经验,放下面子。
报告症状,而不要讲你的理论。不要把别人拖进你的思维定式中。
你提出的问题不必十分肯定。甚至连“穿了格子衬衫”这样的事情也可以提出来
《调试九法》读后感(三):程序调试界的独孤九剑 - 《调试九法》读书笔记
一、调试九大规则
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是偶尔出现难以复现的,学名海森堡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编程实践讲得比较充分,我个人也需要加强。