Home Tags Posts tagged with "代码大全"

代码大全

主要思想:子程序应该不因传入错误数据而被破坏,哪怕是由其他子程序产生的错误数据;更一般地说,其核心想法是承认程序都会有问题,都需要被修改,聪明的程序员应根据这一点来编程;

 

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

好的程序:“垃圾进,什么都不出”,“进来垃圾,出去出错提示”或者“不许垃圾进来”;

通常有三种方法来处理垃圾的情况

检查所有源于外部的数据的值;数值在它可接受的取值范围内;字符串不超长;注意可能攻击系统的数据等;

检查子程序所有输入参数的值;同上,差别在于数据来源于其他子程序;

决定如何处理错误的输入数据;一旦检测到非法数据,按照合理方案进行处理;

 

断言:在开发期间使用的,让程序在运行时进行自检的代码(通常是一个子程序或宏)。断言为真,贼表明程序运行正常,断言为假,则它已经在代码中发现了意料之外的错误;

举例:系统假定一份客户信息文件所含的记录数不可超过50000,那么程序中可以包含一个断定记录数小于等于50000的断言。若记录数小于等于50000,这一断言会默默无语,否则它会大声地“断言”说程序存在一个错误;

作用:对大型的复杂程序或可靠性要求极高的程序来说尤其有用,通过使用断言,程序员能更快速地排查出因修改代码或者别的原因,而弄进程序里的不匹配的接口假定和错误等;

格式:两个参数:一个描述假设为真时的情况的布尔表达式;一个断言为假时需要显示的信息;

写法:assert denominator !=  0: “denominator is unexpectedly equal to 0.”;

声明denominator不会等于0;参数denominator != 0 是个布尔表达式;第二个参数是当第一个参数为false—断言为假时—所打印的消息;

检查假定类型

输入参数或者输出参数的取值处于预期的范围内;

子程序开始(或结束)执行时文件或流时处理打开(或关闭)的状态;

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

文件或流已用只读,只写或可读可写方式打开;

仅用于输入的变量的值没有被子程序所修改;

指针非空;

传入子程序的数组或其他容器至少能容纳X个数据元素

表已初始化,存储着真实数值;

子程序开始(或结束)执行时,某个容器是空的(或满的);

一个经过高度优化的复杂子程序的运算结果和相对较慢但代码清晰的子程序的运算结果相一致;

说明正常情况下,不希望用户看到产品代码中的断言信息,即断言主要用于开发和维护阶段。通常,断言只在开发阶段被编译到目标代码中,而在产生产品代码时并不编译进去,在开发阶段,断言可以帮助查清相互矛盾的假定,预料之外的情况以及传给子程序的错误数据等;在生成产品代码时,可以不把断言编译进目标代码里去,以免降低系统的性能;

使用断言的指导建议

用错误处理代码来处理预期会发生的状况,用断言来处理绝不应该发生的状况;

用错误处理代码来处理反常情况,程序就能从容地对错误做出反映,如果发生异常情况时触发了断言,那么要采取的更正的措施就不仅仅是对错误做出恰当的反映了—而是应该修改程序的源代码并重新编译,然后发布软件的新版本;

避免把需要执行的代码放到断言中;

用断言来注解并验证前条件和后条件(契约式设计);

前条件:子程序或类的调用方法代码在调用子程序或实例化对象之前要确保为真的属性,前条件是调用方代码对其所调用的代码要承担的义务;

后条件:是子程序或类在执行结束后要确保为真的属性,后条件是子程序或类对调用方代码所承担的责任;

断言:用来说明前条件和后条件的有力工具,判断前条件和后条件是否为真;

对于高健壮性的代码,应该先使用断言再处理错误;断言可以帮助再开发阶段排查出尽可能多的错误;

 

错误处理技术

断言用于处理代码中不应发生的错误,如何处理预料之中可能发生的错误呢?

可以选择:返回中立值,换用下一个正确数据,返回与前次相同的值,换用最接近的有效值,在日志文件中记录警告信息,返回一个错误码,调用错误处理子程序或对象,显示出错信息或者关闭程序—或把这些技术结合;

返回中立值:继续执行操作并简单的返回一个无害数值;如数值计算返回0,字符串操作返回空字符串,指针操作返回空指针;

换用下一个正确的数据:处理数据流时,有时只需返回下一个正确的数据即可;

返回与前次相同的数据:返回前一次的读取结果,如体温测量,空气检测等,但银行取款不可使用;

换用最接近的合法值:温度计校准在0到100摄氏度之间,检测到一次小于0的结果,则替换为0,即最接近的合法值,如倒车时,车上无法表示负速度,因此简单地显示0,即最接近的合法值;

把警告信息记录到日志文件中:检测到错误数据时,在日志文件log file中记录一条警告信息,然后继续执行,结合其他错误处理技术使用;

返回一个错误码;

调用错误处理子程序或对象:错误处理集中在一个全局的错误处理子程序或对象中,将错误处理的职责集中到一起,从而使调试工作更简单;但安全性:如果代码发生了缓冲区溢出,则不再安全;

当错误发生时显示出错消息;

最稳妥的方式在局部处理错误;

关闭程序:适用人身安全的应用软件,如治疗癌症病人的设备,一旦输入的药剂异常立刻关闭程序才是最佳选择;

正确性与健壮性正确性意味着永不返回不准确的结果,哪怕不返回结果也比返回不准确的结果好,然后,健壮性则意味着要不断尝试采取某些措施,以保证软件可以持续地运行下去,哪怕有时做出一些不够准确的结果;

人身安全相关的软件更倾向于正确性;

消费类应用软件更注重健壮性而非正确性;

高层次设计对错误处理方式的影响

应该在整个程序里采用一致的方式处理非法的参数,确定一种同意的处理错误参数的方法,是架构层次的设计决策;

一旦确定了某种方法,需要确保始终如一地贯彻这一方法;如果你决定让高层的代码来处理错误,而底层的代只需简单地报告错误,那么就要确保高层代码真的处理了错误;

防御式编程全部的重点就在于防御哪些你未曾预料到的错误;