12.面向正确性与健壮性的软件构造

面向正确性与健壮性的软件构造

1 健壮性和正确性

  • 健壮性:系统在不正常输入或不正常外部环境下仍能够表现正常的程度

  • 面向健壮性的编程

    • 处理未期望的行为和错误终止
    • 即使终止执行,也要准确/无歧义的向用户展示全面的错误信息
    • 错误信息有助于进行debug
  • 健壮性定律:(Postel’s Law)

    • 程序员应总是假定用户恶意、假定自己的代码可能失败
    • 把用户想象成白痴,可能输入任何东西(因此要向用户返回明确错误信息)
    • 对别人宽容点,对自己狠一点(保证自己的代码必须全部安全、放宽用户的输入要求)
  • 如何实现健壮性:

    • 封闭实现细节,限定用户的恶意行为(用户不应该访问库、数据结构、指针等)
    • 考虑极端情况,没有“不可能”:开发人员考虑如何处理极不可能发生的情况,并相应地执行处理。
  • 和健壮性的区别:

    • 正确性:永不给用户错误的结果,没有结果比不准确的结果要好;倾向于直接报错。有利于生成更简洁、更容易理解和维护的代码
      • 让开发者变得更容易:用户输入错误,直接结束
    • 健壮性:尽可能保持软件运行而不是总是退出,即使这会导致有时不准确的结果;倾向于容错
      • 让用户变得更容易:出错也可以容忍,程序内部已有容错机制
  • 使用方式: 对外的接口,倾向于健壮性;对内的实现,倾向于正确性。在内外部之间做好隔离,防止“错误”扩散

  • 可靠性:系统在规定条件下执行所需功能的能力

2 Throwable

在这里插入图片描述

3 Error/Runtime异常、其他异常

  • Unchecked exceptions
    • Error
    • Runtime异常
    • 编译器不会检查error运行时异常,此外的异常统称为。因为即使出现也解决不了,只有在运行时才会报错,此时需要重新编写代码。
    • 对于Unchecked exceptions而言,不需要在编译时使用try…catch等机制处理。可以不处理,编译没问题,但执行时出现就导致程序失败,代表程序中有潜在的bug。类似于编程语言中的动态类型检查。
  • Checked exceptions
    • 其他异常

4 Checked异常、Unchecked异常

这是从异常处理机制角度所做的分类
Java中的异常结构层次:(红色编译时不报错,蓝色编译时报错)
在这里插入图片描述

5 Checked异常的处理机制:

  1. 通过throws声明已检查的异常

    • 如果遇到无法处理的情况,Java方法可以throw一个异常。一个方法不仅会告诉Java编译器它可以返回什么值,还将告诉编译器可能抛出的异常类型。这样的话,需要在规约的前置条件中写出。
      在这里插入图片描述
  2. 如何抛出异常

    • 找到一个能表达错误的Exception类,或者构造一个新的Exception类
      -构造Exception类的实例,将错误信息写入抛出
      在这里插入图片描述
  3. 捕获异常

    • 异常发生后,如果找不到处理器,就终止执行程序,在控制台打印出栈轨迹。

    • 要捕获异常,请设置try/catch块

    • 如果try块中的任何代码引发catch子句中指定的类的异常,则try中后面的代码不会再执行,执行捕获异常的catch代码;如果try中没有抛出异常,则catch中代码不会被执行

    • catch中也可以继续向上抛出异常,不在本方法内处理,而是传递给调用方,由client处理(“推卸责任”)

    • 原则:

      • 尽量在自己这里处理,实在不行就往上传——要承担责任;但有些时候自己不知道如何处理,那么提醒上家,由client自己处理。
      • 如果父类型中的方法没有抛出异常,那么子类型中的方法必须捕获所有的checked exception,因为子类型方法中不能抛出比父类型方法更多的异常。
        在这里插入图片描述

6 自定义异常类

  • 如果JDK提供的exception类无法充分描述你的程序发生的错误,可以创建自己的异常类

  • 可以创建checked exception,也可以创建unchecked exception。前者需要在方法签名中声明继承自exception类或者其子类,并在方法体中捕获或抛出;后者需要继承运行时异常类,不需要捕获,也不需要声明。

7 断言的作用、应用场合

  • 断言:在开发阶段的代码中嵌入,检验某些“假设”是否成立。若成立,表明程序运行正常,否则表明存在错误

  • 每个断言都包含一个您认为在程序执行时为真的布尔表达式。如果断言不为真,则JVM 会抛出一个断言异常,这意味着代码中有错误,需要被修复;如果断言为真,则表示程序员代码编写没问题,可以继续下一步操作。

  • 断言的两种形式:

assert condition;
assert condition : message;//message在发生错误时显示给用户,便于快速发现错误所在
  • 应用场合
    • 断言主要用于开发和维护阶段,避免引入和帮助发现bug; 实际运行阶段,不再使用断言,避免降低性能

    • 如果条件语句或switch语句不能覆盖所有可能的情况,那么最好使用断言来阻止非法情况。

8 防御式编程的基本思路

  • 对于无效输入的保护机制

  • 断言

  • 异常

  • 特殊的错误处理机制

  • 对外隔离(设置路障)

    • 设置路障的一种方法是将某些接口指定为“安全”区域的边界,检查跨越安全区域边界的数据的有效性,如果数据无效,则做出相应响应。
    • 设置路障的方法:
      • 使用public方法充当隔离舱
      • 类中的public方法会假定数据不安全,它们负责检查数据并对其进行清理;一旦数据被类的公共方法接受,类的私有方法就可以假定数据是安全的。
      • 操作间技术
    • 路障的使用使得断言和错误处理之间有了明显的区别:
      • 路障之外的例程应该使用异常处理函数,因为对数据进行任何假设都是不安全的;
      • 路障内的例程应该使用断言,因为传递给它们的数据已经经过清理,如果路障内的某个例程检测到错误数据,则这是程序中的错误,而不是数据中的错误。
  • 调试辅助手段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SolemnJudgment

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值