关于错误处理

来源:互联网 发布:采购平台软件 编辑:程序博客网 时间:2024/05/22 13:28

曾经在博客看到过这句话:无视这个致命缺陷勉强运行呢,还是该马上报错修正缺陷!

 

日志不是糊涂账,不是火锅,不能什么都往里写——否则,这本糊涂账就不会有人去认真分析。

更好的错误处理,能在维护甚至开发期间,更有效的发现bug并解决。

 

容错必须精确、理性。不然越容错越多。

 

CLR的一场极致让人关注最多的一点就是“效率”问题。其实,这里存在认识上的误区,因为正常流程控制下的代码运行并不会出现问题,只有引发异常时才会带来效率问题。基于这一点,很多开发者已经达成共识:1,不应该将一场极致用于正常流程控制中;2,CLR异常机制带来的“效率”问题远不如它带来的巨大收益。

 

如果你不能把异常处理掉,就不要把异常吃掉,让能吃掉它的人吃。

 

案例一:对Base64字符串的解码:

方法1:


在这里字符串为null或者非base64,捕捉异常后返回空,使程序可以继续执行。

这里可以说是进行了把解码的异常吃掉,并返回个空字符串以便继续进行。

而如下的方法2:


不做任何处理,如果有异常,由使用者根据自身情况去捕捉并处理。

 

有人会觉得,如果不写try catch,使用的人每次都要加上trycatch,不就一堆重复代码了吗;使用者都要加的try catch算不算重复代码,这里不讨论,暂且先对比下这两个方法:

方法一,参数是非法,还是空字符串,返回都是空字符串,使用者根本不知道问题的根源是参数非法,还是参数为空;

方法二:如果参数是空字符串,则返回字符串(或许返回string.empty更好),如果非法字符,则会先捕捉再抛出自定义的Base64FormatException异常,如果出错了,调用者可以知道原因是什么,并进行相应的不同的处理。并且为空处理的性能上也更强。如果说方法一也加上为空字符串的判断,那怎么知道,返回空字符串,是解码错误,还是参数为空。

综上所述,异常由使用者捕捉,如果方法不是不管什么异常都统一处理的话,还是不捕捉,由使用者捕捉比较好,不能为了方便说为了让方法勉强运行而在内部捕捉异常,假设有这么一种场景,要编码的内容为空也不影响业务,而参数却是非base64编码字符串,结果用方法一返回空字符串,业务继续进行。

 

性能问题:有人会觉得捕捉异常又抛出,上层还需要再次捕捉,会造成性能问题。但是,抛出Base64FormatException异常的时候,该关心的,不是代码为何出错,而不是性能问题吗?正常的代码,并不会抛出异常,既然抛了,就说明上层代码存在bug。

案例二:数据库的操作

方法:


这是Service层对业务逻辑处理以及数据库操作的方法,在这里用了try catch捕获异常,然后在调用的时候,也捕获异常。按功能来说没什么问题。但是,代码维护的时候,不管本人还是他人,就有问题了。这不成功,是业务不成功,还是系统异常,从代码根本看不出,也就是有可能是业务逻辑的bug,却以为是数据库连接错误抛异常。


个人推荐,在业务处理层,尽量不要加trycatch,有问题的,都由上层捕捉异常。。。代码异常的处理,应该由上层决定,而不是在业务代码中处理。业务逻辑不应该和出错处理耦合在那里(这里说的是常规情况,特殊排除)。

 

类型三:业务处理

 

在适当的业务场合使用异常(如果例子不够好,希望指正下)

 

在业务层,出现一些不合法的,是返回错误信息,还是抛异常。。。目前的代码几乎都是返回错误(或者验证都没有,让程序自己抛异常),返回错误,外部如果要进行,也可以进行,就是程序不会报错。个人觉得,在一些地方,需要适当的抛异常。

 

例如:


如果找不到相应的业务业务单,我选择抛异常。为何?业务申请单和账单是组合关系,没有业务申请单,就不可能会有账单,一个找不到业务申请单的账单号,就不是业务逻辑问题,而是上层代码或本方法中的Get方法有bug,如

一个数据库不存在的数据,何来修改,既然非法,就是异常,所以我抛异常,不返回错误信息。而接下来的逾期时间问题,属于业务逻辑,不符合业务,所以返回错误。能传一个找不到业务申请单的账号单过来,要么上层使用有问题,要么Get方法有问题,还有可能是业务申请单生成账单的时候生成出了问题,这些问题都是代码存在bug,抛异常问题可以快速定位。

又如以下方法:如果使用这个方法,还传个空对象,那上层代码就是有问题的代码了。

 

显性抛出异常从某种程度上实现了将处理异常的代码从正常流程代码中分离开了,使得程序的主线保证相对完整,同时增加了程序的可读性和可维护性。异常沿着调用层次向上抛出,交由调用它的方法来处理。

 

 

欢迎指正、完善或补充。