9防御式编程剖析

上传人:今*** 文档编号:107637522 上传时间:2019-10-20 格式:PPT 页数:52 大小:1,011.50KB
返回 下载 相关 举报
9防御式编程剖析_第1页
第1页 / 共52页
9防御式编程剖析_第2页
第2页 / 共52页
9防御式编程剖析_第3页
第3页 / 共52页
9防御式编程剖析_第4页
第4页 / 共52页
9防御式编程剖析_第5页
第5页 / 共52页
点击查看更多>>
资源描述

《9防御式编程剖析》由会员分享,可在线阅读,更多相关《9防御式编程剖析(52页珍藏版)》请在金锄头文库上搜索。

1、防御式编程 Defensive Programming,任课老师:黄武,上午11时37分,52,2,上午11时37分,提纲,保护程序免遭非法输入数据的破坏 断言 错误处理技术 异常 隔离程序 辅助调试代码,上午11时37分,52,3,上午11时37分,1.保护程序免遭非法输入数据破坏,如何做到防御式驾驶?,上午11时37分,52,4,上午11时37分,1.1 主动防御的思想,防御式编程的主要思想是:子程序不因传入错误数据而被破坏,哪怕是由其它子程序产生的错误数据 其核心是承认程序都会有问题,都需要被修改,这是保护的基础 防御式编程是针对程序外部的保护,问题,你如何保护你的程序免遭外部数据的影响

2、?,52,5,上午11时37分,上午11时37分,52,6,上午11时37分,1.2 如何处理非法数据,通常有三种方法来处理非法数据 检查所有来源于外部数据的值 检查子程序所有输入参数的值 决定如何处理错误的输入数据,上午11时37分,52,7,上午11时37分,1.2.1检查所有来源于外部的数据,外部数据来源于文件,用户输入,网络或其它外部接口,应检查这些值是否在合法的范围之内,外部数据源,上午11时37分,52,8,上午11时37分,1.2.2 检查子程序所有输入参数,子程序参数可能是错误的,需要检查 例如 void Get_Process_Type(short shNo) if ( (

3、0=shNo ) ,问题,你如何检查程序的动态错误?,52,9,上午11时37分,上午11时37分,52,10,2. 断言,断言是在开发期间使用的、让程序在运行时自检的代码 断言为真,则表明程序运行正常,断言为假,则说明程序发生错误,如 assert( !strOrigFileName.empty() ); 断言对于大型复杂程序或可靠性要求极高的程序而言非常有效,程序员可以通过断言快速定位程序中的关键错误,上午11时37分,上午11时37分,52,11,上午11时37分,2.1 断言能够检查到的错误,输入参数或输出参数取值处于预期范围内 子程序开始(或结束)时文件或流是处于打开(或关闭)状态

4、子程序开始(或结束)时文件或流的读写位置位于开头(或结尾)处 文件或流已用只读、只写或读写方式打开 仅用于输入的变量的值没有被子程序所修改 指针非空 传入子程序的数组或其他容器至少能容纳X个数据元素 表已经初始化,存储着真实的数据,上午11时37分,52,12,上午11时37分,2.2 断言的表达,断言通常含有两个参数:布尔表达式和消息,比如 assert( denominator !=0, “ denominator is unexpectedly equal to 0 ” ); 有些语言不直接支持断言语句,可以自己构建断言机制,下面是一个c+的断言: #define ASSERT( con

5、dition, message ) if ( ! ( condition ) ) LogError ( “ Assertion failed: ”, #condition, message ); exit ( EXIT_FAILURE ); ,上午11时37分,52,13,2.3 什么时候使用断言,断言主要用于开发和维护阶段 断言只在开发阶段被编译到目标代码中,而在生成产品代码时不编译到产品代码中,上午11时37分,上午11时37分,52,14,上午11时37分,2.3.1 断言和错误处理的使用状况,断言(assertion)用来检查永远不应该发生的状况,断言用于检查代码中的bug,因此断言通

6、常采用强制退出程序的方式 错误处理(error-handling code)用来检查程序的非正常状况,这些情况能在写代码时就预料到,比如从文件读取的汽车速度数据,应该在0-300Km/h范围内,超出了这个范围被认为数据出错,上午11时37分,52,15,上午11时37分,2.3.2 避免把执行代码放到断言中,如果把代码放到断言中,则在产品发布时关闭断言后这些代码将不被执行,例如,下面的方式不可取 Debug.Assert( PerformAction ( ) ) 上面的代码可以做如下修改: actionPerformed = PerformAction() Debug.Assert( acti

7、onPerformed ),上午11时37分,52,16,2.3.3 前条件和后条件,使用断言保护前条件和后条件 前条件(Precondition)子程序或类的调用方法在调用其子程序或实例化对象之前要确保为真的属性 前条件是调用方代码对其所调用代码的承诺 后条件(Postcondition)子程序或类方法在执行结束后要确保为真的属性 后条件是子程序或类方法对调用方代码的承诺,上午11时37分,上午11时37分,52,17,2.3.3.1 前条件和后条件举例,上午11时37分,Visual Basic示例:使用断言来记述前条件和后条件 Private Function Velocity( - B

8、yVal latitude As Coordinate, - ByVal longitude As Coordinate, - ByVal elevation As Coordinate - ) As single Preconditions Debug.Assert ( -90 = latitude And latitude = 90 ) Debug.Assert ( 0 = longitude And longitude 360 ) Debug.Assert ( -500 = elevation And elevation = 75000 ) Postconditions Debug.As

9、sert ( 0 = returnVelocity And returnVelocity = 600 ) return value Velocity = returnVelocity End Function,上午11时37分,52,18,上午11时37分,2.3.4 先使用断言再使用错误处理,通常而言,要么使用断言,要么使用错误处理,但有时也同时使用,上午11时37分,52,19,上午11时37分,3. 错误处理技术,错误处理技术(Error-Handling Techniques)用于处理那些能够预测的数据出错,常见的处理方法包括: 返回中立值 换用下一个正确的数据(实时系统) 返回与前次

10、相同的数据(数据处理) 换用最接近的合法数据(预先设置),上午11时37分,52,20,上午11时37分,3.1 其他错误处理技术,把警告信息记录到日志文件中 返回一个错误码(设置状态变量) 调用集中的错误处理子程序或对象 当错误发生时显示出错消息 最妥当的方式是在局部处理错误 关闭程序,上午11时37分,52,21,上午11时37分,3.1.1 错误处理技术举例,if( ( shChannel_No MAX_CHANNEL_NUMBER ) shChannel_No = 0; / 返回中立值 if( iHeart_Rate MAX_HEART_RATE ) iHeart_Rate = iLa

11、st_Heart_Rate; / 返回上一次的值 if( ( iVelocity MAX_VELOCITY ) iVelocity = DEF_VELOCITY; / 返回默认值 ,上午11时37分,52,22,上午11时37分,3.1.2 集中的错误处理子程序,构建一个集中的错误处理程序,所有错误处理都由其完成 优点:调试简单 缺点:整个程序都和这个集中错误处理点发生耦合,上午11时37分,52,23,上午11时37分,3.2 正确性和健壮性,正确性(Correctness)是指永不返回不准确的结果,即遇到不准确的结果时不返回,比如医疗检查 人身安全攸关软件往往更倾向于正确性 健壮性(Rob

12、ustness)是指不断尝试采取某种措施,以保证软件可以持续地运转下去,那怕是做出一些不准确的结果,比如视频播放 消费类软件更注重健壮性,上午11时37分,52,24,上午11时37分,3.3 高层设计对错误处理方式影响,应该在整个程序里采用一致的方式处理非法参数,通用的错误处理决策,涉及到软件构架的设计决策 对于高可靠性的系统,在软件构架中可以设计不同层次的错误处理,比如异常的处理,可以设置通用的错误处理方式,比如日志记录,返回值检查等,这些问题只有在构架层次上设计才能够达到统一,上午11时37分,52,25,上午11时37分,4 异常,异常(Exceptions)是把代码中的错误或异常事件

13、传递给调用方代码的一种特殊手段 异常的基本结构是:子程序使用throw抛出一个异常对象,再被调用链上层其他子程序的try-catch语句捕获,上午11时37分,52,26,上午11时37分,4.1 不同语言对异常的支持,表8-1 支持几种流行的编程语言的表达式,上午11时37分,52,27,4.2 使用异常的建议,用异常通知程序的其它部分,发生了不可忽略的错误 只在真正例外的情况下抛出异常 不能用异常来推卸责任 避免在构造函数或析构函数中抛出异常 在恰当的抽象层次抛出异常 在异常消息中加入关于异常发生的全部信息 避免使用空的catch语句 考虑创建一个集中的异常报告机制 考虑异常的替换方案,上

14、午11时37分,52,28,上午11时37分,4.2.1在恰当的层次抛出异常,子程序应该在其接口中展现一致的抽象,抛出的异常也是程序接口的一部分,上午11时37分,52,29,上午11时37分,4.2.2 避免使用空的Catch语句,空的Catch语句意味着程序存在问题,Java示例:忽略异常的错误做法 try / Lots of code catch ( AnException exception ) ,Java示例:忽略异常的正确做法 try / Lots of code catch ( AnException exception ) LogError( “ Unexpected exce

15、ption “ ); ,上午11时37分,52,30,上午11时37分,4.2.3 考虑创建集中的异常报告机制,Visual Basic示例:集中的异常报告机制(第一部分) Sub ReportException ( _ ByVal className, _ ByVal thisException As Exception, _ ) Dim message As String Dim caption As String message = _ “ Exception: “ & thisException.Message & “.” & ControlChars.CrLf & _ “ Class

16、: “ & className & ControlChars.CrLf & _ “ Routine: “ & thisException.TargetSite.Name & ControlChars.CrLf & _ caption = “ Exception “ MessageBox.Show ( message, caption, MessageBoxButtons.OK , _ MessageboxIcon.Exclamation ) End Sub,构建自己的异常报告函数,上午11时37分,52,31,上午11时37分,4.2.3 考虑创建集中的异常报告机制(续),Visual Basic示例:集中的异常报告机制(第二部分) Try Catch exceptionObject As Exception Reportexception ( CALS

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号