Chapter 8 Defensive Programming
防御式编程
这一概念来自 防御式驾驶,在防御式驾驶中要建立这样一种思维,那就是你永远也不能确定另一位司机将要做什么。这样才能保证
在其他人做出危险动作时你也不会受到伤害。
防御式编程主要思想:子程序应该不因传入错误数据而被破坏,哪怕是有其他子程序产生的错误数据。
8.1 Protecting Your Program from Invalid Inputs
保护程序免遭非法输入数据的破坏
·检查所有来源于外部的数据的值
·检查子程序所有输入参数的值
·决定如何处理错误的输入数据
8.2 Assertions
断言
Building Your Own Assertion Mechanism
建立自己的断言机制
Guidelines for Using Assertions
使用断言的指导建议
1. 用错误处理代码来处理预期会发生的状况,用断言来处理绝不应该发生的状况。
有种方式可以让你更好地理解断言,那就是把断言看做是可执行的注解。
2. 避免把需要执行的代码放到断言中。
如果把代码写入断言中,那么当你关闭断言功能时,编译器很可能就把这些代码排除在外了。
3. 用断言来注解并验证前条件(Preconditions)和后条件(postconditions)。
4. 对于高建壮性的代码,应该先使用断言再处理错误
8.3 Error-Handing Techniques
错误处理技术
1. 返回中立值
2. 换用下一个正确的数据
3. 返回与前次相同的值
4. 换用最接近的合法值
5. 把警告信息记录到日志中
6. 返回一个错误码
7. 调用错误处理子程序或对象
8. 当错误发生时显示出错误消息
9. 用最妥当的方式在局部处理措施
10. 关闭程序
Robustness vs. Correctness
健壮性与正确性
正确性意味着永远不返回不准确的结果,哪怕不返回结果也比返回不准确的结果好。然而,健壮性则意味着要不断尝试采取某些措施
,以保证软件可以持续地运转下去,哪怕有时做出一些不够准确的结果。
High-Level Design Implications of Error Processing
高层次设计对错误处理方式的影响
8.4 Exceptions
异常
1. 用异常通知程序的其他部分,发生了不可忽略的错误。
2. 只在真正例外的情况下才抛出异常。
3. 不能用异常来推卸责任
4. 避免在构造函数和析构函数中抛出异常,除非你在同一地方把它们捕获。
5. 在恰当的抽象层次抛出异常。
当你决定把一个异常传给调用方时,请确保异常的抽象层次与子程序接口的抽象层次是一致的。
6. 在异常消息中加入关于导致异常发生的全部消息
7. 避免使用空的Catch语句
8. 了解所用函数库可能抛出的异常
9. 考虑创建一个集中的异常报告机制
10. 把项目中对异常的使用标准化。
11. 考虑异常的替换方案
8.5 Barricade Your Program to Contain the Damage Caused by Errors
隔离程序,使之包容由错误造成的损害
让软件的某些部分处理“不干净”的数据,而让另一些部分处理“干净的”数据,即可让大部分代码无须再担负检查错误数据的职责。
在输入数据时将其转换为恰当的类型
Relationship Between Barricades and Assertions
隔栏与断言的关系
8.6 Debugging Aids
辅助调试的代码
Don't Automatically Apply Production Constraints to the Development Version
不要自动地把产品版的限制加强与开发版之上
Introduce Debugging Aids Early
尽早引入辅助调试的代码
Use Offensive Programming
采用进攻式编程
应该以这么一种方式来处理异常情况:在开发阶段让它显现出来,而在产品代码运行时让它能够自我恢复。----“进攻式编
程(offensive programming)”
Plan to Remove Debugging Aids
计划移除调试富足的代码
1. 使用类似ant和make这样的版本控制工具和make工具
2. 使用内置的预处理器
3. 编写自己的预处理器
4. 使用调试存根
8.7 Determining How Much Defensive Programming to Leave in Production Code
确定在产品中代码中该保留多少防御式代码
1. 保留那些检查重要错误的代码
2. 去掉检查细微错误的代码
3. 去掉可以导致程序硬性崩溃的代码
4. 保留可以让程序稳妥地崩溃的代码
5. 为你的技术支持人员记录错误信息
6. 确认留在代码中的错误消息是友好的
8.8 Being Defensive About Defensive Programming
对防御式编程采取防御的姿态
过度的防御式编程也会引起问题。如果你在每一个能想到的地方用每一种能想到的方法检查从参数出入的数据,那么你的程序员将会
变得臃肿而缓慢。
Key Points 要点
1. 最终产品代码中对错误的处理方式要比“垃圾进,垃圾出”复杂得多。
2. 防御式编程技术可以让错误更容易发现,更容易修改,并减少错误对产品代码的破坏。
3. 断言可以帮助人尽早发现错误,尤其是在大型系统和高可靠性的系统中,以及快速变化的代码中。
4. 关于如何处理错误输入的决策是一项关键的错误处理决策,也是一种关键的高层设计决策。
5. 异常提供了一种与代码正常流程角度不同的错误处理手段。如果留心使用异常,它可以成为程序员知识工具箱中的一项有益补充
,同时应该在异常和其他错误处理手段之间进行权衡比较。
6. 针对产品代码的限制并不适用于开发中的软件。你可以利用这一优势在开发中添加有助于更快地排查错误的代码。