作为一名软件工程师,调试思维是重中之重的能力。而《调试九法》这本书很好的阐述了调试软硬件故障的思想方法,强烈建议阅读原书。
第一,理解系统:
理解系统需要一定的背景知识,比如我是Android 开发,那么我至少要懂Java,C/C++,Android系统的各种机制,规则。如果不明白这些,那么就谈不上去解决Android系统的bug,开发者手册和源代码是最好的学习方式。
第二,制造失败:
也就是复现问题,复现问题的好处是显而易见的,可以观察问题,专心查找原因,并且可以检测是否已经被修复(也就是修改代码之后如何复测验证)。制造失败是希望能复现出错的场景,而不是模拟错误。对于间歇性不易复现的问题需要花大量时间跟踪,收集足够多的信息,并与正常情况比较,观察差异,找到间歇性bug的特征,思考那些不受控制的条件。作为工程师不能随便就讲“那不可能”,bug产生的原因很多,不要过于自信自己的经验和数据统计。
第三,不要想,而要看:
这一条的意思就是不要瞎猜测,要观察bug现象,仔细查看细节,加入log信息,通过反复的重现bug,收集足够多的log信息,不要惧怕阅读庞大的源代码,好的源码其实都很好阅读,尤其是Android OS的源码都非常清晰。根据收集的信息进行分析并创建假说,以此确定要研究的重点方向。
第四,分而治之:
其实就是通过二分的方法确定问题的边界,比如先确定是软件bug还是硬件bug,确定是软件bug,那么是软件哪一层的bug,如此二分下去,缩小范围,面对庞大的系统代码才能精准定位bug。
第五,每次只改一处:
控制变量法则,如此才能消除干扰项,不至于掩盖真正的问题原因,复现测试条件的修改也是一样一次只能改一处。对代码经过改动,将其与正常的系统进行比较,观察差异。同时在时间上也可以对照,检测上一次能正常工作是什么时候,然后检查代码提交记录。我就解过一个因为添加了一个注释而导致的字体库缺失问题。
第六,保持审计跟踪:
本条的意思是说在你复现问题时要做好记录,记录下你做的每一步操作,顺序,和结果。这有助于将问题划分到某个较小的区域,然后专心研究这个区域,同时也容易发现bug与测试人员的关联关系,例如:有一个奇怪的bug,当测试人员站起来时就会复现了,他坐下的时候就会消失,这是因为他坐下时是盲打键盘,盯着屏幕,站起来时会盯着键盘。针对这样的问题,如果善于记录和关联,就会发现问题的真正原因。好记性不如烂笔头,对问题做记录,下次遇到的时候也能很快修复。
第七,检查插头:
也就是要能对自己的假设进行合理怀疑,比如在测试手机人脸识别解锁的时候,你发现只能打开后置摄像头,这显然是bug,但是先别急着怀疑是代码的问题,就算你发现有两台工程机都是如此,那么请使用第三台继续测试,因为有极大的可能是测试机的前置摄像头坏了。当我们测试某个问题时,首先要确定他是否在满足基本的测试状况,比如要测电话功能,那么至少要先插上sim卡,检测sim卡是否匹配,是否具有信号等。如果某个问题用了很多方法还是一头乱麻,或者代码已经修改了,但是仍然测不过,那么就应该检视一下测试工具是否正常。
第八,获取全新观点:
这一点讲的其实就是向别人请教,如果一个问题实在找不到原因而卡住的时候,尽管可以用其他的手段解决,但是可能时间成本过高,毕竟我们都是凡人,并不是全知全能的,此时向别人请教会是一个好办法,但是这有个前提,那就是你已经分析过问题,并且已经知道问题产生的原因大概是什么,比如你想读写某个分区,你已经配置的seploicy,但是仍然没有权限读写该分区,你一筹莫展的时候,问一问周围的同事,可能他就会告诉你是不是忽略的自主访问控制权限配置。寻求帮助的方式最简单的就是谷歌,百度,利用搜索引擎能解决很大一部分问题,毕竟很多问题并不是你最先遇到。记住,寻求帮助的时候,要向对方报告症状,而不是你的理论猜测。
第九,如果你不修复bug,它将继续存在:
也就是要在修复之后多做几次测试,找到问题真正的root cause,只有解决了真正的bug,才能杜绝相同的问题发生。