一、异常处理不简单
个人觉得,异常处理对于程序员来说,尤其是对于那些初级.NET程序员来说,是最为熟悉的同时也是最难掌握的。说它熟悉,因为仅仅就是Try/Catch而已。说它难以掌握,很多开发人员却说不清楚Try/Catch应该置于何处?什么情况下需要对异常进行日志记录?什么情况下需要对异常进行封装?什么情况下需要对异常进行替换?对于捕获的异常,在什么情况下需要将其再次抛出?什么情况下则不需要。总之,异常处理没有我们想象的那么简单。
无论对于何种类型的应用,异常处理都是必不可少的。合理的异常处理应该是场景驱动的,在不同的场景下,采用的异常处理策略往往是不同的。异常处理的策略应该是可配置的,因为应用程序出现怎样的异常往往是不可预测的,现有异常策略的不足往往需要在真正出现某种异常的时候才会体现出来,所以我们需要一种动态可配置的异常处理策略维护方式。目前有一些开源的异常处理框架提供了这种可配置的、场景驱动的异常处理方式,EnterLib的Exception Handling Application Block就是一个不错的选择。
二、异常处理对于最终的开发人员是透明的
“异常处理对于最终的开发人员是透明的”,可能这句话说得有点过头。但是,就我个人的项目经验来讲,这是一种理想的状态。由于异常策略是一般是通过配置动态配置的,不需要反映在代码上面。如果能够通过框架的方式提供异常处理的实现,使开发人员无需编写任何异常处理的代码,只需要关注业务流程的实现就可以了,这不仅能够提高开发的效率,也能够提高系统的可维护性。
我们目前的项目是一个典型的分布式应用,所有的业务流程的处理和数据访问都实现在服务端,最终以WCF服务的形式暴露给客户端(Smart Client)和第三方应用。所有客户端和服务端从逻辑上具有相应的层次划分,但是异常处理仅仅实现在两个地方,一个地方是WCF服务本身,另一个实现 UI层。忘了说明一点,我们项目直接将EnterLib的Exception Handling Application Block作为我们的异常处理框架。对于服务端的异常处理来说,我们通过WCF与EHAB的集成来实现的(《WCF与Exception Handling AppBlock集成》),所以不需要开发人员添加任何一句Try/Catch代码。但是客户端来说,对于某个控件的事件来说,由于UI本身就是处于整个调用栈的最顶层,很难通过基于AOP的拦截机制来实现对异常处理的动态注入,所以客户端会出现非常类似于下面代码所示的Try/Catch。
1: private void buttonCalculate_Click(object sender, EventArgs e)
2: {
3: try
4: {
5: //
6: }
7: catch (Exception ex)
8: {
9: if (ExceptionPolicy.HandleException(ex, "policyName"))
10: {
11: throw;
12: }
13: }
14:
15: }
我是一个对重复代码具有强迫症的人,看到两个相同的代码我都有对代码进行重构的冲动,何况如此众多的相同代码充斥在客户端。
三、通过编写公共方法的形式实现代码的重用
为了避免开发人员编写相同的Try/Catch,很多人首先想到的肯定是将重复代码定义在一个公共的方法上,以实现代码的复用。这个公共方法很简单,只需要如下几句代码即可。