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

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

面向健壮性的编程希望:处理未期望的行为和错误终止 ;即使终止执行,也要准确/无歧义的向用户展示全面的错误信息 

正确性:程序按照spec加以执行的能力,是最重要 的质量指标!

正确性倾向于直接报错(error),健壮性则倾向于容错(fault-tolerance)

可靠性=健壮性+正确性

可以通过平均故障间隔时间(MTBF)(平均无故障运行时间),是指相邻两次故障之间的平均工作时间,来衡量健壮性。

MTBF用于描述可修复系统的平均无故障运行时间,MTTF(故障前平均时间)描述不可修复系统的故障前平均时间

1.Error and Exception
 

这里有两种很重要的分类,分类一:

Error:程序员通常无能为力,一旦发生,想办法让程序优雅的结束,通常是一些外部的不可抗力导致的。

Exception:程序执行中的非正常事件,导致程序无法再按预想的流程执行。是你自己程序导致的问题,可以捕获、可以处理。

其中由于error难以处理,重点关注Exception。首先Exception和Error都是继承自Throwable类的,其中Exception又分为 RuntimeException和其它,单独分出RuntimeException的原因是RuntimeException比较特殊,运行时异常,是程序源代码中引入的故障所造成的,如果在代码中提前进行验证,这些故障就可以避免;而其它异常即使在代码中提前加以验证(如:文件是否存在),也无法完全避免失效发生,是程序员无法完全控制的外在问题所导致的。

这就引出了第二个重要分类:

Checked exceptions:包括Exception中除了RuntimeException的所有异常,这些既是异常,又是无法完全避免失效发生的。可以理解为需要检查的异常。

unchecked exceptions:包括Error所有和RuntimeException,可以理解为没有检查的必要,Error检查了也无能为力,RuntimeException检查的话会降低对程序员的要求,掩耳盗铃。

对与Checked exceptions,必须捕获并指定错误处理器handler,否则编译无法通过;unchecked exceptions则不需要。

处理Checked exceptions,会用到如下关键字:

(throws) 声明“本方法可能会发生XX异常”
(throw)  抛出XX异常
(try, catch, finally) 捕获并处理XX异常

注: Unchecked异常也可以使用throws声明或try/catch进行捕获,但大多数时候是不需要的,也不应该这么做,是掩耳盗铃,对发现的编程错误充耳不闻的行为。

什么时候使用Checked exceptions,什么时候使用Unchecked呢?

如果客户端可以通过其他的方法恢复异常,那么采用checked exception; 

如果客户端对出现的这种异常无能为力,那么采用unchecked exception; 

总结起来就是如下的表:

 注意:在规约中“异常”也是方法和 client端之间spec的一部分,在post-condition中刻画,使用关键字@throws, 程序员必须在方法的spec中明确写清本方法会抛出的所有checked exception,以便于调用该方法的client加以处理。

还有一些要点:

1.也可以定义自己的异常类,抛出异常的方法throw new EOFException(); 

2.异常发生后,如果找不到处理器,就终止执行程序,在控制台打印出stack trace。 可以不在本方法内处理,而是传递给调用方,由client处理(“推卸责任”) 

3.本来catch语句下面是用来做exception handling的,但也可以在catch里抛出异常,目的是更改exception的类型,更方便client端获取错误信息并处理。

4.finally关键字的优先级最高,甚至高过return,当异常发生后,剩余代码通常不会执行,但Finally部分的代码,是否捕获异常都会被执行。 

2.Assertions
首先要知道,断言是为了程序的正确性而生的,可以快速失败,避免扩散,将bug限制在最小的范围内 。

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

断言即是对代码中程序员所做假设的文档化,也不会影响运行时性能(在实际使用时,assertion都会被disabled)。

形式是assert condition;或assert condition : message;

什么时候用断言呢?

断言可以用来核实:1内部不变量;2表示不变量;3控制流不变量;4方法的前置条件;5方法的后置条件。

断言主要用于开发阶段,避免引入和帮助发现bug ,实际运行阶段, 不再使用断言需要注意的是:

1.程序之外的事,不受你控制,不要乱断言,断言只是检查程序的内部状态是否符合规约,外部错误要使用Exception机制去处理。

2. Java缺省关闭断言,要记得打开(-ea) 

3.防御式编程
1)保护程序免受无效输入的影响在:对每个函数的输入参数合法性要做仔细检查,并决定如何处理非法输入 

2)设置路障:类的public方法接收到的外部数据都应被认为是dirty的,需要处理干净再传递到 private方法——隔离舱;“隔离舱”外部的函数应使用异常处理,“隔离舱”内的函数应使用
断言。

3)使用如 SpotBugs的工具。 

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值