https://www.zhihu.com/question/28177315
http://www.cnblogs.com/duguguiyu/archive/2008/03/16/1108091.html
纠错前先思考:
在我加入贝尔实验室一年多后,Gerard Holzmann设计了一个很小的交换式制图语言,我开始和Ken Thompson一起在开发针对这种语言的即时编译器上做结对编程。我打字比较快,所以我坐在电脑前,Ken站在我身后看我编程。我们开发的很快,但经常会遇到问题,而且可以看出来出错了——毕竟这是一个图形化的编程语言。当程序出错时,我本能的一头扎进问题,检查报错跟踪信息,添加调试打印语句,启动调试器,等等,但Ken只是站在那思考,完全不理会我也不查看我们写的出问题的代码。一段时间后我发现一个规律,Ken经常会比我先找到问题出在什么地方,而且会突然的喊一嗓子,“我知道什么地方的问题了。”每次他的判断都很准确。我认识到,Ken已经在脑海里构建了代码的模型,当有问题出现时,那是他脑子里的模型出了问题。在思考为什么会发生这些错误时,他能凭直觉找到模型中什么地方不对或发现写的代码跟这个模式什么地方有出入。
Ken教会了我一个极其重要的习惯:纠错前先思考。如果你一头扎进问题中,你可能只解决了当前出现问题的代码,但如果你先思考这个错误,这个bug是怎么引入的?你通常发现和纠正一个更高层次的问题,进而改进了系统设计,防止了更多bug的出现。
我认识到这种编程思考模式非常的重要。有些人痴迷于一行行的、使用各种工具来调试所有的东西。但我现在相信,思考——不看代码的思考——是最好的调试途径,因为它能让你开发出更好的软件。
程序员调试能力和相关书籍:
在软件行业中,个人觉得每个Coder、Leader(那些当了Leader以后就不需要Code的除外)都应该除了具有良好的编码能力以外,最为主要的就是Debug的能力要坚实。千万不要告诉我Debug工作是Tester和QA的事情,首先你要认识到Debug的能力是一个并不简单的能力,能帮助你提高你的开发能力,加快开发速度,节约开发成本;其次你更应该知道,你所掌握的Debug的能力和技术并不可能抢去Tester或者QA的饭碗,他们做的工作更仔细、全面,更富有创造力。由于本人数年来一直使用VC6,所以下面使用的观点和相关的描述都是从VC出发的,肯定有所偏颇、错误之处,还望各位看官不吝啬地指出,本人定虚心接受,共同讨论,共同学习,共同进步。个人觉得Debug能力包括以下三个个方面:
1、良好的编码习惯,良好的逻辑结构能力,对Bug的预见能力。一个成熟的程序员,应该有一个良好的编程习惯,不仅需要有良好的编码格式规范,更为需要的是对于程序中的逻辑实现时候有一种良好的结构。编程其实就是数据和逻辑的集合,数据的处理较为简单,或者说是需要的逻辑思维能力比较少,当算法逻辑要在数据上实现的时候,同一种逻辑,让不同的程序员来实现可能有各种各样的不同实现结构,从这个角度来说,这里所说的“良好的编码习惯”就应该指的是对于逻辑实现时候使用的良好的编程结构,一个好的编程结构应该是能预防错误的发生,对错误的预见和错误出现以后的错误处理与异常处理的良好安排。也许有人说这不好办吗?每个逻辑判断的地方添加条件判断或者异常处理不就行了?个人觉得不是那么回事,过多的if、assert、ASSERT等语句或者是宏,尤其是并列的if语句需要耗费很多判断、执行的时间,对于一个子程序(函数),尤其是调用频率比较频繁的子程序(函数),一次浪费了一点点时间,多次、频繁地调用浪费的时候就显得可观了,所以并不是if语句使用的多,程序出错的可能性就小,过犹不及!如果确实需要使用多个if语句进行条件判断,最好能使用嵌套的if语句,逐步的缩小判断范围,这样消耗的时间要比并列的if语句要小,还要注意的是if语句的条件判断也不是万能的;assert、ASSERT等判断宏也不是万能的,它会造成Debug和Release版本在响应速度和最终的编译结果的不同,对于一些关注于性能、响应速度的程序,所造成的影响是不可忽视的。不过开发过程中的调试阶段倒是提倡使用这些宏来发现算法错误和不足。另外对于异常处理段的使用,个人觉得能不用异常处理的地方尽量不要使用异常处理,除非当某个错误发生以后导致程序不能继续执行或者是崩溃的时候才使用异常,有时候你能使用异常处理,将发生错误的程序继续执行下去,但是可能产生的最后结果并不是客户所需要或者是期望的,这样就容易让客户产生质疑:你是不是在程序中做了什么手脚?这也让你失去了获得Bug发生的前提状况信息,从而失去了一次修改Bug的机会,所以说有时候当程序发生错误时,仅仅弹出一个MessageBox提示一些信息,然后关闭程序,也不失为一个好的办法。
2、编码过程中的调试跟踪和错误定位能力。这个能力主要就是在开发过程中,当自己在Build程序,Run起来以后,竟然发生了Bug或者是Memory Leak,这时候就需要你使用各种工具进行调试跟踪了。首先你要相信VC不仅是一个很好的IDE,也是一个很好的Debug工具,其提供的调用栈、条件断点、数据断点、反汇编等工具足够强大,足够应付平常的Bug,但是现在很多的程序员,包括一些自称为老程序员的也未必能很好的使用这些工具,尤其是条件断点和数据断点(在下面介绍的第二本书中有详细的使用说明)。当VC不能满足你的要求的时候你就需要使用其他的工具了,例如:SmartChecker,BoundChecker,Purify,SoftICE等等了。从这个角度来说,这里的“调试跟踪能力”不仅是程序员对Bug的定位能力,更为主要的还是对于调试工具的掌握、使用的能力。“磨刀不误砍柴工”,在开发之前或者开发闲暇时,好好的研究一下一些开发、调试工具不愧为一种好的提升这种能力的好办法。能静下心来思考一下这些工具的工作原理就更好了,这样不仅能帮助你在编程的时候预见Bug,并且对你提高你的编程技巧也会有所帮助。例如VC中的程序在Debug模式下为什么能发现数组访问越界?这是因为在Debug模式下,在分配数组所占用的内存时候,编译器在数组内存的两端分别加入了一个字节的越界判断内存。这也就是为什么很多的MFC程序在使用自定义消息的时候在Debug模式下没有错误而在Release模式下发生错误的原因了。这里我还想说一说我最喜欢做的两种调试方法:当Bug出现的时候,首先确定Bug的位置,然后:A、注释掉可能导致Bug的段落,在需要取得数据值的地方直接提供一个合理的值,然后看看程序是否能正确运行,如此循环往复,逐步缩小范围,最终找出Bug所在;B、如果Bug被定位在一个小的功能、子程序或者函数中,可以使用新建一个Test工程,在一个完全“干净”的环境下,对此功能、子程序或者函数进行测试,找出Bug所在。此节最后我想说的就是利用你的网络。当一个Bug出现时,你也许感到茫然,也许感到无从下手,这时候你就可以利用的你网络资源,使用强大的搜索引擎(比如Google、Baidu等等),输入相关的错误提示信息,也许搜索到类似问题的网页,也许别人也遇到过同样或者同类的问题,其他人所提供的答案就是你所需要的,或者能给你以提示、启发的!
3、对事后发生的Bug能有良好的感知能力。当一个Bug出现的时候,优秀的程序员能根据Bug发生的前提和Bug发生的时间点、程序中的位置,很好的感知到Bug可能发生在哪一个函数或者哪几个函数中,是什么情况导致Bug的出现的,并且能够很快的定位错误并Fix这个错误。这种能力使用的地方往往是程序已经Release了,已经被客户使用了,在使用的过程中发生了Bug,客户向你“倾诉”时。那么怎么才能有这样的能力呢?也许很多的这种能力都是在你不断的摔倒,被经理P了N次以后,所积累起来的经验,所以说这也是一种痛苦以后所获得的快乐的能力,它需要你对自己所做的软件产品的结构、运行条件、运行原理和相关的涉及部分有很好的理解、掌握。有的时候多在网站上看看别人的经历也能有所收获。
在以上的三种能力中,第一种能力主要在于态度和思维能力,后两种则偏向于学习能力和经验的积累;个人觉得第一种最为重要,所谓的“态度决定一切”嘛,呵呵。
最后向你推荐几本关于调试的书籍:
1、《Writing Clean Code——Microsoft Techniques for Developing Bug-free C Programs》(中文版译作《编程精粹——Microsoft编写优质无错C程序秘诀》或者叫做《零错误程序》)——这是一本出版很早的书,现在也许在书店中都看不到了,但是你要相信此书的作者Steve Maguire(曾是Microsoft资深的程序员,参加了Excel在多个平台下的开发和移植工作)所提供的许多防错、排错、测试的准则还是能让人从中获益非浅的。作者将每章的要点都和自己实际工作经历相结合,提供了翔实的例子和相关代码,使用的语言更是幽默风趣,让人读起来不会感觉晦涩难懂,尤其是每章结束部分提供的练习和思考题更是贴合实际,发人深省。也就是这些原因才使得这本书经久不衰,一直为广大程序所喜爱,所广泛地讨论。至今尚未能见到能与之相媲美的书籍。网上所流传的林锐博士所著的《高质量C++编程指南》和《软件工程思想》在深度和广度上与之相比也显得逊色不少!
2、《Debugging Windows Programs》(中文版译作《Windows程序调试》,中国电力出版社出版)——这是一本现在在书店很为流行的一本书。此书使用的语言比较朴实、易懂,也许是译者精心处理的结果,叙述习惯比较符合国人口味。这本书主要包含调试策略、调试工具、调试技术三部分,本书主要介绍的是在VC这个IDE、编译器下开发程序所应有的一些技术。看完此书你肯定会更为深入的了解MFC,了解结构化异常和C++异常的区别和联系,了解怎么调试多线程程序,怎么调试COM程序,怎么调试内存,怎么调试绘图程序等等。不管你是自认为有多年的开发经验的开发高手,还是刚刚入门的初学者,相信只要你耐心的看完此书,你一定会和我一样深深的感叹一句:原来VC的调试功能这么强大!如果早点看到这本书就好了!
3、《Debugging Applications》(本人尚未见到中文版)——这本书主要介绍的是VC和VB的调试,其中VC的调试占到70%-80%左右。本书也分为三部分:Debug的形式,强有力的Debug,Debug的工具和技术。其中有部分内容和上一本书所说的相同。但是这本书还是提供了很多新的东西:介绍了远程调试,提供了一些新的工具使用例子的说明,介绍了更多的底层的东西,甚至涉及汇编的相关信息的阅读和理解。在阅读了上一本书以后,如果你还想提高,这本书是你不错的选择。
第一本书主要就是培养大家第一种Debug能力的,后两本书是培养大家第二种Debug能力的,对于第三种能力主要还是要靠经验的积累。
我现在就看到这三本书是比较好的书,如果你觉得有其他的比较好的相关书籍或者相关信息请告知我。在肯定这几本书对你的开发过程会有所帮助的前提下,另外我想说的就是即使你看了这几本书你也不会编写出完全没有Bug的程序,毕竟Bug的种类和发生的情况实在是有很多的客观和主观因素,不可能完全杜绝。程序设计是一门实践性很强的工作,唯有在工作、实践过程中总结教训,总结经验才能不断提高。祝大家在获得知识,积累经验的过程中少走弯路,大踏步的前进!!!