2013-10-29 169 views
0

我工作的n層應用程序,只有在我的表現層做的try/catch n層。如果數據層或業務層發生錯誤,則此錯誤將由我的表示層中的try/catch捕獲。這是好的,還是我應該嘗試捕捉每一層的每種方法?使用嘗試捕捉

+1

處理異常時,只要您能夠繼續執行代碼,即使出現錯誤,無論發生什麼層次。 – Servy

回答

0

這裏是要避免在任何層面的內容:一堆方法,所有看起來像這樣:

void method() 
{ 
    try 
    { 
     // some code here that may potentially throw an exception 
    } 
    catch (/* anything here */) 
    { 
     // code right here to handle that exception 
    } 
} 

如果這是你在做什麼這樣做,你可能會回到VB的舊版本On Error Goto系統,因爲你還沒有獲得任何東西。異常爲錯誤處理提供了兩個主要優勢:以不同方式輕鬆處理不同類型錯誤的能力,以及在程序調用堆棧中進一步捕獲錯誤的能力。這是你在這裏問的第二個優點。

因此,我們看到您確實希望允許異常「向上冒泡」到更高層,因爲它是我們爲什麼總是有例外的很大一部分......但是您是否總想在表示層處理它們?不,我們可以做得更好。有時,可能存在關於如何響應來自數據層的某些例外的業務規則。有時,數據層本身可能能夠處理異常並從異常中恢復,而不用提醒其上方的圖層。另一方面,例外的一個優點是它可以讓你在較低的層次上編寫較簡單的代碼,並且對於錯誤處理代碼而言,正常的程序執行流程的中斷更少。這樣做的代價是將更多的try/catch放置在表示層中。同樣,這並不意味着表示層是處理它們的唯一地方,但是這是確保它們不會越過未捕獲到表示層的努力的地方。如果您無法在其他地方處理它們,請確保您有方法在表示層捕獲它們,並以友好的方式將它們展示給用戶。使用相同的機制記錄或報告您的異常也是一個好主意,因此您可以獲得有關應用程序失敗的良好指標,然後使用該信息使您的應用程序更好。

當你確實處於最後一個異常處理程序中時,你可能還想考慮終止應用程序。如果你真的有意想不到的事情發生,如未處理的異常通過表示層,那麼有一個有效的思想流派,表明繼續運行該程序可能不是一個好主意。但即使在這種情況下,您也需要捕捉並嘗試報告異常,然後儘可能優雅地崩潰。

1

在一般情況下,最好是捕捉儘可能接近它發生在哪裏,讓您的代碼可能做一些事情來修復/調整/反應問題的異常。這個「做什麼」取決於情況。例如,如果您的服務層呼叫失敗,則可能需要重試呼叫,因爲該服務可能太忙;而如果你的存儲過程被破壞了,那麼你重試多少次並不重要,它會被打破,直到數據庫中的邏輯被糾正。

如果你想要做的是錯誤日誌,然後抓住儘可能接近它發生在哪裏的錯誤是那麼有用。

我曾經工作過的每一個項目必須在應用程序的每一層try-catch塊。

try-catch的推論是Fail Fast的概念,它通常表示當系統立即失敗而不是緩慢失敗時(讀取:數小時,數天,數週,數月甚至數年的操作),調試生產力會增加。

在.NET Framework快速失敗的一個很好的例子是Convert.ToInt32()使用相對於一個直線上升鑄造使用(int),像這樣:

int? settingValue = Convert.ToInt32(SomeSettingString); 

if(settingValue == null) 
{ 
    // Do something here 
} 
else 
{ 
    // Do something else here 
} 

如果SomeSettingString可以轉換爲一個int,則該值被設置爲和Do something else邏輯被執行。假設從現在開始一年後,設置發生變化並返回null,因爲轉換失敗,現在突然邏輯執行,並且發現這種情況是一種調試冒險,如果您能發現的話。像這樣的大多數問題似乎只發生在PRODUCTION而不是DEV。

現在讓我們來看看同樣的事情,但由於沒有快,就像這樣:

try 
{ 
    int settingValue = (int)SomeSettingString; 
} 
catch(Exception ex) 
{ 
    // Fail fast and throw exception 
    throw new Exception("Fail fast"); 
} 

現在發生異常時立即設置字符串導致一個轉換到int失敗。

注意:要注意的是未能快速通過空catch塊被破壞的是「吃」的例外。應避免try塊空catch塊,因爲它們不可避免地導致了「吃」的例外情形。

不要這樣做:

try 
{ 
    // Exception waiting to happen here 
} 
catch(Exception ex) 
{ 
    // Catch-all, because all exceptions derive from Exception class 
    // So this will eat exceptions and pretend like they never happened 
}