天天看點

異常管理介紹如何處理異常好的習慣

在任何應用系統開發中,異常管理對開發人員來說都是一個關鍵領域。作為一個開發人員,你應該采用一種合适的、能讓你編寫健壯且高品質代碼的異常管理政策。如果使用得當,異常管理将是一個很強大的概念而且使你的開發工作變的很容易。然而,一個不合适的異常處理将會使你的應用系統性能降低。

在你鑽研這些之前,要先搞清楚異常管理是什麼,這點很重要。一般來說異常就表示“打破系統預定的假設”。“異常”和“錯誤”是不一樣的,為了解釋清楚,我們來看兩個例子:

       我們假設你試圖向一個檔案寫入資料,而你的應用程式也認為這個檔案在正确的路徑上。如果不在,就會抛出一個異常。而話說回來,如果你的職責是跟蹤此檔案,那麼代碼裡還有(找不到檔案的)異常那将是一個不好的編碼習慣,這種情況應該被校驗代碼處理(而不是異常)。

       再讓我們假設一個一般的ASP.NET程式中,你正試圖更新資料庫中所有必需的字段。你的應用程式認為此資料庫連接配接可用,假設實際上這個連接配接是不可用的……抛出異常是一個解決方案。而我們又把話說回來,如果更新資料庫的必填字段時出現有幾個值為空的字段,那抛出異常就沒有必要了,這些處理應該由校驗代碼完成。

       作為一個開發人員,你應該感受到通過try, catch, finally塊來建構一個結構化異常處理機制的優點。.NET架構提供了一大堆異常處理層次來處理不同種類的異常。所有的異常都繼承自Exception(基類)。你可以通過繼承來實作自定義錯誤處理以擴充異常處理機制。不幸的是,很多開發人員都誤用了這種架構能力。一個随時要記着的事是當一個異常發生在運作時時(這個架構)應該如何運作?一般有以下三種情況:

忽略異常,讓它在調用棧裡上升而被其它的catch塊捕獲。

捕獲異常,同時為你的應用程式執行必要的動作,如果你不想再次在異常中抛出異常的話。

捕獲異常,并用其它異常覆寫它。這樣和你的應用程式有更密切的關系。異常覆寫是為了避免打破(架構中的)抽象層次。你可以通過你抛出的異常的InnerException屬性指定原異常是什麼,這樣就可以把你現有的異常用一個新的異常來覆寫了(更與你系統有關的)。為了了解異常覆寫,讓我們來看一個能引起IOException異常的方法,你可以在應用級别使用LoadingException 或 FailtoLoadInfoException來覆寫原有的IOException異常,這樣比把底層的IOException給使用者看到要來的好些。

  經驗總結

盡可能在最低級别處理錯誤。 避免通過異常處理機制将較低級别(DataAccess,Facade)抽象公開給較進階别(UI)。 如果您必須使異常沿棧上移,那麼應将較低級别異常轉化為對于處理層而言有一定意義的異常(自定義異常)。

一個應用程式的異常處理架構應該有以下幾種(要求):

探測異常;

執行代碼清除;

内部異常覆寫;

内部異常替換;

記錄并報告錯誤資訊;

建立能被外部監視的事件以幫助系統操作;

在開始你應該建立一個一緻的,健壯的異常管理架構,在你所有的系統中應該很好的封裝并抽象其記錄和報告等的細節。

       以下列出一些不錯的提示/建議供你在(設計)異常處理(時)參考:

抛出異常要不小的代價。是以,你應該盡可能地在“異常情況”下進行異常處理,不要去控制正規邏輯流程。比如,以下代碼:

void EmpExits(string EmpId) {     //

異常管理介紹如何處理異常好的習慣

 search for employee    if(dr.Read(EmpId) ==0) // no record found    {        throw(new Exception("Emp Not found"));     } }

應該用以下代碼:

bool EmpExits(string EmpId) {     //

異常管理介紹如何處理異常好的習慣

 search for employee    if(dr.Read(EmpId) ==0) // no record found    {        returnfalse;     } }

避免在循環中捕獲異常,如果實在是要捕獲,那把整個循環都放在try/catch塊裡。

采用标準try/catch/finally異常處理方式進行處理,這在托管代碼裡是被推薦的。最後的Finally塊確定異常事件中的資源都被釋放掉了。 比如:

SqlConnection conn =new SqlConnection("

異常管理介紹如何處理異常好的習慣

"); try {     conn.Open();     // some operation     // some additional operations} catch(Exception ex) {     // handle the exception} finally {     if (conn !=null&& conn.State ==ConnectionState.Open)         conn.Close(); // closing the connection}

盡可能的用校驗代碼而避免使用異常。如果你知道一個可避免的條件可能會出現,那就讓它避免。比如,在執行任何操作以前,檢查空值(VB裡是Nothing),這樣可以避免使用異常以及性能問題。 以下代碼:

double result =0; try {     result = firstVal/secondVal; } catch(System.Exception e) {     // handling the zero divided exception}

應該替換成:

double result =0; if(secondVal !=null&& secondVal >0) {     result = firstVal/secondVal; } else {     result =System.Double.NaN; }

不要為沒有必要的情況(原文:reasons)抛出異常。再次抛出異常的開銷和執行個體化一個新異常的開銷一樣的大,同時再次抛出異常使程式調試工作增加難度。比如:

try {     // Perform some operations ,in case of  throw an exception…} catch (Exception e) {     // Try to handle the exception with e    throw; }

推薦的處理不同的錯誤的不同的方法是實作一系列的catch塊,這看起來好像沒有什麼,但可以讓你的異常處理從特殊走向普通。比如捕獲一個和檔案有關的異常明顯要比捕獲一個FileNotFoundException, DirectoryNotFoundException, SecurityException, IOException, UnauthorizedAccessException甚至最後的基類Exception,好的多。

ADO.NET 的錯誤應該通過 SqlException 或 OleDbException來處理。

使用ConnectionState屬性來檢查連接配接是否可用要比異常處理好的多。

要常使用Try/Finally,Finally提供了關閉連接配接的機會。Using語句可以達到同樣的效果。

        用指定的處理程式來處理異常。在一些情況下如果你知道一些可能的異常那就用相應的異常處理類,比如:

try {     

異常管理介紹如何處理異常好的習慣

 } catch(SqlException sqlexp) // specific exception handler{     

異常管理介紹如何處理異常好的習慣

 } catch(Exception ex) // Generic exception handler{ 

異常管理介紹如何處理異常好的習慣

 }

你的異常處理架構應該可以探測異常并在内部将其覆寫,(或是)使用其它異常将其替換,或是為監視系統而記錄和報告這些資訊。

本文轉自左正部落格園部落格,原文連結:http://www.cnblogs.com/soundcode/archive/2012/11/22/2782227.html,如需轉載請自行聯系原作者