Chapter 23 Debugging
 调试

调试是确定错误根本原因并纠正此错误的过程。
23.1 Overview of Debugging Issues 调试概述
·Role of Debugging in Software Quality 调试在软件质量中所扮演的角色
同测试一样,调试本身并不是改进代码质量的方法,而是诊断代码缺陷的一种方法。

·Variations in Debugging Performance 调试效率的巨大差异
除了调试效率的巨大差异之外,这项研究还印证了软件质量的普遍法则:提高软件质量能够减少开发成

本。最好的程序员能够找出最多的错误,最快的找出错误,并且往往能够正确改正错误。

·Defects as Opportunities 让你有所收获的缺陷
程序中的错误为你提供了学习很多东西的绝好机会。
1. 理解你正在编写的程序。
2. 明确你犯了哪种类型的错误。
3. 从代码阅读者的角度分析代码质量
 你必须阅读自己的代码,以便发现其中的缺陷。这就使你有了带着挑剔的眼光审视自己代码

的质量的机会。代码易读吗?它怎样才能更好?用你的结构重构你现在的代码,并让自己下次编程的代码更好。
4. 审视自己解决问题的方法
5. 审视自己修正缺陷的方法
 你是否使用了goto这样的绷带或对一些处理特殊情况进行简单包扎,从而仅仅治标不治本呢?

·An Ineffective Approach 一种效率低下的调试方法
   The Devil's Guide to Debugging 调试之魔鬼指南
1. 凭猜测找出缺陷
2. 不要把时间浪费在理解问题上
3. 用最唾手可得的方式修正错误

   Debugging by Superstition 迷信式调试
 撒旦已经慷慨地将地狱的某个部分租给了那些在调试时怨天尤人的程序员了。每个团队里都有这样一个程序员,他总会遇到无穷的问题:不听话的机器,奇怪的编译错误,月圆时才会出现的隐藏缺陷,失效的数据,忘记做重要的改动,一个不能正常保存程序的编译器——你怎么描述这种行为呢?

这就是“迷信式编程(Programming by superstition)”。
 要知道,如果你写的程序除了问题,那就是你的原因,不是计算机的,也不是编译器的。程序不会每次都产生不同的结果。它不是自己写出来的,是你写的,所以,请对它负责。 即使某个错误初看似乎不能归咎于你,但出于你自身的利益,最好还是假设它的产生同你有关。这样就能避免陷入这样的尴尬地:在公众面前先指责别人犯了错,最终却发现错误其实由你而生。

23.2 Finding a Defect 寻找缺陷
 调试包括了寻找缺陷和修正缺陷。寻找缺陷——并且理解缺陷——通常占到了整个调试的90%。
·The Scientific Method of Debugging 科学的调试方法
在运用经典的科学调试方法时,你会经历如下步骤:
1. 通过可重复的试验收集数据
2. 根据相关数据的统计,构造一个假说;
3. 设计一个实验来证明或者反证这个假说;
4. 证明或反证一个假说;
5. 根据需要重复进行上面的步骤。

寻找缺陷的有效方法:
1. 将错误状态稳定下来;——Stability the Error
2. 确定错误的来源(即那个失误“fault”)——Locate the Source of the Error
3. 修补缺陷
4. 对所修补的地方进行测试
5. 查找是否还有类似的错误。

·Tips for Finding Defects 寻找缺陷的一些小建议
1. 在构造假设时考虑所有的可用数据
2. 提炼产生错误的测试用例
3. 在自己的单元测试族(unit test suite)中测试代码
4. 利用可用的工具。
5. 采用多种不同的方法重现错误
6. 用更多的数据生成更多的假设
7. 利用否定性测试用例的结果
8. 对可能的假设尝试头脑风暴
9. 在桌上放一个记事本,把需要尝试的事情逐条列出
10. 缩小嫌疑代码的范围
11. 对之前出现的缺陷的类和子程序保持警惕
12. 检查最近修改的代码
13. 扩展嫌疑代码的范围
14. 增量式集成
15. 检查常见缺陷
16. 同其他人讨论 —— 有人称之为“忏悔式调试”
17. 抛开问题,休息一下

·Brute-Force Debugging 蛮力调试
在调试软件故障时,蛮力调试常常是一种被忽视的方法。“蛮力”是指一种或许会被认为乏味,费神,耗时但最终能确保可以解决问题的方法。
1. 在使用“快速肮脏调试法”的时候设置一个时间上限。
 对每一种蛮力调试方法,你的反应都可能是“我做不了!工作太多了!”。 我们每个人的投机心理都宁愿去用一种可能在五分钟内发现缺陷的高风险方法,也不愿意为某种保证能够找到缺陷的方法花上半小时的时间。
 如果打算通过捷径摘取胜利果实,那么请为你尝试捷径的时间设置一个上限。如果耗时超过了上限,就应老老实实地承认问题比你最初想象的要更加难于分析,应该转到困难的路上重新开始。
2. 做一张蛮力调试方法列表

·Syntax Errors 语法错误
语法错误的问题已经就如剑齿虎与猛犸象一样将要退出历史舞台了。在显示诊断信息方面,编译器做得越来越好。下面一些建议来加速这一稀有物种的灭绝:
1. 不要过分信任编译器信息中的行号。
2. 不要迷信编译器信息。
3. 不要轻信编译器的第二条信息
4. 分而治之
5. 找出没有配对的注释或者引号

23.3 Fixing a Defect 修正缺陷
1. 在动手之前先要理解问题
 “调试之魔鬼指南”说的很对:如果想让自己的生活潦倒,让自己的代码质量一塌糊涂的最好方法,就是不懂装懂地动手修补程序缺陷。
2. 理解程序本身,而不仅仅是问题
3. 验证对错误的分析
4. 放松一下
5. 保存最初的源代码
6. 治本,而不是治标
7. 修改代码时一定要有恰当的理由
8. 一次只做一个改动
9. 检查自己的改动
10. 增加能暴露问题的单元测试
11. 搜索类似的缺陷

23.4 Psychological Considerations in Debugging 调试中的心里因素

23.5 Debugging Tools - Obvious and Not-So-Obvious
 调试工具——明显的和不那么明显的
·Source-Code Comparators 源代码比较工具
·Compiler Warning Messages 编译器的警告消息
1. 将编译器的警告级别设置为最高级,尽可能不放过任何一个警告,然后修正编译器所报告的全部错误;
2. 用对待错误的态度来处理警告
3. 在项目组范围内使用统一的编译设置。
·Extended Syntax and Logic Checking 增强的语法检查和逻辑检查
·Execution Profilers 执行性能剖测器
·Test Frameworks/Scaffolding 测试框架/脚手架
·Debugger 调试器

Key Points 要点
1. 调试同整个软件开发的成败息息相关。最好的解决之道是使用本书中介绍的其他方法来避免缺陷的产生。然而,花点时间来提高自己的调试技能还是很划算的,因为优秀和拙劣的调试表现之间差距至少是10:1.
2. 要想成功,系统化地查找和改正错误的方法至关重要。要专注你的调试工作,让每一次测试都能让你朝着正确的方向前进一步。要用科学的方法。
3. 在动手解决问题之前,要理解问题的根本。胡乱猜测错误的来源和随机修改将会让你的程序陷入比刚开始调试时更为糟糕的境地。
4. 将编译器警告级别设置为最严格,把警告信息所报告的错误都改正。如果你忽略了明显的错误,那么要改正那些微妙的错误就会非常麻烦。
5. 调试工具对软件开发而言是强有力的支持手段。找出这些工具并加以应用,当然,请记得在调试的时候开动脑筋。

posted on 2009-05-14 10:22  SamZhang  阅读(386)  评论(0编辑  收藏  举报