12 Construction for Robustness and Correctness
面向正确性与健壮性的软件构造
- 健壮性和正确性
Robustness 健壮性:系统在不正常输入或不正常外部环境下仍能表现正常的程度
面向健壮性的编程:1.处理未期望的行为和错误终止
2.即使终止执行,也要准确/无歧义的向用户展示错误信息
3.错误信息有助于进行debug
对别人宽容点,对自己狠一点
Correctness正确性:程序按照spec加以执行的能力,是最重要的质量指标!(永不给用户错误的结果)
正确性倾向于直接报错(ERROR),健壮性则倾向于容错。
- 怎么评估正确性和健壮性?
外部观察角度:MTBF---平均失效间隔时间:失效间隔时间的期望值
内部观察角度:Residual defect rates 残余缺陷率:每千行代码中遗留的bug的数量
- Error和Exception
Throwable是Error和Exception的超类
对于Error,程序员通常无能为力,一旦发生了,只能想办法让程序优雅的结束
对于异常,自己程序导致的问题,可以捕获,可以处理
异常:程序执行中的非正常事件,程序无法再按照预想的流程执行。
异常可以分为两类,一类是运行时异常RuntimeException和其他异常
运行时异常:由程序员在代码里处理不当造成的
其他异常 :由外部原因造成的
RuntimeException运行时异常,是因为程序的源代码引入的故障
比如:ArrayIndexOutOfBoundsException、NullPointerException。。。
非运行时异常是程序员无法完全控制的外在问题所导致的,比如IO异常。
- Checked and Unchecked exception
Error和RuntimeException是Unchecked的,其余的都是Checked的
对于UnChecked Exception:
可以不处理,编译没问题,但执行时出现就代表程序失败,代表程序中的潜在bug
Unchcked异常也可以使用throws声明或try/catch进行捕获,但大多数时候是不需要的,也不应该这么做
对于Checked Exception :
必须catch并处理这个异常,或者通过throws这个异常,告诉编译器你处理不了。
必须捕获并指定错误处理器handler,否则编译无法通过
当要决定是采用checked exception还是unchecked exception时候,问一个问题:
如果这种异常一旦抛出,client会做怎么样的补救?
如果客户端可以通过其他方法恢复异常,那么采用checked exception
如果客户端对这种异常无能为力,采用unchecked exception
异常出现的时候,要做一些试图恢复他的操作而不仅仅只打印他的信息。
尽量使用unchecked exception来处理编程错误,因为不用使客户端代码显式的处理他们,衙门会在出现的地方挂起程序并打印出异常信息。
Checked exception应该让客户端从中得到丰富的信息
如果想让代码更加易读,倾向于用unchecked exception来处理程序中的错误
程序员必须在方法的spec中明确写清楚本方法会抛出的所有checked exception
结果是false
- 预防bug
最好的防御就是不要引入bug
如果无法避免的话,尝试着将bug限制在最少的范围之内(限定在一个方法之内,不扩散)
Assertions 断言:当程序不满足前置条件时候,可以通过抛出AssertionError异常来快速结束程序,避免扩散fail fast
断言使对代码中程序员所作假设的文档化,也不会影响运行时的性能(实际使用时,assertion都会被disabled)
Assert condition : message 当condition不满足的时候,message会显示给用户
断言默认会关闭,记得打开-ea
断言保证正确性,错误/异常处理使保证健壮性。
断言和异常处理都可以处理同样的错误
client希望使用checked异常,因为可以提示更清晰的错误信息并加以补救,避免程序的直接推出。开发者更倾向于使用unchecked,会让代码更加简洁易读。