2009-12-11 74 views
3

我有一個三層結構
1.介紹層
2.業務層
3.數據層
表示層通過服務門面業務層交互。現在我很困惑我應該在哪裏拋出異常,我應該在哪裏登錄它們,我應該在哪裏捕捉併吞下它們。目前,我正在登錄後在表示層中吞噬異常,而我正在記錄並將它們扔到其他地方。這會導致異常獲得記錄三次。這不是一個大問題,但我想知道關於這方面的最佳做法。何時拋出異常以及何時記錄它們?

例如: 表示層代碼:

try 
{ 
    UserService.GetAllUsers() ; 
} 
catch(Exception ex) 
{ 
    Logger.log(ex) // exception gets logged here 
    // redirect to a friendly user error page 
} 

UserService層代碼

try 
{ 
    IUserDAO userDAO = ServiceRegistry.GetRegistry().GetDAOFactory().GetUserDAO() ; 
    return userDao.GetAllUsers() ; 
} 
catch (Exception ex) 
{ 
    Logger.log(ex) ; // and here ! 
    throw; 
} 

DAOLayer代碼

try 
{ 
    // All db interaction code 
} 
catch(Exception ex) 
{ 
    Logger.log(ex) //and here !! 
    throw ; 
} 
+0

這一切都在同一臺物理機器上?或者你有服務器和客戶端?在我們的應用程序中,我們通常(嘗試記錄)所有物理機器上的錯誤消息...... – Fortega 2009-12-11 07:18:04

+1

當前這些都在同一臺物理機器上,但將來我們可能會將它們放在不同的物理機器上。應該這樣嗎? – 2009-12-11 07:21:10

+0

我認爲它的確如此。如果服務器上存在異常,那麼您希望將其記錄在那裏,但也要在客戶端調用導致異常發生的方法,以便在兩個位置上都可以追蹤錯誤。 它可能看起來像你記錄了太多/太多,但由於它會導致性能或存儲問題的機會非常小,所以我會像這樣離開它... – Fortega 2009-12-11 07:26:16

回答

4

絕對沒有必要將每段代碼放在try-catch塊中。例如,如果您的'DAOLayer'中發生異常,則您的日誌文件將包含3次相同的異常...

請記住黃金法則有例外 - 例外應該是例外!這通常意味着您應該只捕獲您能夠處理的異常 - 您應該忽略的所有其他異常 - 較高級別的處理程序應該處理這些異常。

如果擔心未處理的異常會導致應用程序崩潰(並且正確如此),則應該查看.Net公開的用於處理未處理的異常的兩個事件。第一個是AppDomain.CurrentDomain.UnhandledException,第二個是Application.ThreadException(它位於Windows.Forms命名空間中)。

1

我實在看不出爲什麼你的日誌記錄例外並重新推出它。當然無論哪個進程最終吞下它都可以進行日誌記錄。如果您想記錄該信息,則可以簡單地使用ex.StackTrace來獲取調用堆棧。

一般情況下,重新拋出異常時導致異常的問題,是不是可以在代碼是在一級處理,你會做什麼。您通常會使用更具體的catch塊來捕獲這些塊並進行適當的響應(例如,如果由於網絡超時而發生異常,您可以重試連接或嘗試連接到備份服務器)。您需要在修復它的地方記錄異常並繼續。

如果在得到異常的地方沒有什麼可以做的,那麼如果我不能指望進一步調用堆棧中的某些東西來爲我管理日誌記錄,我只會費心去捕獲並記錄它。否則,它只會創建一個相當無意義的重複消息。

+0

圖層的客戶端可能會改變,如果我沒有登錄我的圖層,我有點依賴客戶端來做日誌記錄,如果他們不這樣做,我就會喝湯。 – 2009-12-11 07:43:50

+1

那麼,這是一個明智的理由登錄多個地方 - 因爲你不能指望客戶端照顧日誌記錄。可解決的錯誤仍然應該單獨被捕獲。 – 2009-12-11 08:19:04

1

你應該拋出異常時,特殊的事情發生了 - 任何層上......如果你期待一些錯誤條件上來定期,代碼爲他們 - 顯示錯誤,給用戶和手段來修復錯誤。

記錄下所有的警示,無一例外!很高興有這些數據,如果你按照我以前的建議,你不會有太多的。

你應該從未吞例外。往上看。你會如何知道事情是否出錯?

+0

吞併異常而不是允許應用程序失敗有時可能是正確的調用。它正在交易魯棒性的正確性,有時魯棒性更重要。 – 2009-12-11 07:27:51

+0

始終記錄。您可以根據要求決定是否要引發異常。 – Oded 2009-12-11 08:48:22

1

我傾向於做的是爲每個級別一個例外,我包裝異常,並通過它,如果向上的下一層無法處理異常。

例如,如果您嘗試更新數據庫,但主數據庫已關閉,則可能只需轉到輔助數據庫,以便嘗試該操作,如果它工作,則記錄日誌但不通過它在。

我傾向於通過對不能處理的異常,直到我到達頂層。在那裏,對於某些錯誤將它們傳遞給客戶端,如果它是用戶可以做某些事情的例外情況,則以其他方式記錄併吞下。

如果它類似於內存不足,那麼在應用程序崩潰之前讓用戶知道,並準備妥善地死去。

0

而不是在自定義異常中包裝異常或僅依靠StackTrace爲您提供在最高級別登錄異常時需要的所有信息,您可以使用ex.Data在傳遞異常之前添加有關該異常的更多信息鏈,例如ex.Data.Add("filename", filename)。您的日誌代碼可以轉儲出所有這些附加屬性。這可能會爲您提供足夠的信息來了解拋出異常的原因並重現它。

相關問題