沒頭沒尾--專案開發筆記:異常處理與日誌記錄程式碼自動生成(工具能生成多少程式碼!?續一) (轉)

amyz發表於2007-10-17
沒頭沒尾--專案開發筆記:異常處理與日誌記錄程式碼自動生成(工具能生成多少程式碼!?續一) (轉)[@more@]

標題:沒頭沒尾--專案開發筆記:異常處理與日誌記錄程式碼自動生成(工具能生成多少程式碼!?續一)

關鍵詞:分散式開發 專案分工 與C#的混合開發 AOP 程式碼生成工具 異常處理 日誌記錄

12月7號:從AOP的想法中得到對專案中異常與日誌記錄的抽離與處理方式

 :namespace prefix = o ns = "urn:schemas--com::office" />

上次寫的程式碼生成工具是從的方面來講程式碼生成工具。寫的比較粗,只是定義出了程式碼生成工具在我們的專案中對應的目的以及實現幾種手段。可能比較抽象。下面用本專案中對異常處理與日誌記錄處理的處理方式來解釋程式碼生成工具的應用。

 

異常處理與日誌記錄的統一處理機制

這裡說的異常處理與日誌記錄的統一處理是指部分處理。整個系統中,對於異常處理與日誌的處理只可以在任何的地方來做。這種方案只是將80%的日誌與異常處理使用程式碼生成工具來進行生成。對於特殊的異常處理,還是每個員自己去搞定J。

異常處理與日誌的記錄處理應該是完全不同的兩件事件。但是基本上我認為這兩件事件都是獨立於業務過程,並且在我們的系統中,異常的事件必須要記錄到日誌處理。所以我考慮統一進行處理。

專案開始的時候,我去讀了幾本有關C#的參考資料。根據我以前開發應用的,C#對應的類可以將例外順著的棧一直將例外拋到最外層。跟蹤C#程式碼的時候我也發現C#中往往做一個非常簡單的呼叫時,也可能要呼叫很多層的程式碼。(microsoft的習慣,以前寫MFC的時候就發現了L。)所以異常處理的外拋機制我想應該是必不可少的。

老實說,專案開始的時候我並沒有考慮清楚日誌與異常處理應該如何去做。只是有一個不是非常明確的想法是要將這兩個處理的過程一起進行考慮。於是現在,在專案已經進行到一半的時候開始對這個問題進行統一的處理。不得不用程式碼生成工具,要不會麻煩死的。

第11期的程式設計師雜誌中介紹了有關AOP的方法,我覺得獲益匪淺。我想AOP的核心無疑是面向方面這四個字。至於具體的實現,目前給出的並沒有針對C#的版本。那麼我們只能去應用它的思路。我覺得他的思路中比較明確的把開發程式中的關注分開,從而對開發進行的劃分。但是我並沒有看出對開發過程人員分工進行重新的組織。

(每我想了想如果我們寫的是一個沒有異常處理機制的庫,從外部使用AOP的事情訊息擷取方式可能沒有辦法得出去擷取錯誤的訊息以及記錄。只透過擷取訊息的方式可能是無法達到統一處理異常的機制?不知道朋友們對這個問題有什麼看法。)

我們的系統中,層次的劃分之後,伺服器端呼叫可以分成兩個大的部分。 Service是根據客戶端的請求各自的定義。而其它的,如Facade、Business Rules,DO等等都是以庫的形式存在。(可以在Web Service的BIN的目錄找到一堆的DLL)。針對這種情況,專案組定義的原則是庫中最好不要捕獲異常(除非某個異常表示的是程式碼可以處理的情況),而且從Web Service呼叫程式碼可以處理它們。(參考C#高階一書。)

最後專案小組商量的結果就是利用C#可以將例外可以一直丟擲到最外層的異常處理原理。只在最外層的Web Service層寫統一異常例外的處理。(特殊的異常處理每個人再自己寫。)並且由於Facade層與Web Service層所定義的結構都是以面向設計來進行處理的。(可以參考上一篇:工具能生成多少程式碼!?)也就是說結構是完全相同的。例如:

如果Facade層的ProductFacade.cs有一個以下的:

  ///

  /// Update all change Product Data item.

  ///

  public int ApplyAllChangeItem(String XMLStringofProductData)

  {

……………………

  }

那麼Web Service層中一定會對應有ProductService.asmx.cs。其中會有以下方法:

  public int ApplyAllChangeItem(String XMLStringofProductData)

  {

    return new ProductFacade().ApplyAllChangeItem(XMLStringofProductData);

  }

(程式碼段一)

上面的Web Service的方法是不包括對異常與日誌處理,如果加上對日誌與異常的處理,這個方法是這樣寫的。

    [WebMethod(EnableSession=true,Description = " Update all change Product Data item.")]

  public int ApplyAllChangeItem(String XMLStringofProductData)

  {

    try

  {

    return new ProductFacade().ApplyAllChangeItem(XMLStringofProductData);

  }

    catch(Exception e)

  {

    try

    {

      lasterror = e.Message;

    throw new ExceptionEx(e);

    }

    catch

    {

      HttpContext.Current.Response.Redirect("Common.asmx/GetErrMessage?", false);

    return null;

    }

 

    finally

    {

    }

  }

    catch

  {

    try

    {

      lasterror = "UnknowError!@@";

    throw new ExceptionEx(lasterror);   

    }

    catch

    {

      HttpContext.Current.Response.Redirect("Common.asmx/GetErrMessage?", false);

    return null;

    }

    finally

    {

    }

    return null;

  }

    finally

  {

  }

  }

(程式碼段二)

 

(注:

u  ExceptionEx是我們自己定義的例外類,開發人員可以在開發過程出現程式出現異常時自己去丟擲這個例外。也可以不去自已寫例外的處理。出了錯自己會丟擲的。

u  ExceptionEx的負責將例外統一進行日誌處理。只要new ExceptionEx就會記錄日誌。

程式碼生成工具的應用

上面的對異常問題的分析實際上在一開始我並沒有想清楚。也就是說,系統開始時,我們並沒有考慮怎麼樣去統一異常的處理。(不知道還沒有朋友們也是這樣做的??)於是先開始只與負責部分的同仁一起做出資料庫連線時例外處理的例子。統一了那個過程。(已經有朋友指出我們是魯莽程式設計,鬱悶。還是我的經驗不夠。)而且在上面這個異常與日誌方案沒有出來之前,我已經生成了部分的Web Service的程式碼。所以當這個處理方式定義下來之後,我們要做的是兩件事情:

1.  修改已經完成的程式碼,加入統一的處理

2.  根據Facade層自動生成Web Service的程式碼

下面分別針對兩種情況來說明程式碼生成工具;

²  修改已經完成的程式碼,加入統一的處理

還是用上一篇的說法,製作一個程式碼生成工具一定要搞清楚三個問題,輸入、生成方法以及輸出分別是什麼?

針對已經完成的程式碼,一定是修改已經在Web Service目錄中已經有的Web Service。修改的部分一定是要針對每個Web Service類中的Web Service的方法進行處理。然後將try之類的異常處理的部分加入進去。下面是具體過程的描述:

1.  透過輸入得到Web Service的目錄;

2.  遍歷目錄,找出所有最後八個字元是“.asmx.cs”的檔案;(Web Service的類檔案)

3.  將檔案內容讀入一個檔案字串中;

4.  迴圈查詢以 “[WebMethod(”為開頭的字串位置;

5.  找出上面步驟字串位置之下第一個“{”的位置,然後再根據花括號的對應關係找出與第一個“{”對應的“}“的位置;

6.  透過4與5將Web Service的函式提取出來,存入一個函式字串中。

7.  在第一個“{”的位置之後插入“try{”;(try的字元是從模板檔案中讀入的)

8.  在最後一個“{”的位置之前插入“catch………………”;(catch的字元是從模板檔案中讀入的)

9.  將新生成函式字串替換檔案字串中原有的函式字串

10.  反覆3-9步驟,直至檔案字串尾;

11.  將檔案字串寫入檔案中,替代原來的檔案。

透過這個過程,就可以將上面所有類似於程式碼段一的程式碼都生成程式碼段二的程式碼。開發人員可以不去重複的寫try與catch的程式碼。

如果在開發過程中加入了一種新的異常類(比如生成ExceptionEx1, ExceptionEx2),我們所要做的就是修改模板檔案,Web Service的所有檔案就好。

 

²  根據Facade層自動生成Web Service的程式碼

這個過程與修改過程不一樣的地方就是輸入並不是讀取已經存在的Web Service檔案,而是讀取Facade層的程式碼,生成Web Service檔案。下面是具體的過程描述:

1.  透過輸入得到Facade層的目錄以及Web Service的目錄;

2.  讀取Web Service生成模板。將其讀入一個大的字串中。

3.  遍歷Facade目錄,找出所有最後九個字元是“facade.cs”的檔案;(我們定義的facade類檔案);設為XXXfacade.cs

4.  將檔案內容讀入一個檔案字串中;

5.  迴圈查詢以 “/// ”為開頭的字串位置;(生成Facade方法時加入註釋的最後一條。)

6.  在Web Service字串中加入一個新的方法的字串;

7.  找出上面步驟字串位置之下第一個“{”的位置,然後再根據花括號的對應關係找出與第一個“{”對應的“}“的位置;

8.  透過4與5將Web Service的函式提取出來,存入一個函式字串中。

9.  讀出函式字串中Facade的方法。(如果是函式屬性是private則跳過。)讀出函式字串中Facade方法的引數。

10.  修改Web Service字串中的替換字元,將Facade的方法以及參法分別寫入。

11.  反覆3-10步驟,直至Facade檔案字串尾;

12.  將新生成的Web Service字串寫入XXXService.asmx.cs以及XXXService.asmx檔案中。(XXXService.asmx檔案的內容很少,與函式無關。)

 

透過這種方式生成的web service的程式碼將會對應所有的facade層的類與函式。並且將異常例外處理進行了統一的處理。減少了開發人員的工作量以及出錯的機會。使可以找到出錯的日誌,有利於除錯過程。

 

目前還沒有看出這樣生成的程式碼有什麼大的問題,希望這麼做過的朋友們給給我好的建議。

還有,我對程式碼生成工具產生的程式碼的問題有一些想法,回頭與朋友們交流吧。

 

如果對專案的前因後果不清楚,可以參考以前的文件:

http://www.csdn.net/develop/author/netauthor/ViktorYu/

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-977247/,如需轉載,請註明出處,否則將追究法律責任。

相關文章