1.是否需要已检测异常
《Clean Code》一书对已检测异常是持完全否定态度的。事实上,有很多人是不认可已检测异常的,一方面,在目前的主流语言中,只有java提供了已检测异常机制,那么这从反面证明已检测异常并不是一种“必须”或者说是“优秀”的语言机制。已检测异常的设计初衷是希望借助编译期的检查来强制异常处理,从而有助于构建出健壮的系统。但正如《Clean
Code》一书所说,那些没有已检测异常的语言就不能构建健壮的系统么?显然不是,也就是说已检测异常并不是"看上去那么美"。另一方面,人们普遍认为引入已检测异常的一个很大的代价就是违反了开闭原则。一旦底层的某个方法需要修改接口抛出一个已检测异常,那么上层的所有调用接口都不能幸免,它们的接口或是实现也必然需要做出改动!再比如:一个较“底层”的方法抛出已检测异常,如果上层方法对此异常也“无能为力”的话会怎样呢?捕获而不处理是肯定不正确的。而如果再抛出就需要有一个合适的异常来包裹一下以便符合当前方法的抽象级别。
2.对于一个异常应该根据什么原则来确定它应该是已检测异常还是未检查异常?
实际上,如果在回答第一个问题时,我们选择了不使用已检测异常的话,也就不存在这个问题了。但是在广泛使用已检测异常的系统里,知道怎样区分已检测异常和未检测异常是非常必要的。一般来说:从调用者的角度去看,已检测异常是那些完全有理由能“预见”或是“重现”的异常情况。那这也正意未着方法本身明确要求调用者不能忽视(既然它已经预见到可能会发生了)这些异常情况。基于这样的准则,我们说:几乎所有的业务异常(有深刻业务含义的异常)都应该是已检测异常。除此之外都应该属于程序性错误,也就是未检测异常。
这看起来很简单,但是却忽略了一个问题:抽象级别的问题。现在的系统都是依赖各种框架或组件构建起来的。在框架和组件级别,一些“当然”业务上的已检测异常,在上层看来是很“底层”的“技术”问题。比如,在一个文件处理框架里,FileNotFoundException是一个很自然的“业务”异常,因而是一个已检测异常。但是对于调用者来说,如果对此异常也“无能为力”会怎样呢?捕获而不处理是肯定不正确的。而如果再抛出就需要有一个合适的异常来包裹一下以便符合当前方法的抽象级别。这样看,处理已检测异常确实是很“劳神”的(当然你可以说这正是它的优点)。
3.视图层的异常统一处理方法
当异常一直浮升到视图层时,就需要考虑以何种方式通知用户系统出现了问题。当发生异常时跳转到统一的异常处理页面显示错误信息是一种普遍的做法。至于说在当前页面弹出对话框显示异常的形式可能会更加友好一些。但是由于页面请求既有http请求又有ajax请求的话,弹出对话框的方式可能有些技术上的困难。 |