2008-12-03 28 views
12

我正在開發一個第三方函數庫的包裝,它與一些特殊的硬件接口。所以基本上,我想用連接和斷開方法將dll函數(bool Connect(),void Disconnect()等)封裝在MyHardwareObject中。何時重新拋出異常,何時返回FALSE?

從DLL連接功能可以拋出一些具體的例外,例如,當在硬件不存在。對於應用程序,有關連接方法失敗原因的信息被認爲是不重要的,因此不需要包含在例外中的附加信息。

處理這些異常的最佳方式是什麼,返回false,或者將未處理的異常留在這裏,然後在處理連接方法返回false這一事實的級別上捕獲它?

bool MyHardwareObject.Connect() 
{ 
    try 
    { 
     ThirdPartyLibrary.Connect(); 
    } 
    catch (SomeException) 
    { 
     return false; 
    } 
    return true; 
} 

與之相對

bool MyHardwareObject.Connect() 
{ 
    ThirdPartyLibrary.Connect(); 
    return true; 
} 

(或在第二種情況下更好void MyHardwareObject.Connect(),因爲我們要麼返回true,或者拋出一個異常?)

或者還有什麼會怎麼做?最重要的是:爲什麼?

回答

7

這真的很難例外和返回代碼之間做出明智的選擇。這取決於很多事情,以及如何在代碼庫的其餘部分處理錯誤將是最重要的 - 保持一致。

最近,我傾向於更多地轉向了「不拋出一個異常,如果它不值得」。我們的異常做了很多工作:記錄東西,創建堆棧跟蹤等。如果我只是想將一個字符串轉換爲一個整數,如果輸入的字符串格式不正確,則拋出異常可能是不值得的。另一方面,如果我們的系統中無法使用正確的數據構建對象,那麼我的系統中就不需要這些對象,在這種情況下,它們的構造函數會拋出異常。

如果代碼庫的其餘部分並沒有給你如何做任何暗示,我喜歡這種經驗法則:想象,拋出一個異常,使您的計算機發出一聲蜂鳴聲。只要你能忍受它,投擲就很好。

9

在我看來,第一種情況是肯定比第二個好。你需要你的硬件庫包裝第三方庫的方式,你的用戶不必知道它的內容。
如果需要,除了真或假的錯誤處理更詳細,你可以考慮重新拋出自己的異常,翻譯從第三方庫之外的東西用自己的代碼更加一致。

6

我會傳遞例外。如果你不知道,你正在屏蔽可能重要的信息,以後可能會有用。我知道你現在沒有使用它,但是如果你在將來決定根據錯誤類型處理不同的恢復會怎麼樣。此時,您將不得不撤消您編寫的所有代碼以屏蔽異常。儘管我不同意@MadKeithV的說法,但我認爲他有責任在您自己的異常中包裝異常,可能會爲您的應用程序提供更好的語義。

+0

嗯,我並不是在暗示重要的信息,而是認真考慮哪些信息是重要的傳遞,哪些信息應該由Connect安全地處理失敗或成功,而不是盲目傳遞所有異常。所以我認爲我們大多同意。 – 2008-12-03 13:51:11

0

我相信異常機制背後的原理是「失敗的快速」的理論。

你想讓你的客戶端應用程序「快速失敗」是連接不成功嗎?
如果是,只需拋出異常或將異常封裝在自己的應用異常中。

如果客戶端忽略該異常,他的應用程序將停止。

返回false意味着客戶端可能會忽略的問題,他的應用程序仍然可能崩潰,但「後來」 ......

1

這是爲你的程序運行所需的第三方庫,或者它只是增加一些額外的功能,雖然不錯,但不是必需的?另外,硬件可能會失敗。最後,硬件會拋出多少種類型的異常?

如果您的程序運行時實際上並不需要該庫,那麼您肯定需要在某個時候捕獲該異常,但是您可能希望更高一些。

如果硬件可能會拋出多種類型的異常,則更可能是您想重新拋出異常,因爲只是返回一個值會導致您丟失一些信息。但是,您確實說客戶不在乎爲什麼它失敗了,只是它做到了,所以這不應該成爲問題。

最後,如果硬件故障很普遍,那麼與故障很常見的情況相比,您可能更希望返回錯誤代碼(或者在此情況下爲false)。

我認爲在你的情況下,它真的歸結爲第一個問題。如果你真的不需要這個庫,請返回false並確保它非常明確地記錄了該操作可能由於任意原因而失敗,並且他們需要檢查返回值。如果你需要它的工作,重新拋出異常,並讓它傳播到任何你可以優雅地退出的地方。

+0

它是必需的 - 與此硬件接口是應用程序的主要任務。我是否正確理解你:你不會使用返回值,因爲有人可以通過調用MyObject.Connect()來使用,而不用檢查返回值,就像在if(!MyObject.Connect())中一樣。 `? – Treb 2008-12-03 15:50:42

3

我會建議第二個。根據例外情況處理異常並採取正確的行動將成爲調用者的責任。 假設Connect拋出AccountExpiredException,NetworkUnavailableException,InvalidCredentialsException等(這些僅僅是示例)我可以提示用戶「修復」異常(聯繫管理員,檢查網絡電纜,檢查用戶名/密碼)。 我甚至會建議刪除返回值(指標),並使其無效。看看SqlConnection Open方法 - 就像你連接 - 它不會返回值,而是會引發異常。 吞下這樣

bool MyHardwareObject.Connect() 
{ 
    try 
    { 
     ThirdPartyLibrary.Connect(); 
    } 
    catch (SomeException) 
    { 
     return false; 
    } 
    return true; 
} 

異常是不是一個好主意恕我直言。我會建議你實施IDisposable模式。 只是我2美分。

6

閱讀:http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

簡而言之:

是否來電有返回值有什麼用處?它可以恢復還是世界末日的錯誤?如果這只是一個小問題,請使用返回碼。如果各種狀態的發生頻率相同(50%時間失敗,50%時間起作用),則使用返回碼,因爲調用者必須處理這種情況,而異常無助於此。

你想傳遞額外的信息(比如第三方的東西的設置,所以有人有機會調試後來發生的事情)?使用例外。