面向健壮性的软件构造
健壮性
系统在不正常输入,或不正确外部环境下仍能够表现正常的程度
面向健壮性的编程
- 处理未期望的行为和错误终止
- 即使终止执行,也要准确、无歧义展示错误信息
- 错误信息有助于debug
正确性:
永不给用户错误的结果 , 倾向直接报错→对内,倾向于正确
健壮性:
尽可能保持软件运行,倾向于容错→对外,倾向于健壮
error→defect / fault / bug(缺陷)→failure(失效)
测试正确性和健壮性
→MTBF(平均失效时间)外部观察
→defects / KLOC (每千行代码遗留bug数量)
异常处理技术
Error(内部错误)、设备错误、物理限制
Exception(异常):程序导致的问题 , 可以捕获、处理
↓↓↓
执行中的非正常事件, 程序无法再按照预想流程执行、return 之外的第二种退出途径
Throwable继承树:
RuntimeException运行时异常,是源程序代码中引入fault造成的
Unchecked Exceptions:
不需要在编译的时候catch→不需要不代表不能,所有Thrownable实现类均能实现catch
Checked Exceptions:
必须catch,否则无法通过编译
自定义异常可以通过继承Exception或Exception其余子类
五个关键字:
try / catch / finally / throws / throw
通过throws声明checked exceptions:
异常时return之外第二种退出方法,是方法和client端之间 spec 的一部分,在post-con刻画
LSP:
子类型可以抛出比父类型更少异常 , 但不能更宽泛
try / catch异常
尽量在本方法内处锂 ,实在不行向上传递
自己不知如何处理,交由client处理
chaining Exceptions:
try{
…
}catch ( xx Exception e )
throw new YYExceptionc (e) ;
**finally块 **
异常发生后对资源进行合理清理( inclose )
Analyzing state Face (分析栈调用)
函数调用栈:后进先出 ( 先被调用的函数在栈底)
断言和防御式编程 (侧重于 convectness ):
防御式编程:
- make bugs impossible
- 限定bugs在 尽可能小的范围 ⇒ fail fast
( 使用断言检查 pre-condition 是一种典型方式)
**使用 Assert **:
→内部不变量 . Rep Invariant , 控制流不变量
→方法的前置、后置条件
异常处理:
预料到可以发生的不正常情况
断言处理:
绝不应该发生的情况
对于pre-和post-condition使用Assert:
- 如果参数来自于外部,用异常
- 如果参数来自于自己的其他代码,可以使用断言
**防御式编程 ( Defensive Programming ) 技术 **
1)断言( Assertions )
2)异常 (Exceptions)
3)Protecting Programs From Invalid inputs 对于来自外部的数据的细检查 . 并决定其合活性
4)Barricade ( 设置路障)
5)Debugging Aids
Debugging:
目的:寻求错误的根源并消除
复现 ( Reproduce) Bug:从最小的测试用例开始
诊断 ( Diagnoses) Bug:
修复(常与refactor联系)
反思
Testing:
程序正确性确认方法
→形式化推理
→代码评审
→测试