持续重构,其乐无穷。html
一:发现问题编程
先来讲如何重构业务层的try{}catch{}finally{}代码块,我看过不少代码,异常处理这一块大体分为两种状况,一种是每一个方法都大量的充斥着try{}catch{}finally{},这种方式的编程已经考虑到了异常处理,还有一种就是没有try{}catch{}finally{}的代码,由于根本就没有考虑代码的异常处理。每当我看到这样的代码,我都很忧伤。从程序的健壮性来看第一种仍是要比第二种状况好,至少在编程意识中,随时想到了异常状况,有一种基本的编程思想。spa
好比:一个业务单据的多表插入,关联修改,虚拟删除等都是一些基本的操做,可是又是比较容易引发错误的操做,在这些方法上都会加上try{}catch{}finally{}对代码进行有效的防错处理。早期的代码是这样的。日志
public Boolean Save(AccountModel accountData) { Boolean result = false; try { //TODO ... result = true; } catch { } finally { } return result; } public Boolean Edit(AccountModel accountData) { Boolean result = false; try { //TODO ... result = true; } catch { } finally { } return result; } public Boolean VirDelete(AccountModel accountData) { Boolean result = false; try { //TODO ... result = true; } catch { } finally { } return result; }
仅仅定义了添加,修改,删除几个空方法,就写了三四十行代码,若是业务稍微复杂些,异常处理的代码很快就会突破百行大关。虽然复制,粘贴try{}catch{}finally{}很好使,可是业务逻辑代码大量充斥着这样的try{}catch{}finally{}代码,确实显得作事不够利落。code
二:解决问题htm
那怎样来解决这件棘手的事呢,首先定义一个公用的try{}catch{}finally{},以下如示:blog
public class Process { public static bool Execute(Action action) { try { action.Invoke(); return true; } catch (Exception ex) { //1,异常隐藏 //2,异常替换 //3,异常封装 //写日志 return false; } finally { } } }
上边的代码定义了公用的try{}catch{}finally{},最关键是怎么运用起来,以下代码:事务
protected void Page_Load(object sender, EventArgs e) { AccountModel accountData = new AccountModel(); //准备传入的参数 Boolean result = false; //接收返回的值 Process.Execute(() => result = Save(accountData)); //执行方法 } public Boolean Save(AccountModel accountData) { Boolean result = false; //TODO ... result = true; return result; } public Boolean Edit(AccountModel accountData) { Boolean result = false; //TODO ... result = true; return result; } public Boolean VirDelete(AccountModel accountData) { Boolean result = false; //TODO ... result = true; return result; }
这样的精简过的代码,是否是感受心情很舒畅。字符串
三:提高与扩展get
对于满足者常乐的人来讲,到第二个步骤就能够洗洗睡了。可是对于精益求精的人来讲,问题仍然没有完。咱们来讲一个应用场景,在WCF中的应用,咱们知道WCF服务端的异常,不通过<serviceDebug includeExceptionDetailInFaults="true"/>的设置,服务端的异常是没法抛到客户端的。可是在正式环境中,不可能对进行serviceDebug的配置。正确的处理是在服务端对异常进行隐藏,替换,或者封装。
好比咱们在服务端捕获了一个已知异常,可是这个异常会暴露一些敏感的信息,因此咱们对异常进行替换,抛出新的异常后,咱们还要把这个异常怎样传输给客户端。首先们要明确WCF中的一些基本常识,就是WCF中的数据传递要遵循WCF的数据契约,服务端抛到客户端的异常(异常其实也是数据),因此必需要给异常定义异常契约。
[DataContract(Name = "WCFException")] public class WCFException { [DataMember(Name = "Type")] public String Type { get; set; } [DataMember(Name = "StackTrace")] public String StackTrace { get; set; } [DataMember(Name = "Message")] public String Message { get; set; } }
而后处理异常的公共方法改写为:
public static bool Execute(Action action) { try { action.Invoke(); return true; } catch (Exception ex) { //1,异常隐藏 //2,异常替换 //3,异常封装 //写日志 WCFException exception = new WCFException { Type = "Error" , StackTrace = ex.StackTrace , Message = ex.Message }; throw new FaultException<WCFException>(exception , new FaultReason("服务端异常:" + ex.Message) , new FaultCode(ex.TargetSite.Name)); } finally { } }
这样在服务端抛出的异常,就能在客户端捕捉到。如今是否是感受本身又提高了一些,想成为编程高手是指日可待了。
四:触类旁通
异常的处理也不过如此,那是否是应该触类旁通,看看事务的处理应该怎么办?好比如今大量的访求都用到了事务,以下代码:
public Boolean Save(AccountModel accountData) { OracleConnection conn = new OracleConnection("链接字符串"); IDbTransaction trans = conn.BeginTransaction(); Boolean result = false; try { //TODO ... trans.Commit(); result = true; } catch { trans.Rollback(); } finally { } return result; }
特别是 trans.Commit(); trans.Rollback(); 这样的代码出如今每一个与事务相关的方法中, 让我感受到代码的臃肿,以及隐陷约约的失望。
通过我几天的翻阅资料终于实现了事务的公用访求提取。使用方法以下代码所示:
[TransactionAttribute] [ExceptionAttribute] public bool Save(DataContext dContext, Dictionary<string, string> dtoPara) { Boolean returnVal = true; //TODO ... return returnVal; }
就是在一个方法上加[TransactionAttribute]就表示这个方法写在了事务中,反之,不在事务中,加[ExceptionAttribute]就表示这个方法做了异常处理,反之,不做异常处理。经过反射或者AOP都能实现Attribute编程的效果。最后,还有什么疑惑,能够在评论中给我留言,固然别忘记了点右下角的【推荐】。