18

自從微軟推出了應用程序塊,我已經碰到誰使用Exception Handling Application Block人。我最近仔細看了一下自己,總結了如下基本功能(如果您已經知道它的作用,請跳過以下代碼塊):微軟異常處理塊 - 它不是一個完美的例子嗎?

異常處理應用程序塊旨在集中並完全配置配置文件以下key exception handling tasks

  • 日誌作爲例外
  • 更換異常
  • 包裝紙的異常
  • Propa門控的異常

該庫是由有您修改的try catch塊如下:基於什麼是在app.config中指定了策略名

try 
{ 
    // Run code. 
} 
catch(DataAccessException ex) 
{ 
    bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Policy"); 
    if (rethrow) 
    { 
     throw; 
    } 
} 

see here for docs),HandleException要麼...

  • 拋出一個完全新的異常(取代原來的除外)
  • 包裹原始異常在一個新的並拋出
  • 吞異常(即什麼都不做)
  • 有你重新拋出了原來的異常

此外,您還可以配置它事先做更多的東西(例如日誌除外)。

現在這是我的問題:我完全無法看到如何使它可配置是否有利於是否替換,包裝,吞下或重新排除異常。根據我的經驗,這個決定必須在你寫的代碼,因爲你通常會變更時,異常處理行爲改變周圍或調用代碼時進行。

例如,當您重新配置時,您的代碼可能會開始出現錯誤行爲,從而導致特定點拋出的特定異常現在被吞下而不是重新排出(catch塊之後可能有代碼,發生異常)。異常處理中的所有其他可能更改也是如此(例如,替換 - >重新拋出,吞下 - >換行)。

所以,我的底線是,異常處理模塊,解決了真的不存在實踐問題。異常日誌記錄和通知位是好的,但不是所有其他的東西只是過度工程的完美例子嗎?

+0

好問題。 +1。還在http://stackoverflow.com/questions/438073#438230中添加了「異常消除搭配」的參數。你能檢查出來嗎? – VonC 2009-01-14 19:48:27

回答

12

如果你使用控制流異常,那麼你會想遠離基於策略的異常處理掉。

但是,如果您想要視爲不可恢復的異常(後臺任務失敗,套接字已斷開連接,文件被刪除等),則可能需要具有可配置的基於策略的異常處理。例如,如果您正在開發API,您可能希望API中的每個函數僅引發標準例外(ArgumentException等),以及您自己的特定於庫的例外情況內部非標準異常(例如MyLibraryException)。在這種情況下,所有重要的是某些東西無法正常工作。你並沒有把這個例外分開,並找出出了什麼問題。你只是承認,一些事情出了問題,並且你應該現在做一些的事情。

一些事情應該是可配置的,因爲它不關你做什麼。向用戶顯示一個消息框?模態還是非模態?記錄異常?你如何記錄異常?調用日誌Web服務?追加到日誌文件?寫入Windows事件日誌?將條目插入數據庫?將條目插入兩個數據庫?它對你的應用程序的其餘部分無關緊要。如何處理異常的選擇與應用程序的其餘部分完全正交。

(順便說一句,這不是我怎麼會接近配置的基於策略的異常處理,我會傾向於更多地轉向一個AOP風格,比如在容器中註冊一個異常記錄器攔截。)

+0

我同意你可能想要在應用程序關閉之前配置會發生什麼(通知用戶,登錄異常,發送電子郵件到支持等)。你似乎用「控制流」來引用所有其他的東西(吞下,重新拋出等等),對吧? – 2009-01-03 10:49:02

+0

不一定 - 它取決於軟件。如果您將異常視爲可恢復的,那麼您將它們視爲控制流。如果您將它們視爲不可恢復,那麼您可能對此應用程序塊感興趣。 – yfeldblum 2009-01-03 12:22:00

1

很簡單:如果你想在你的發佈代碼不同的異常處理比你的調試代碼,那麼這將是有益的。

+0

你有一個真實的例子嗎?你是否在調試模式下重新拋出特定的異常,但在釋放時吞下它? – 2009-01-03 02:19:00

+0

我一直在尋找這些真實世界的例子來證明它的有用性,但迄今爲止還沒有成功。 – 2010-07-14 06:58:55

0

在我看來,使用異常處理塊的一個實際值從你的catch塊中的一行代碼開始:

bool rethrow = ExceptionPolicy.HandleException(ex,「Data Access Policy」);

一行代碼 - 你能得到多少簡單?在一行代碼後面,配置策略可以輕鬆執行策略的分配/更新,而無需重新編譯源代碼。

如前所述,異常政策實際上可以執行許多操作 - 無論您的政策中有何定義。在catch代碼塊中顯示的一行代碼中隱藏複雜性,是我看到真正價值的地方。

我會說複雜,但沒有過度工程。所以我的想法是,當您需要改變處理/記錄異常的方式時,可以在維護期間看到巨大的收益,因爲它可以輕鬆地更改配置,並且仍然具有相同的一行源代碼。

5

我在開發沒有可恢復狀態的函數時遇到了這個問題。我相信這種策略驅動的異常處理實際上是有用的,並確保作爲該項目一部分的所有其他開發人員實際上都遵守不可恢復異常的標準。

我同意上面的海報,如果您將它們用於控制流程,您可能希望遠離基於策略的異常。

3

我不認爲這完全在工程上。事實上。異常可以通過中央處理程序的事實在我的工作中是一件好事。我有開發人員會吃掉每一個例外 - 處理或不處理,這樣就不會冒泡到最高層,並在最終用戶面前發出令人擔憂的警告,或者在未被捕獲時嚴重弄亂服務/守護進程。

現在,我們可以隨時啓動日誌記錄,而無需在整個應用程序中重新啓動或不必要地將日誌記錄邏輯進行分配。現在我們可以在不離線的情況下觀看例外情況等。

智能編程如果你問我...

4

我有該聲明同意「異常處理模塊,解決了真的不存在實踐的問題。」自從發佈以來,我一直使用該塊,我很少覺得使用它可以獲得更多收益。那麼,也許有點頭痛。 :)

在開始之前,我會承認我喜歡Exception Shielding at WCF Service Boundaries的功能。然而,這是最近添加的,不涉及編碼 - 只有屬性和配置,並不是通常銷售塊的方式。這是微軟如何展示它在http://msdn.microsoft.com/en-us/library/cc309250.aspx

alt text http://i.msdn.microsoft.com/Cc309250.05-CrossLayer(en-us,MSDN.10).gif

我的眼睛上面是流量控制。

try 
{ 
    // Run code. 
} 
catch(DataAccessException ex) 
{ 
    bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Policy"); 
    if (rethrow) 
    { 
     throw; 
    } 
} 

當您將流量控制方面與上面的代碼相結合時,您絕對不是making wrong code look wrong。 (不要介意if(rethrow)構造不提供太多抽象。)這可能會使不熟悉策略定義的開發人員的維護變得更加困難。如果配置文件中的postHandlingAction發生更改(可能會在某個時候發生),那麼您可能會發現應用程序以未曾測試的意外方式運行。

也許我不會覺得這是令人反感的,如果該塊沒有處理流量控制,但只是讓你連鎖處理程序在一起。

但也許不是。其實我不記得曾經被要求:

  • 處理異常時添加一塊新的功能(例如除了記錄到事件日誌同時發送電子郵件實際上,記錄塊可以做到這一點。如果你已經自己記錄異常:))
  • 跨整個「策略」更改異常處理行爲(吞下,重新拋出或拋出新的)。

我並不是說它沒有發生(我敢肯定有人有故事!我只是覺得異常處理應用程序塊使得程序更難理解和維護,這通常比塊提供的功能更重要。