小课堂Week9 例外处理设计的逆袭Part2

小课堂Week9

例外处理设计的逆袭Part2

今天继续阅读《例外处理设计的逆袭》这本书,我们先看两个案例:

案例1

问:如果要设计一个依据学号到数据库中查询学生资料的函数,当找不到符合条件的学习资料时候,是不是要丢出异常?

分析:
根据Part1中的介绍,例外的生命周期包括fault、error、failure,那么要抛出的首先应该是一个fault。
让我们看下案例中的这个场景属于哪类fault。
首先,这个不是component fault,因为与环境无关。
找不到资料,看起来是主观引入的,那是不是一个design fault,我们之前也讲过,design fault应该是不可预期的,但是这个找不到资料明显是可预期的,所以也不是design fault。
综上所述,找不到资料不是一个fault,所以也不是一个异常,不应该抛出。
那问题又来了,如果不抛出异常,那应该返回什么呢?默认情况下,应该是返回null,但是我们知道null带来的后遗症会很多,所以建议的是返回一个Null Object,比如Java8中的Optional,Scala中的None对象等都能解决这个问题。

案例2

问:考虑一个三层体系的系统,包括了用户界面App,业务处理GameServer和底层通讯Acceptor。
Layer1:App
Layer2:GameServer
Layer3:Acceptor
如果Acceptor收到一个IOException要如何处理。

分析:
首先,异常适不适合在App端处理,这个是否定的,因为IOException是一个比较偏技术的异常,如果直接反馈给用户,其实并不友好,用户也无法处理。另外,从异常的生命周期看,反馈给用户的话,相当于把error变成了failure,这种情况应该尽量的减少。
其次,是不是适合在Acceptor中处理,大多数情况下不适合,应该acceptor作为一个底层组件,其职责比较单一,所掌握的信息也是不够全面的,异常处理界有一句话叫:能力越大,责任越大。Acceptor往往是能力不够。
所以,比较适合在GameServer中将异常处理掉,由于其中信息作为全面,我们可以有多种的处理思路和方法。

异常处理强度等级

这个部分应该是整本书的精化,通过对于强度等级的实施,可以把异常处理的理念在工程上实施出来。

等级0:不管例外

等级1:error-reporting,立即中止运行 ,所有例外都往外抛,全部报告给使用者,或者开发者使用

解读:等级1要求比较低,实质上就是把所有的error都转成了failure,但是当中的重点是往外抛这个概念,也就是异常信息在最外层才被记录,因为异常有传递体系,越外层信息会越全,只有越全面的信息才越有用。

等级2:和1相同,都往外报,但在错误发生时,故障程序是可以继续运行的。
如何做到这一点呢,有两个策略:

  1. 向后回复:将程序状态回退到处理以前,比如Oracle中的rollback方法,其缺点是需要备份之前的状态,成本比较高
  2. cleanup:通过清理逻辑恢复程序状态,这个存在开发和分析工作量,但更为通用。

等级3:在2的基础上,提供应急处理方法,确保业务能正确执行
如何做到这一点呢,有两个策略:

  1. retry:对于CF,有比较多可能在重试后解决。
  2. 向前回复:需要有备份的应急渠道和程序,这个会有比较高的开发成本,但是可以达到非常高的容错能力。

最后,还想说下,并不是所有程序都需要达到最高等级,这个需要根据程序的重要程度来进行区分,但是,至少应该能达到等级1。

上一篇:性能:15个JavaScript本地存储技术的函数库和工具


下一篇:15个JavaScript本地存储技术的函数库和工具