异常的处理位置有些疑问
比如一个简单三层,DAL、BLL、UI中都有可能发生异常,发生的异常需要进行日志记录,那么我应该在哪里进行日志记录操作?
1、每层的每个可能发生异常的方法中,都加上try{}catch{}
2、其中DAL、BLL 的方法内部的catch{}中,全都写成throw; 将异常向上抛;
3、在UI 的后台,catch{}中,去处理异常,比如讲异常信息进行日志记录。
请问,这种做法合理吗?会有哪些没想到的问题?
还是 处理异常的位置有更合理的地方?
进行了些取舍,将DAL进行try--catch,UI 进行try--catch。中间的部分就放开,由DAL throw 直到UI层来捕获,虽然进行了2次catch,但是还是比较放心,像BLL,尽量做好代码上的校验,防止一般的异常出现。
感谢各位。
个人做法是:
通常在调用关系的最后一层捕捉异常,不提倡在被调用层大量捕捉异常。
因为 被调用层 不知道 调用层 如何使用自己,过多的捕捉反而掩盖了错误,不如不捕捉,扔给调用层自己去处理。
但有些例外的异常应该优先处理,如:
被调用层代码中有资源需要释放。
被调用层代码中有重要的业务逻辑,则捕获 做出应对。
对于被调用代码的某种异常,有合适的解决方法。
等等。。
感觉对于每层捕捉异常,并向上层抛这种方式不太好。因为捕捉异常对性能影响比较大。这样会造成每层都要对异常处理。
有时候也要看具体情况而定。
个人意见,标记一下,听听大家看法。
捕捉异常对性能影响是大,但是,这是在异常发生的时候才会影响到性能,如果正常执行try中的内容,对性能没有任何影响;
异常一定要处理,当异常发生的时候 严重的会导致页面黄页,此时就没必要在乎什么性能了。
“通常在调用关系的最后一层捕捉异常,不提倡在被调用层大量捕捉异常。”
请问: 调用关系的最后一层 是指那一层(UI? DAL?),被调用层是指?(UI? DAL?)
"被调用层代码中有资源需要释放。" : 这个很重要。
-----------------------------
我目前是由底层全部向上抛出(需要释放资源的就地解决),交给UI层来处理异常的响应方式,同时记录日志。
@cloud_915:
关于逐层上抛。
你DAL,BLL,UI代码 都捕捉并上抛的话。
在不发生异常的情况下,是没有问题。
假如DAL发生了异常,你会对此异常捕捉三次。
这就是性能损失。
我觉得通常情况一次就够了,在UI层捕捉。。
特殊情况,在DAL,BLL捕捉处理,是否上抛,看情况而定。
我说的最后一层是 UI层。
@摇啊摇啊摇: 是说 DAL,BLL 都不做try--catch,只在UI 加catch? 这样能捕捉到全部吗?我没有这样写过,如果可以那还挺省事的?
@cloud_915:
因为 所有的BLL,DAL最终都是被UI的后台代码调用的。
所以在UI层肯定能捕获到所有的错误。
我就是这么做的,只是某些个别特殊情况,在DAL,BLL捕捉处理
这样的缺点是,异常通过几层抛出来后。你的日志中 只能获取到当前层的异常信息。
实际上这个异常信息并不是 最开始引发异常的信息。不方便通过日志定位问题所在。
以上是我的方式。这个问题我也比较关注。看看大神们有没有好的方式。我也学习下。
@摇啊摇啊摇: catch三次 的性能三次损失 ,这个以前居然没注意,长经验啦。
创建一个异常类。抛出异常时写入日志文件即可
但是要在哪个位置去调用日志方法?哪一层。
这种层层向上抛出的思路正常吗?
@cloud_915: 我觉得只要抛异常了就将其写入日志文件中。。看起来不是更清楚么,所以我觉得不用向上抛出
@墨然: 当日志中有些信息参数,需要在某个特定的层才能得到时,直接写日志就行了
这个问题我有时也很纠结,在业务处理的地方捕获。
个人认为在UI层和业务层时的情况是可预测的这种情况下能够避免就不要抛异常,而在dal层和数据库通信,这个过程并不是一个可控的工程(如数据库打开失败,sql执行超时等一些无法确定的情况),这种时候就需要try{}catch{}了,所以try{}catch{}并不是要区分是在哪一层用,而是要看代码执行时是否有不可预测的可能抛异常的情况
我把日志都放到UI来写,主要是由于 日志记录中一些参数(比如IP)只能在这里获得,如果把这些信息都层层传递到下层,我觉得没必要,也麻烦;
我的最终目的是部署后,能追溯异常的各种信息,方便维护。不然直接catch后不抛出,也可以的。