1700448803
1700448804
这里产生了两个问题:一是异常是主逻辑的补充逻辑,修改一个补充逻辑,就会导致主逻辑也被修改,也就是出现了实现类“逆影响”接口的情景,我们知道实现类是不稳定的,而接口是稳定的,一旦定义了异常,则增加了接口的不稳定性,这是对面向对象设计的严重亵渎;二是实现的类变更最终会影响到调用者,破坏了封装性,这也是迪米特法则所不能容忍的。
1700448805
1700448806
(2)受检异常使代码的可读性降低
1700448807
1700448808
一个方法增加了受检异常,则必须有一个调用者对异常进行处理,比如无受检异常方法doStuff是这样调用的:
1700448809
1700448810
public static void main(String[]args){
1700448811
1700448812
doStuff();
1700448813
1700448814
}
1700448815
1700448816
doStuff方法一旦增加受检异常就不一样了,代码如下:
1700448817
1700448818
public static void main(String[]args){
1700448819
1700448820
try{
1700448821
1700448822
doStuff();
1700448823
1700448824
}catch(Exception e){
1700448825
1700448826
e.printStackTrace();
1700448827
1700448828
}
1700448829
1700448830
}
1700448831
1700448832
doStuff方法增加了throws Exception,调用者就必须至少增加4条语句来处理该异常,代码膨胀许多,可读写性也降低了,特别是在多个异常需要捕捉的情况下,多个catch块多个异常处理,而且还可能在catch块中再次抛出异常,这大大降低了代码的可读性。
1700448833
1700448834
(3)受检异常增加了开发工作量
1700448835
1700448836
我们知道,异常需要封装和传递,只有封装才能让异常更容易理解,上层模块才能更好的处理,可这也会导致低层级的异常没玩没了的封装,无端加重了开发的工作量。比如FileNotFoundException在持久层抛出,就需要定义一个MyException进行封装,并抛出到上一个层级,于是增加了开发工作量。
1700448837
1700448838
受检异常有这么多的缺点,那有没有什么办法可以避免或减少这些缺点呢?有,很简单的一个规则:将受检异常转化为非受检异常即可,但是我们也不能把所有的受检异常转化为非受检异常,原因是在编码期上层模块不知道下层模块会抛出何种非受检异常,只有通过规则或文档来约束,可以这样说:
1700448839
1700448840
受检异常提出的是“法律下的自由”,必须遵守异常的约定才能自由编写代码。
1700448841
1700448842
非受检异常则是“协约性质的自由”,你必须告诉我你要抛出什么异常,否则不会处理。
1700448843
1700448844
以User接口为例,我们在声明接口时不再声明异常,而是在具体实现时根据不同的情况产生不同的非受检异常,这样持久层和逻辑层抛出的异常将会由展现层自行决定如何展示,不再受异常的规则约束了,大大简化开发工作,提高了代码的可读性。
1700448845
1700448846
那问题又来了:在开发和设计时什么样的受检异常有必要转化为非受检异常呢?“尽可能”是以什么作为判断依据呢?受检异常转换为非受检异常是需要根据项目的场景来决定的,例如同样是刷卡,员工拿着自己的工卡到考勤机上打考勤,此时如果附近有磁性物质干扰,则考勤机可以把这种受检异常转化为非受检异常,黄灯闪烁后不做任何记录登记,因为考勤失败这种情景不是“致命”的业务逻辑,出错了,重新刷一下即可。但是到银行网点取钱就不一样了,拿着银行卡到银行取钱,同样有磁性物质干扰,刷不出来,那这种异常就必须登记处理,否则会成为威胁银行卡安全的事件。汇总成一句话:当受检异常威胁到了系统的安全性、稳定性、可靠性、正确性时,则必须处理,不能转化为非受检异常,其他情况则可以转换为非受检异常。
1700448847
1700448848
注意 受检异常威胁到系统的安全性、稳定性、可靠性、正确性时,不能转换为非受检异常。
1700448849
1700448850
1700448851
1700448852
[
上一页 ]
[ :1.700448803e+09 ]
[
下一页 ]