精簡本身20%的代碼(異常的處理)

持續重構,其樂無窮。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編程的效果。最後,還有什麼疑惑,能夠在評論中給我留言,固然別忘記了點右下角的【推薦】。

文章出處:http://www.cnblogs.com/xcj26/p/3442089.html#!comments

相關文章
相關標籤/搜索