软件构造 7-3 断言和防御性编程

    断言和防御性编程

目录回忆:设计和抽象数据类型

断言

  什么断什么不断

  使用断言的指导方针

防御性编程

  防御型编程的技巧

回忆

第一层防御:使bugs不可能

  最好的防御bug的方法就是在设计的时候就尽量避免bug

  - 静态检查:在编译的时候,可以抓住许多bug

  - 动态检查:比如数组溢出

  -  不变量:不变量

  -  防御性拷贝

  - 引用不变量:by final

第二种防御:

  如果bug不能被阻止,则限制在尽可能小的范围内

  问题越早发现,越容易被修复

  利用assertion检查前置条件的满足性如上图,抛出异常

  检查前置条件是防御性编程的一种方式

断言

什么是?

断言用于运行时检查代码的正确性

每个断言都有一个boolean表达式(你认为正确)

如果不正确,JVM会抛出AssertionError。

断 言要优于if-else语句:1.对程序中的假设起到适当的文档作用;2.在实 际运行时不会带来性能问题(在实现运行时断言可被禁止)。

断言通常需要两个参数(也可以只有表达式)

-一个正误表达式,假设其为正确的

-message表示如果失败的信息

为什么?

测试 不变性是否保持,同时起到了文档说明作用

验证编程者的理解

提高程序的无bug自信

使黑盒测试变为白盒

能被用于验证

  内部不变量

  类不变量

  控制流不变量

  方法的前置条件

  方法的后置条件

什么去断什么不断?

  用

   输入值是否在指定的范围内

   文件或流是否打开关闭

   文件或流的读写控制

   读入参数是否被修改

   是否为空指针

   数组长度

   Table已经初始化去包含真实值

   容器类是否为空或者为满

   两个结果是否匹配

   (开发时用来帮助发现错误,分布时禁用)

  不用

   断言不是免费的,需要慎用

   可以信任的内容比如x+1

   不要用断言来测试外部情况,文件是否存在,输入正确性,网络是否可用,断言用于检测内部的内容

   外部导致的不是bug程序无法预测和控制,外部应该用exception机制来处理

在开发过程中打开断言。

  java默认关闭断言。建议,如果对性能影响不大,可以在发布版本中保留

  

注意这里的断言和Junit的测试里面的断言方法不一样,这里是用来正文中使用的。

断言的使用原则

  断言和异常机制:

    断言使正确性(处理不该发生的)

    异常时健壮性(不知道什么时候发生的)

  Exception处理错误的输入 数据,断言检查bugs

  断言在大型复杂程序和高可靠性程序中特别有用

  运行时关闭断言

  断言用于前置和后置条件(Use Assertions for pre-/post- conditions )

真实世界的程序和项目往往太杂乱,不能完全依 靠断言。

防御性编程

  防御性编程是防御性设计的一种形式,旨 在确保在不可预见情况下软件持续提供功能的能力

   主要思想:如果某个方法被传入了不良数据,即使这 是另一个子程序的错误,方法本身也不会受到破坏。

    (就像开车,不管别人做了怎样危险的事,你要保证自己的安全避让或正常行驶)

   优点

      提升代码质量

      使代码更加可以理解

      软件在可以预测的情况下运行,不管其他程序怎么样1

防御性编程的技巧

  包括了了前面的的断言和异常处理

1.在出现了无效的输入

    输入垃圾,输出垃圾(这样不好)。我们从不输出垃圾,不管他输入的是不是垃圾  

    检查外部输入的数据

    检查每个常规的参数

    决定如何处理不好的输入

2.隔栏

    隔栏是一种容损策略 ,起到防火墙的作用(对进来的数据进行消毒,对错误敏感反应)

    One way to barricade for defensive programming purposes is to designate certain interfaces as boundaries to “safe” areas.Check data crossing the boundaries of a safe area for validity and respond sensibly if the data isn’t valid. 

    类的public方法中假设数据是 不安全的,他们负责检查和清洗;private方法则认为被公有方法接收 处理后的数据是安全的。

    类似于手术室管理,进入之前消毒,之后认为安全

    在输入时将输入数据转换为适当的类型

  隔栏的实现可以体现断言和异常的区别

    外部隔栏使用错误(异常)处理

    内部隔栏使用断言

  隔栏的使用也展示了在架构级别如何处理错误,决定哪些代码位于 内部,哪些位于隔栏之外是架构级决策

3.bug急救(Debugging Aids)调试助手(见7.4)

   不要把产品版的限制强加于开发版之上

    在开发过程中牺牲速度和对资源的使用,以换取可以使开发更顺利的内置 工具。

    使用进攻式编程 :对异常的处理:在开发阶段让异常尽可能明 显的展示出来,而在产品运行时让异常能够自我恢复。 --进攻式编程

    尽可能使程序失败 ,Sometimes the best defense is a good offense(最好的防御是进攻),开发时失败地越严重,发布后失败地越轻微。

    做好计划,避免调试用代码和程序代码纠缠不清。

      - 使用版本控制和生成工具,如make

      - 使用内置的预处理器。

    编写你自己的的预处理器

      - 如果该语言不包含的话

    使用调试存根(不知道在说什么看完7.4再说)

开发中,希望错误尽可能明显;发布后,希望错误尽可能 不明显。

    保留检查重要错误的代码 :确定程序的哪些部分能够承受未检测 出错误而造成的后果,哪些不能。 

    删除检查琐碎错误的代码 : 如果错误的后果微不足道,可以删除检测代码 |并不是物理删除 ,要利用版本控制或者make工具 

    删除导致硬崩溃的代码:会造成严重错误的调试代 码(如数据丢失),应该被移除 

    保留帮助优雅退出的代码:如果程序包含检测潜在致命错误的调试代码,可将这些调 试代码保留,以使程序稳妥的崩溃。 

    日志错误和友好错误消息:考虑在产品代码中留下调试代码,但改变他们的行为,以便适合 生产版本。如在产品中禁用断言,但把断言转换为将消息记录入日志中。确保您留下的错误消息是友好的。 

   

考虑在产品代码中留下调试代码,但改变他们的行为,以便适合 生产版本。如在产品中禁用断言,但把断言转换为将消息记录入日志中。

原文地址:https://www.cnblogs.com/hitycy/p/10897424.html

时间: 2024-08-28 03:53:35

软件构造 7-3 断言和防御性编程的相关文章

【软件构造】第七章第三节 断言和防御性编程

第七章第三节 断言和防御性编程 本节:第2种技术--断言.防御式编程 Outline 断言 什么是断言 断言的应用场景 防御式编程(不是考点,不加叙述) Notes: ## 断言 [什么是断言] 作用:允许程序在运行时检查自己,测试有关程序逻辑的假设,如前置条件.后置条件.内部不变量.表示不变量.控制流不变量等 目的: 为了在开发阶段调试程序.尽快避免错误 使用阶段: 断言主要用于开发阶段,避免引入和帮助发现bug 实际运行阶段, 不再使用断言 软件发布阶段,禁用断言避免影响性能. [应用场景]

软件构造 第七章第三节 断言和防御性编程

第七章第三节 断言和防御性编程 断言:在开发阶段的代码中嵌入,检验某些"假设"是否成立.若成立,表明程序运行正常,否则表明存在错误. 可用于检查: 内部不变量: 表示不变量: 控制流不变量 方法的前置条件 方法的后置条件 断言主要用于开发阶段,避免引入和帮助发现bug 实际运行阶段, 不再使用断言 软件发布阶段,禁用断言避免影响性能. 断言?Correctness 错误/异常处理?Robustness Defensive Programming 对来自外部的数据源要仔细检查,例如:文件

iOS防御性编程

防御性编程是一种细致.谨慎的编程方法.为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能地“保护”自己.我们通过明确地在代码中对设想进行检查,击碎了未记录下来的设想.这是一种努力,防止(或至少是观察)我们的代码以将会展现错误行为的方式被调用. 防御性编程是一种编程习惯,是指预见在什么地方可能会出现问题,然后创建一个环境来测试错误,当预见的问题出现的时候通知你,并执行一个你指定的损害控制动作,如停止程序执行,将用户重指向到一个备份的服务器,或者开启一个你可以用来诊断问题的调试信息.这些防

防御性编程【转】

http://www.cnblogs.com/bakari/archive/2012/08/27/2658215.html 本篇是我根据网上的一些陈述经过整理和总结而得.其中详细的内容我会标注出处.看不懂的可以查看原文. 一.什么事防御性编程 详细请见:http://www.uml.org.cn/codeNorms/201007165.asp 防御性编程是一种细致.谨慎的编程方法.为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能地“保护”自己.我们通过明确地在代码中对设想进 行检查,

防御性编程(转载)

本篇是我根据网上的一些陈述经过整理和总结而得.其中详细的内容我会标注出处.看不懂的可以查看原文. 一.什么事防御性编程 详细请见:http://www.uml.org.cn/codeNorms/201007165.asp 防御性编程是一种细致.谨慎的编程方法.为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能地“保护”自己.我们通过明确地在代码中对设想进行检查,击碎了未记录下来的设想.这是一种努力,防止(或至少是观察)我们的代码以将会展现错误行为的方式被调用. 防御性编程是一种编程习惯

软件构造 7-1 健壮性与安全性

健壮性与安全性 什么是健壮性与安全性? 如何衡量健壮性与安全性? 健壮性:系统或组件在存在无效输入或压力环境时一颗正确运行的程度. 健壮性编程关注异常终止和异常活动的处理. 健壮性原则:严于律己(满足specification),宽以待人(接受各种输入) 健壮性编程原则(把用户当做小孩) 1.用户会修改代码,而且自己写的还不对 2.用户不会看specification(所以我们应该在他操作错误时返回明确的错误信息帮助其改正) 3.危险行为,我们不应当将信息暴露给用户,以至于产生漏洞,使用户专注于

软件构造-犯错的艺术——健壮性与正确性,异常,防御式编程,debugging与test的思考与总结

健壮性与正确性 健壮性与正确性是不同的——一个倾向于使程序尽可能保持运行,即使遇到错误,一个倾向于使程序尽可能正确,不在意保持运行 异常 异常分为两种——checked exception与unchecked exception 二者的区别在于: checked exception需要显式的处理,说白了就是编程者必须要么用catch抓住它,然后在try中想办法处理掉,要么显式的将这个异常扔到调用的上一级方法,也就是甩锅.总而言之,你永远不能无视checked exception unchecke

【软件构造】第一章 软件构造基础(2)

二.软件构造的质量目标 1. 外部属性(主要):影响用户感受,如外观.速度等 (1)正确性:符合规格范围和计划目标 ·只保证各个层面的正确性(假设调用正确) ·检验与调试 ·防御性编程 ·形式化编程 (2)健壮性:响应规格范围外的异常情况 ·提示错误信息 ·正常退出或降级 (3)可扩展性:提供增加新功能的空间 ·固化需求以规避风险 ·设计简洁.离散化 (4)可复用性:使软件模块能够被其他程序使用 ·模式固化 (5)兼容性:跨平台.跨软件交互 ·使用标准文件格式.数据结构.接口,保持一致性 ·定义

【软件构造】第三章

不变量 好的ADT其中最重要的一点就是它会保护/保留自己的不变量. 不变量是一种属性,它在程序运行的时候总是一种状态,而不变性就是其中的一种:一旦一个不变类型的对象被创建,它总是代表一个不变的值. 当一个ADT保护/保留自己的不变量时,对代码的分析会变得更简单.例如,你能够依赖字符串不变性的特点,在分析的时候跳过那些关于字符串的代码:或者当你尝试基于字符串建立其他的不变量的时候,也会变得更简单.与此相对,对于可变的对象,你将不得不对每一处使用它的代码处进行审查. Tweet t = new Tw