故障定位四法

 
        很早就在构思一篇关于故障定位的文章,开始动笔之前,到图书馆转了一圈,意外发现了一本非常有趣的书——《调试九法 软硬件错误的排查之道》,虽然有些观点不尽认同,但是质量的确上乘,而且书中的例子相当生动。本文完成于读完此书之后,权当一篇读书笔记,借此抛砖引玉。

       世间万事万物皆为系统,当系统没有按照人们的期望运行,即可称之为故障。社会矛盾激化可以称之为故障,依赖政治家去解决,经济停滞不前可以称之为故障,依赖经济学家去解决,人身体不适可以称之为故障,依赖医生去解决,一起犯罪案件也可以称之为故障,依赖警察去解决......在需要解决故障的众多行业和职位当中,软件工程师不可谓不幸运,我们碰到的故障总是发生在范围相当确定的系统当中,软件总是严格依照代码运行,可以人为控制复现,可以选择性插入观察点,软件故障可以说是最容易定位和解决的故障。

****************************************************************************
望——隔岸观火
       个人始终觉得一上手就试图找到代码的错误是对别人或者是自己过去的劳动成果不尊重的表现,一个你能够轻易发现的代码缺陷,在别人眼中绝不会是一个很难发现的问题或者难以解决的故障。我们更接受的观点是智者千虑必有一失、尺有所短寸有所长,在某种特殊环境,某些特殊操作的触发下,故障显现,我们更可能需要考虑的是一个综合的复杂的环境下整个系统的运行情况,而不仅仅是一小部分代码的缺陷否则,经常只能是事倍功半。 
       在这个阶段,主要的工作应该是从系统的外部收集故障的相关信息。跟测试人员的沟通,了解他们所期望的功能体现,他们发现故障的一系列触发条件,确认他们的描述与自己的理解是否有偏差,该故障是必现还是需要某种触发条件还是有一定概率出现或者很难出现。在可能的情况下,结合自己对系统的理解,尝试简化测试环境,复现故障,收集触发故障的最简化环境,找到甚至是人为制造出最快复现故障的方法。有时候确定了故障的复现规律,原因也基本上就能够确定,解决方案也呼之欲出了。
        参考:制造失败 保持审计跟踪 不要想,而要看

****************************************************************************
闻——走马观花
        尽可能地收集到故障发生的外部环境信息之后,需要开始对系统内部运行情况进行跟踪,最直接的方法自然是看代码。通过语言的基础知识或者是自身的逻辑分析能力找出代码中的问题,或者你可以洋洋自得地嘲笑一把上一位程序员怎么会犯下如此低级的错误,或者我需要惭愧地承认自己居然不自量力地向你推荐一篇如此肤浅的文章。可是如果你不能,那么我想告诉你的是,看代码不是期望发现错误,而是找出定位错误的方法。
        在一个复杂的系统中,我们不可能一开始就对整个系统的特性和运行有细致的了解,只能基于对故障的理解确定对应的系统入口及查找路线,结合前期总结出的复现环境和复现操作对系统运行的上下文环境做出一些假设,在上下文环境中,跟踪故障涉及的主要路径的运行的情况,确定合适的观察点或者是一些值得怀疑的地方。运气好的话,可以发现一些有用的调试开关和被自己忽略的关键函数调用,利用系统既有的一些手段,也许能够马上找到导致故障的关键函数和关键模块。系统及其与外部环境之间的交互在脑海中的模型通过这一阶段逐步细化,但是需要控制住解决故障的冲动,把不熟悉的地方当成是一个潘多拉魔盒,除非确认问题就出在此处,否则千万不要轻易打开。
        参考:理解系统

****************************************************************************
问——刨根问底 
        对于前面介绍的两个方法,耗时不长且所完成的工作通常都是对定位解决故障有直接意义,而对于任一问题的深入研究,时间一般不会太短,当对故障的根源做出错误判断的时候,这一工作虽然对程序员的能力和知识范围的扩展有巨大的促进作用,但是对当前故障的解决可能毫无帮助,这也是不建议过早进行深入研究的原因。了解了故障的复现条件,识别出系统的基本模型,通过快速地浏览代码只能定位比较明显的故障,如果此时故障的根源还没有显现,我们不得不进行更深入的探索,虽然困难,但这一过程是求知若渴的程序员自我提升的最佳时刻。
        通过更广泛的信息收集对研究范围做出假设,反复地试验、观察检查可能遗漏的重要信息,通过更周密的分析获得对系统更加清晰的认识,反复地询问自己对系统运行和外界影响还有什么不清楚的地方。依然还是上面那句话,软件工程师是幸运的,系统始终会按照代码的指示运行,而且始终按照同一条路径运行,在这条路径上,反复地确认自己的期望是什么,而系统运行的实际情况又是什么,找到了两者不符之处就找到了继续搜寻的方向。不管系统运行得对,或者不对,答案就在那里,不离不弃。
        参考:理解系统 获得全新观点 不要想,而要看 检查插头

****************************************************************************
切——无的放矢
        正所谓人算不如天算,有的时候自我感觉手头上已经掌握了大量信息,但是仍然找不到确定的答案,原因只有一个,我们对系统和环境的理解还是不够深刻。到了这一刻,我不得不承认自己已经黔驴技穷,自己的逻辑思维能力相当低下,更可悲的是还不愿意动脑子,我已经为这个故障耗尽最后一丝耐性,恨不能将这个可恶的系统抽筋扒皮,千刀万剐,挫骨扬灰。
        我不止一次对自己的智商失去信心,但是我的自信始终不改——程序就是数据和逻辑的游戏,遵循的唯一的规则就是代码,如果我不能找到故障,那就让故障自己来找我。尽可能详细地添加打印,收集系统的运行轨迹和关键数据的信息。修改相关逻辑,干涉系统运行,观察是否能够加剧或者减轻故障。使用更为简单但是合适的逻辑替代系统中的单元模块,观察是否能够规避故障。总之,怀疑一切可以怀疑的地方,通过切割、替换等方法,降低系统的复杂性,让故障自己浮出水面。
        参考:分而治之 保持审计跟踪 不要想,而要看

总结
      上面描述的四种方法没有严格的顺序性,可以反复交叉进行,什么时候使用什么方法,什么时候进行切换还是依赖于当事人的经验判断。

你可能感兴趣的:(故障定位四法)