天天看点

【代码大全】第8章 防御式编程

第八章 防御式编程

防御式编程的主要思想就是,子程序不应该因为传入错误数据而被破坏。其核心想法就是要承认程序都会有问题,都需要被修改。

处理外来垃圾的方法:检查所有来自外部的数据值,检查子程序的输入参数值,决定如何处理数据。

防御式编码的最佳方式就是一开始代码中引入错误,使用迭代式设计、编码前先写伪代码、写代码前先写测试用例、底层设计检查等活动都可以防止。

断言 在开发阶段使用的,让程序在运行时进行自检的代码。可以利用断言检查如下假定:

n 输入参数或输出参数的取值处于预期范围

n 子程序开始执行(结束)时,文件或流处于打开(关闭)状态

n 子程序开始执行(结束)时,文件或流的读写位置处于开头(结尾)

n 文件或流已打开

n 输入变量的值没有被子程序修改

n 指针非空

n 传入子程序的数组至少能容纳X个元素

n 表已初始化,存储着真实的数据

n 子程序开始(结束)时,容器空(满)

n 一个高度优化过的子程序与一个缓慢的子程序,结果一致

断言只在开发阶段被编译到目标代码中,而在生成代码时不编译进去。使用断言的指导建议:

n 用错误处理代码来处理预期会发生的状况,断言不行!

n 避免把需要执行的代码放入断言中(如果未编译断言呢?)

n 用断言来注解并验证前条件和后条件

n 对于高健壮性的代码,应该先用断言,再处理错误

错误处理技术:返回中立值,换用下一个正确的数据,返回与前次相同的数据,换用最接近的合法值,把警告信息记录到日志文件,返回一个错误码,调用错误处理子程序,显示出错消息,用最妥当的方式在局部处理错误,关闭程序

而处理错误最恰当的方式要根据出现错误的软件的类别而定。

异常 用异常通知程序的其它部分,发生了不可忽略的错误

n 只在真正例外的情况下才抛出异常

n 不能用异常来推卸责任

n 避免在构造函数和析构函数中抛出异常,除非你同时捕获。

n 在恰当的抽象层次抛出异常

n 在异常消息中加入导致异常的全部信息

n 避免空的catch

n 了解函数库可能抛出的异常

n 考虑创建一个集中的异常报告机制

n 把项目中对异常的使用标准化

n 考虑异常的替换方案

隔离程序,使之包容由错误产生的损害,它类似于一个消毒室。

辅助调试

n 尽早引入辅助调试的代码

n 采取进攻式编程(确保断言语句使程序终止,完全填充所有内存,完全填充所有文件或流,删除一个对向前把它填满垃圾数据)

n 计划移除调试辅助的代码(使用版本控制工具,使用内置的预处理器,编写自己的预处理器,使用调试存根)

产品代码中该保留多少防御式代码?

n 保留检查重要错误的

n 去掉检查细微错误的

n 去掉可能导致软件硬性崩溃的

n 保留可以让软件稳妥崩溃的

n 为你的技术支持人员记录错误信息的

n 确认留在代码中的错误信息都很友好

对于防御式编程,采取防御的姿态,避免过度。

继续阅读