小扯一下调试。。。

前段时间陆陆续续读完了pangba老大力荐的Why Programs Fail, 一本关于程序调试的大作。给人最大的启发就是调试是一门科学而不是艺术。我从来不知道,原来调试还有那么多的千奇百怪的工具,可以写那么多的数学推导。从 小学开始我们就开始了解,作文没写好你可以说老师欣赏不了,而数学题算错了只能怪自己混的不够到位。于是我们总是很主观的把调试当成艺术来看待,调试能力 的高低不仅取决大量经验的积累也是天分所致。很遗憾的是,本书中告诉你,调试是有方法可以寻求的,像解数学题一样,用既定的方法套路去做,无论天赋高低经 验多寡,都能得到正确结果。恩,好像说的有点夸张了。但至少,调试是有章而寻的,是无须质疑的。我想我会努力去尝试使用一些书中提到的工具,但我依然不甘 心把一个充满所谓艺术性的活干的如此机械,书中的一些经验总结一下,同样可以在无足够工具支持下快速的进行调试。
TRAFFIC。这是作者把调试各步骤首字母提取出来的得到的一个词。依次对应跟踪问题,重现问题,自动化和简化,寻找感染源,专注可能的来源,分离感染链
问题跟踪,一个极其重要的内容是,错误是谁发现的。个人觉得,谁发现的直接影响到错误的可重现度。按可重现度高低来排,依次应该是自己发现》测试人员发 现》用户发现,而错误的可重现度,是影响调试时长(甚至是成功与否)的重要因素。换句话,如果想很好的调试,应该尽早的让潜在的错误跳出来和你对话,所有 为尽早发现错误进行的努力都是值得的。这些努力包括:断言,异常(你为什么不使用异常?),单元测试,重构,代码走查,静态分析等等。当你写下一些code的时候,你应该多考虑一点,如果出错,我是否能很快知道是这里出来的,这就是一个很好的习惯。
日志,我觉得其最重要的作用是用于重现问题阶段。它不应该作为个人编码阶段定位错误点、分析bug的最优先选择(当然这有太多的意外情况,比如你有很好的 日志分析和记录系统,或者没有其他更好手段可以使用等等...),而是应该作为重现客户问题的重要手段。在问题重现中,我们总是希望错误能在我这里明明白 白再出现一次,但很多时候这样小小的渴望都沦落成为了奢求。我曾做一个外包项目,在这里跑的好好的程序到美国那边总是出错。介于保密的原因,很多东西我们 不能够过多的了解,甚至连真实的数据我们都拿不到。这时候我们能够依仗的就是各种日志文件。通过日志,你可以在不重现错误的前提下推断出错误,不知其然却 知其所以然,未必不是解决问题的方法。
更多的时候,我们能够重现错误,但重现步骤过于繁杂(比如客户告诉你,他是一边倒立一边点鼠标发现这个错误的...),不能够帮我们很快定位在真实的错误 起始点上。这时候就需要进行简化,用到的是作者看家的兵器delta技术,有兴趣的可以翻书查看,而论其思想,主要是二分思路,或者说有条理有步骤的剔除 非相关因素。有条理有步骤是最关键的词汇,二分只是其中一种很步骤很条理的方式,而其他的,我觉得只要是够有规律,能够达到循序渐进,不走弯路的,都行。
书中描述了所谓的科学调试的方法。基本是按照回溯的路线(及从错误的出现点出发寻找错误的发起点...),提出假设,观察,验证或推翻假设,一直将假设等同于错误的起点为止。我觉得这也只是有步骤有条理的方式的很好的一种,而不是全部。
只是规规矩矩走路的人往往会错失捷径。我们很多时候看到这个错误出现,根本不用一步一步回溯,根据我们的经验和奔涌的肾上腺素,就能快速而准确的猜出问题 的原因,省时省力(该方法被称为快速而杂乱的调试...)。我想这是很多人(也包括我吧...)发掘问题起因的最习惯手段。而世界的残酷在于,一旦我们沉 迷于我们自己的猜测,会深陷其中,无法自拔,赌徒似的把大把大把的时间投进去,却血本无归。一个标准是,如果进行了十分钟的杂乱的调试依然没有找到问题的 话,就转入科学调试状态(把自己做成一个快表系统...),鱼和熊掌,就是这样来兼得。
此外,我们还有很多调试的手段,我觉得从目的上看可以分成事前推测和事后分析(还是那个WS的比喻,套&&药...~_~)。一个错误出 来,我们可以先走查一下代码,看看编译器的warning等等。书中最NB的,是一种静态分析技术,通过工具解析代码结构,得到一些可能的错误起因。在我 眼里,这就是所有事前分析手段的专业版本,有空我一定要玩玩这些工具。可惜的是,我们总是不能聪明到看(或自动分析)代码就可以了解所有错误的程度。很多 东西只有run起来,才有恍然大悟的机会。所以我们需要很多事后分析手段。用的最多的还是调试器。日志,对,也可以用在这里。两者最大区别时,调试器是精 确慢速而局部的,日志是粗犷全面但部署困难的。两者的使用,和场合和工具的犀利程度有很大关系。对我个人来说,在二者皆宜的场合,我会动用调试器。
说到调试器,不得不说测试(这里指的是程序员个人的单元测试...)。在此前一点概念需要说明。在很多人概念里,调试简单的对应使用调试器,与测试是格格 不入的。而在本书中,调试,指为了发现错误的起因所使用的所有手段,其中包含测试。测试最最最最优良的一点在于它是自动化的。或者说是可永远重现的。这就 是说,使用测试,可以帮你解决诱发错误,重现错误等及其麻烦的事情。但是,测试往往只是能够帮你找到错误的出现点,而不总是能快速的把你带到错误的起因 点,而为了部署这些测试你需要花费很多的精力。正是基于此,包括云风老大等很多人不屑使用测试(再次强调,这是指个人的单元测试...)。但是,这部以为这测试不重要,而成为你可以肆意偷懒放低代码质量的借口。而是因为其带来的好处被其他的一些技术抵消了,这样的话,为其付出的代价就会显得很沉重。
但是无论你使用什么样的手段进行调试。代码结构的质量才是最最最根本的内容。一个函数划分很细致,不大量滥用全局变量的代码,使用很多无副作用的函数,通 过测试你发现错误出现点,往往你就能很快到达错误起点(因为你把错误可能出现的地方限定在了有限的范围)。而如果你代码结构混沌不堪,函数/类之间关系错 综复杂,哪怕你用测试找到了错误出现点,开着调试器进去看,你也会很快转晕。所以提高代码质量,合理应用适合的调试工具和手段,正确使用调试的方法才是正 道。在这里,不得不提一下TDD。最初的时候我总觉得TDD最核心的是T,Test。后来才开始明白,它最核心的其实是D,Drive。你可以把测试写的 很弱,但你一定要在此影响下把代码重构的很好。由此得到一个蛮歪的理:如果你或你团队的代码素质很高,可以尝试不用TDD的一些开发手段;但如果你或你团 队代码素质不够高,请把自己套在TDD里面磨练一下。之所以说歪,是因为我其实只想说后半句,前半句纯属为了对仗工整而用。
最后我发现我忘提一个很好玩的东西,断言。我一直觉得这个东西很有意思。是一种游离在单元测试与调试器之外的手段,是一个隐藏在事后分析中的事前推测派来 的间谍。assert的意义在于猜测并提醒一些最有可能的错误,它不精确但也不死板。我一直觉得,全面合理的铺下断言这张网(三个部分,输入输出不变 式),可以很有效的提高调试速度。

posted on 2008-03-16 04:07 duguguiyu 阅读(2884) 评论(10)  编辑 收藏 网摘 所属分类: 心得体会设计模式C++

评论

#1楼 2008-03-16 11:48 怪怪      

老兄, 你这篇文章太好了....., 比我说的清楚多了。

不过在这点上, 我和云风的还是不一样(虽然他比我牛的多), 他极端, 敢说敢做; 我却是个中间派。
  回复  引用  查看    

#2楼[楼主] 2008-03-16 11:58 duguguiyu      

@怪怪
谢谢,看了你那篇TDD的,大赞~~~。

这个问题,我也倾向于用TDD,个人环境不一样可能所需要的手段也不一样吧。
  回复  引用  查看    

#3楼 2008-03-16 12:15 怪怪      

@duguguiyu
我觉得就是具体问题具体分析。

其实我TDD的地方不多, 都是感到拿一个梳子理一遍更轻松的场景,局部使用TDD。因为说实话,很多场景简单到测试写出来出错的概率一点不比子程序本身是错误的概率高(当然就如你所说,简单不简单, 其实是根据人的因素改变的)。

但我仍然倾向于人应该将自己的行为规范化。我只是烦恼不问青红皂白, 流行啥就照本宣科的做法和说法。

我把我最后一篇文章更新了,嵌了你的后半段进去,加了点注释,不反对吧? :P

http://www.cnblogs.com/guaiguai/archive/2008/03/16/1108079.html
  回复  引用  查看    

#4楼[楼主] 2008-03-16 12:17 duguguiyu      

@怪怪
呵呵,受教了~~。当然没有问题的:),我去see see。。。
  回复  引用  查看    

#5楼 2008-03-16 12:55 deerchao      

pangba? 我猜你说的是pongba(刘未鹏).   回复  引用  查看    

#6楼[楼主] 2008-03-16 13:28 duguguiyu      

@deerchao
呵呵。是的。。。
  回复  引用  查看    

#7楼 2008-03-17 10:37 力大无比[未注册用户]

扯的蛮有道理   回复  引用    

#8楼 2008-03-17 11:54 Clark Zheng      

好文!   回复  引用  查看    

#9楼 2008-11-20 15:14 Sail      

TRAFFIC。这是作者把调试各步骤首字母提取出来的得到的一个词。依次对应跟踪问题,重现问题,自动化和简化,寻找感染源,专注可能的来源,分离感染链。

第一招,跟踪问题已经成习惯了。
  回复  引用  查看    

#10楼 2008-12-23 10:36 秒大刀[未注册用户]

“全面合理的铺下断言这张网,可以很有效的提高调试速度”   回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1108091




相关文章:

相关链接:

导航

公告



姓名:A2F1H1I1N1U2Y1



性别:这里会有女人么?



特长:擅长回答各类码工常见问题,正确率高到0%。



欢迎前往观看另一个我








Chrome技术讨论QQ群:49829897


<2008年3月>
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

搜索

 

留言簿

随笔分类(149)

随笔档案(105)

积分与排名

最新评论

阅读排行榜