《代码大全》 阅读笔记 第八章 防御式编程

        防御式编程的主要思想是:子程序应该不因传入错误的数据而遭到破坏,哪怕是由其他子程序产生的错误数据。程序的作用通常是输入一段数据,然后经过子程序的处理之后,输出一段数据。然而输入的数据可能是非法的,不是所期望的数值,子程序接收并使用的时候,会使得子程序出现错误或者崩溃等。这里的防御式编程就是说,使得程序处理这些非法数据的能力,在力所能及的范围内,拥有处理问题的能力,保护自己。比如除法运算中的除数不能为0。

一、保护程序免遭非法输入数据的破坏

        对于成熟的程序,应该是“垃圾数据进来,什么数据都不出”,保证数据输出的都是正确的数据。

        三种方法来处理进来垃圾数据的情况:

  • 检查所有来源源于外部数据的值

检查所有来自外部的数据值,以确保它在允许的范围之内。对于数值,须确保它在可接受范围内;对于字符串,须确保它的长度没有超长等。。

  • 检查子程序所有输入参数的值

和上一点相似,不同的只是上一点的数据来自外部接口,而这一点的数据来自其他子程序,不是外部接口。

  • 决定如何处理错误的输入数据

需要根据情况的不同,来确定不同的解决方案。

二、断言:

断言这里,不曾了解。没接触过大项目,也没使用过,不过看简介它在复杂程序中检查错误很有效果,以后有机会学习补上。

三、错误处理技术

如何处理这些生活中可预知的错误。

  • 返回中立值

继续执行程序操作,返回一个中立的值。比如整形数据返回0,字符串数据返回null等、

  • 换用下一个正确的值

使用下一个正确的数值来替换,使得程序的继续执行运行下去

  • 返回与前次相同的数据

使用前一个正确的数值来替换,使得程序的继续执行运行下去

  • 换用最接近的合法值

预计正确的数值应该满足一个可接受的数值范围的。当得到的数据不在范围之内的时候,选择距离正确数值范围最近的值作为结果。

  • 把警告信息记录到日志文件中
  • 返回一个错误码
  • 调用错误处理子程序或对象

当发现非法数据的时候,通过调用项目中专门用于处理错误异常的子程序来处理。

  • 当错误发生是显示出错消息
  • 用最稳妥的方法在局部处理错误

发现错误的时候,尽量放在子程序内部完成处理。

  • 关闭程序

虽然很多时候,对非法数据的处理就是在避免程序的关闭。但是一些特殊的行业里面,检测到数据的时候,必须关闭。比如航天,比如医药制造。

健壮性和正确性

正确性:永远不能返回错误的结果,哪怕程序的强制停止。

健壮性:不断的尝试某些措施,以保证程序的正常运行,哪怕返回的数值是错误的。

在处理错误的时候,需要根据不同的行业软件来选择追求正确性还是追求健壮性。

处理错误的方法有很多,但是当项目中选中某一个方法的时候,那么就要确保整个项目采用统一的处理方案。

即使你很确定某个子程序返回的值不会出错,但是你还需要检查其返回的值。

防御式编程的全部重点就在于防御那些你未曾预料到的值。

四、异常

异常是一个将可能出现的错误和异常信息交给调用方处理的特殊手段。

异常需要谨慎明智的使用,容易降低复杂度。草率粗心的使用容易使代码变得无法理解。

使用异常的几个建议:

  • 用异常通知程序的其他部分,发生了不可忽略的错误。 出色的消息通知机制。
  • 只在真正例外的情况下才抛出异常    在通过其他方法实践之后,仍然无法解决的时候,才会抛出异常
  • 不能用异常来推卸责任   异常最好在局部处理,不要抛给上一层处理。而且,子程序将自己的异常交给调用他的人处理,就会暴露出一些实现细节
  • 避免在构造方法和析构方法中抛出异常,除非你在同一个地方把它们捕获   程序的构造函数和析构函数通常执行通常比较复杂、 
  • 在恰当的抽象层次抛出异常   与其他子程序或者类保持一致的抽象性。
  • 在异常消息中加入关于导致异常发生的全部信息  有助于读取异常消息人的工作,方便代码修复
  • 避免使用空的catch语句   空的catch语句,不会输出任何提示性质的语句,会导致编程人员不知道这里出错、
  • 了解所用函数库可能抛出的异常  因为未能提前捕获的异常可能会导致程序的崩溃。
  • 考虑建一个集中的异常报告机制   对异常的集中处理,有利于保持一致性
  • 把项目中对异常的使用标准化  标准化的异常处理机制,有利于代码的编写、阅读和修改等。
  • 考虑异常的替换方案   不停的思考对异常其他的处理方案

五、隔离程序,使之包容由错误造成的损害

在项目中,建立一个隔离仓,里面存放一些理论上不会出错的子程序。外部向里面传送数据的时候,那些数据必须经过合法性的校验,并当数据非法的时候做出及时的响应。

在船体下部分,会将船下面分成很多个块,当其中某一块进水之后,不会遭遇灭顶之灾。

六、辅助测试的代码

  • 不要自动地把产品版的限制强加于开发版之上  产品版本和开发版本,两者的限制要求是不同的。开发版本上增加很多不必要的限制,容易影响开发效率、
  • 尽早引入辅助调试的代码 
  • 采用进攻式编程  什么是进攻式编程?开发阶段勇敢的面对各种异常,产品发布的时候,使之拥有自我修复的功能。这样的做法的好处是,能够在开发阶段遭遇更多的问题,以致于在产品发布之后,产生的问题会相对较少。
  • 计划移除调试辅助的代码  

七、确定在产品代码中该保留多少防御式代码

  • 保留那些检查重要错误的代码
  • 去掉那些检查细微错误的代码
  • 去掉那些可能导致硬性崩溃的代码
  • 保留可以让程序稳妥的崩溃的代码
  • 为你的技术支持人员记录错误信息
  • 确认留在代码中的错误消息是友好的

八、对防御式编程采取防御的姿态

过度的防御式编程的实现,容易构成程序运行的冗余臃肿与缓慢。

需要考虑好在什么地方进行防御,添加什么的防御。然后因地制宜的调整你进行防御式编程的优先级、

posted @ 2012-09-24 16:23  zhouzidan  阅读(1520)  评论(0编辑  收藏  举报