一.正确性与健壮性
健壮性:程序在用户非法输入下,非法环境下表示正常的程度,也可以叫鲁棒性。
面对用户输入错误时,要能提示错误,处理未期望行为,并且应该要显示有助于DEBUG的错误信息。
健壮性原则
1.伯斯塔尔原则:对自己严格,对他人宽容。
封闭全部细节,考虑所有情况。
正确性:程序按照spec执行的能力。正如第二章就说明的,spec是决定正确性的。
与健壮性对比
1.健壮性倾向于用户,容纳用户的输入错误。
正确性倾向于开发者,对不符合spec的输入任意处理。
2.健壮性倾向于对外接口,正确性倾向于对内实现。
对此我的理解是健壮性倾向于在调用方法时,按照spec选择不合法数据并加以处理,正确性倾向于保证内部实现一定按照spec进行
在不同条件下,我们需要不同的权衡。
比如我们对于银行卡密码输入错误,就不能对其进行容错。
可靠性:程序在规定条件下执行功能的能力。
可靠性=健壮+正确性
几个名词解释
error,bug,failure
error:程序开发人员的错误。
bug:错误导致的功能上的问题
failure:问题外部表现导致程序失效
嘛,用马克思联系的观点看,failure是bug的表现,bug是failure的实质,而error是bug的因果。
程序员把+打成-号是错误,错误导致这部分运算不符合要求是bug,用户调用发现5+3=2是failure.
面向健壮性编程步骤
1.编程时注意正确性与健壮性
技术手段:断言,代码审查,防御式编程
2.观察测试发现问题发现正确性或健壮性不足
技术手段:内存转储,执行日志,堆栈树
3.确认bug所在
技术手段:bug localization, 调试器
4.修复bug
code revision
嘛一个总结上面
编码要理解正确性健壮性,测试要确认正确性健壮性,DEBUG要提升正确健壮性。
异常与错误处理
分类
JAVA中把未期望的执行,分为两类异常和错误。
二者都继承自Throwable接口,可以抛出。
错误:发生在内部,程序员无能为力,无法处理。
虚拟机错误,配置错误。
倒是有意思的是断言错好像也是error。
错误不是我们的程序造成的,我们无法处理也不能管它。
异常:自己程序导致的问题,我们应该处理。
异常处理
异常:程序中发生的非正常事件,已经发生不能继续执行下去了。
异常类会把事件发生时候的信息传递给上层程序,等待异常处理程序
来完成,目前程序会返回,是return后的第二个返回机制。
没有异常处理程序自动终结。
提供专门的异常类有很多好处
1.不会忘记处理异常,编译器强迫。
2.提供更好的异常信息摘要
3.代码结构更好
4.健壮性与可维护性更好了。
异常的进一步分类
异常分为:运行时异常(RuntimeException)
和其他异常。
运行时异常是由于程序员代码处理不当造成的。
而其他异常是外部造成的
运行时异常是完全可以修改代码避免的,比如空指针,可以检验后调用,数组长度不够,代表我们应该加大数组了。
而其他异常不是我们的代码问题。
受检异常和非受检异常
二者是在异常处理的机制上对异常的划分,但是非受检就是运行时异常和error。
异常发生时,我们需要告诉编译器,我们可以解决这个异常或不能解决我们要向上抛出。
对于受检异常,编译器要求我们必须告诉如何处理。
而对于runtimeexception 与 error编译器不强制要求我们处理,他们是非受检异常。
1.对于error,我们代码无法管。
2.对于runtimeexception这显示我们有编程错误,我们应该修改代码,而不是处理错误。
在自定义异常类时,非受检异常继承自runtimeexception,受检异常直接继承exception.
|
受检异常 | 未受检异常 |
---|---|
必须显式捕获传递异常 | 不必显示捕获传递 |
继承自exception | runtimeexception |
从异常发生的现场获取详细的信息,利用 异常返回的信息来明确操作失败的原因, 并加以合理的恢复处理 | 简单显示无法处理 |
正常与异常代码混合 | 逻辑清楚明白 |
受检异常与非受检异常选用
1.如果客户端对异常无能为力,用非受检异常。
如果客户端能通过其他的方法恢复异常,受检异常。
2.对于编程错误尽量使用非受检异常来处理。
3.要想简洁易读,用非受检异常。
要详细信息用受检异常。
4.对于可预料,无法预防,可恢复用受检异常。
否则非受检异常
5.可合理恢复受检异常。用受检异常表示意外结果,用非受检异常表示bug
throws声明抛出异常
异常是spec的一部分,很好理解,异常是程序从意外的地方退出,其实类似于return,在后置条件刻画。
JAVA中的规约标注@throws
一般两种情况需要注明异常抛出
1.你真的抛出了一个异常,用throw了
2.你调用的方法抛出了异常,而且你没有处理这个异常。