这篇文章是《调试九法: 软硬件错误的排查之道》的阅读笔记. 这本书的主旨, 是介绍如何修复 bug: 找出 bug 发生的原因, 并给出修复方案.
调试 bug 的九个规则列举如下, 建议将这个清单打印出来, 摆放在工作时候能看到的地方.
调试九法
调试规则
接下来一次看下每个规则的核心理念, 从名字上来看, 每个规则看起来都比较明显(PS: 由于翻译的问题, 有些词可能没那么容易理解), 但是理解这些规则和应用这些规则中间还是差了很多距离的.
规则 1: 理解系统
你必须掌握系统的工作原理以及它是如何设计的, 在某些情况下还要知道为什么这样设计. 如果你没有理解系统中的某个部分, 那么这通常是出问题的地方.(这不仅仅是墨菲定律的问题, 如果你不能理解你所设计的系统, 你的工作可能会变得一团糟).
如何理解系统呢?
阅读手册
逐字逐句阅读手册, 仔细理解每个细节
知道什么是正常的, 知道什么是正常的可以帮助你注意到什么是不正常的
知道工作流程, 要理解业务, 要讲系统的工作过程对应到具体要解决的现实问题
选择合适的工具, 选择合适的辅助 (监控, 插桩) 工具可以帮你理解系统
查阅细节, 经验有时候会骗人, 记忆有时候会出错
规则 2: 制造失败
这一点比较容易理解, 就是问题复现, 在日常工作中, 你在排查一个问题的过程中, 最重要的一步就是复现问题 -- 能复现的问题都能解决.
这里有几个要点需要注意:
引发失败, 而不要模拟失败, 不要尝试用不同的方式去模拟问题, 而要模拟和构建引发 bug 发生的条件
debug 的动作, 不要影响错误的发生方式, 可以影响错误的发生频率
从头开始, 需要有一个正常的状态到不正常的状态的过程, 从开始正常的状态开始观察, 直到问题发生;
终极方案, 控制变量法, 将可能引发错误的因素依次排除; 排除所有可能的原因后, 剩下那个答案, 无论多么不可思议, 都是事实.
规则 3: 不要想, 而要看
亲眼看到底层的失败是非常重要的, 如果你猜测失败是如何发生的, 那常常会修复一些根本不是 bug 的问题.
在软件世界里, 观察意味着设置断点, 添加调试语句, 监视程序值以及检查内存; 在医学领域, 需要测试血样和进行 X 光透视.
对细节的观察应该到什么程度合适呢? 简单的答案是: 一直观察, 直到把问题的原因锁定在几种可能之内.
在系统设计的时候, 就要考虑到将来调试, 排查问题的情况, 将日志视为系统设计的一部分 - 打印一些关键日志, 或者设计一些打开日志的开关, 以便在生产环境针对某个 case 进行调试.
日常生活中有很多插桩的 case:
体温计测量体温
自行车轮胎漏气时, 都是将轮胎打满气, 然后放在水里检查哪里漏气
天然气中加入了臭鸡蛋的气味
规则 4: 分而治之
反复将问题分成好的一半和坏的一半, 然后缩小搜索范围, 然后进一步研究有问题的那一半链路.
规则 5: 一次只改一个地方
初中就学过的控制变量法.
在修改 bug 时候, 如果某个改动没有修复 bug, 就应该立即把它改回来.
规则 6: 保持审计跟踪
记下你的每步操作, 顺序和结果;
魔鬼藏在细节中;
将一些事情关联起来思考;
好记性不如烂笔头;
规则 7: 检查插头
一些显而易见的假设可能是错误的; 是不是运行了正确的代码? 是不是打了正确的包? 插头是不是掉了? 从一些最基本的问题开始确认, 很多时候问题就出在这里. 对自己使用的工具进行测试, 因为工具也是一种软件, 难保不会出问题.
规则 8: 获得全新观点
"要想重新理清一个案子的头绪, 最好的方法就是把它讲给别人听." -- 福尔摩斯,《银色马》
向别人解释问题的过程, 会让你对问题进行重新的梳理和理解, 这时候可能发现之前没有发现的问题.
bug 发生了, 以除掉 bug 为自豪, 而不是非得以自己除掉 bug 才自豪.
不管你是跟什么人求助, 或者需要别人什么样的帮助(征求意见, 获取专业知识, 听取经验), 在向别人描述问题的时候, 一定要记住一件事 -- 报告症状, 而不是讲你的理论; 另外, 有些症状你可能不是十分确定, 也可以描述出来.
规则 9: 如果你不修复 bug, 它将依然存在
"当危险已经离你很近时, 拒绝承认它并不是勇敢的表现, 而是愚蠢." -- 福尔摩斯,《最后一案》
如果你不修复 bug, 它不会自动消失. 按照前面的规则解决问题后, 要进行一次回归验证, 确保已经修复问题, 并且没有引入新的问题.
我的感想
这本书里的很多案例都是是硬件相关的, 对于软件开发工程师来说不太熟悉, 不过在阅读的过程中, 建议可以想想自己在工作中排查问题的场景, 是不是按照一定的章法去排查的? 有没有从最基本的假设开始确认? 有没有查阅文档? 有没有关注本次变更的内容? 有没有按照二分法进行排除?
作为软件开发工程师, 在实际工作中很少有机会从 0 开始构建一个系统, 更常见的情况是接手维护一个已经运行了几年, 经历了几代的系统. 写代码只是工作中的一部分, 还有很多其他的事情需要做: 修复 bug, 需求评审, 系分评审, 项目排期等等.
修复 bug(解决问题)的能力, 是软件工程师的核心竞争力之一. 在最开始的工作中, 有时候会羡慕老司机的 "直觉"-- 看到一个错误日志, 就大概知道是哪里有问题, 后来自己查问题查得多了之后, 自己也 get 到了这种 "直觉", 也理解了 -- 这不是直觉, 这是已经被实践验证过很多次的经验, 即使这样, 我也会告诫自己 -- 不能完全依赖这种经验, 经验有助于缩小待验证的范围, 还是需要事实 (重现问题) 去证实前面的猜测.
本号专注于后端技术, JVM 问题排查和优化, Java 面试题, 个人成长和自我管理等主题, 为读者提供一线开发者的工作和成长经验, 期待你能在这里有所收获.
javaadu
来源: http://www.jianshu.com/p/425f0e37b9ba