2008-08-22 74 views
9

我有一些代碼給一個實用程序,然後發送電子郵件給該用戶的用戶ID。您是否爲特定問題或一般例外編寫例外情況?

emailUtil.sendEmail(userId, "foo"); 

public void sendEmail(String userId, String message) throws MailException { 
    /* ... logic that could throw a MailException */ 
} 

MailException可以拋出一些原因,與電子郵件地址的問題,與郵件模板的問題等

我的問題是:你創建的每一個新的異常類型這些異常,然後單獨處理它們,或者您是否創建一個MailException,然後在異常(計算機可讀,而不是描述文本)中存儲一些東西,這些異常允許我們根據實際發生的事情做不同的事情。

編輯:作爲一個澄清,例外不適用於日誌和不是,這與代碼如何對它們做出反應有關。爲了保持與郵件例如去,讓我們說,當我們發送郵件可能失敗,因爲你沒有一個電子郵件地址,或者它可能是因爲你沒有有效的電子郵件地址,或者它可能會失敗..等

我的代碼會想不同的反應,每一個問題(主要是通過改變信息返回給客戶端,但實際的邏輯也一樣)。

難道是最好有這不得不給它一些內部的這些問題,每一個或一種把傘異常的異常實現(枚舉說了),讓代碼區分什麼樣的問題,它是。

回答

8

我通常從一般的異常開始,並根據需要進行子類化。如果需要的話,我總是可以捕捉到一般的異常(以及它的所有子類異常),但也可以捕捉到具體的異常。

來自Java-API的示例是IOException,它具有FileNotFoundException或EOFException(以及更多)之類的子類。

這樣,你得到兩者的優點,你不必扔從句,如:

throws SpecificException1, SpecificException2, SpecificException3 ... 

一般

throws GeneralException 

就足夠了。但是如果你想對特殊情況有一個特殊的反應,你總能找到特殊的例外。

1

這取決於你的應用程序在做什麼。你可能想扔在案件個別例外像

  • 該應用程序是高可用性
  • 發送電子郵件尤爲重要
  • 的應用範圍小,發送電子郵件是一個很大一部分它
  • 該應用程序將被部署到一個網站,爲遠程和你只會得到日誌調試
  • 您可以封裝在mailException例外的某個子集恢復,但不是別人

在大多數情況下,我會說只要登錄異常的文字,不要浪費你的時間已經相當granularizing顆粒例外。

10

在我的代碼,我發現大多數例外滲透達到,他們是由我的異常處理程序簡單地顯示一個消息給用戶(和寫入日誌)抓到一個UI層。畢竟,這是一個意外的例外。

有時候我也想趕上一個特定的異常(如你似乎想要做的)。但是,您可能會發現這種情況有點罕見,並且它指示使用異常來控制邏輯 - 效率低下(緩慢)並且經常被忽視。

因此,使用你的例子,如果你想運行一些特殊的邏輯沒有配置郵件服務器時,您可能需要一個方法添加到emailUtil對象,如:

公共BOOL isEmailConfigured()

...先調用它,而不是尋找特定的異常。

當有異常情況真的發生,它的真正含義,這種情況是完全出乎意料和代碼不能處理它 - 所以你能做的最好的是它報告給用戶(或將其寫入日誌或重啓)

作爲具有異常層次VS例外與 - 誤差碼功能於他們,我通常做後者。如果你只需要定義一個新的錯誤常量而不是全新的類,那麼添加新的異常就更容易了。但是,只要您嘗試在整個項目中保持一致,則無關緊要。

+0

你還記錄你的例外服務器端? – pjp 2009-08-07 10:39:42

+0

@php:是的,好點,如果它是一個服務器代碼。對於真正的客戶端應用程序(而不是web),我通常也可以選擇在客戶端登錄異常以進行調試。 – 2009-08-08 17:21:54

1

我傾向於從可能執行有問題的方法返回一個狀態對象列表,而不是使用異常。狀態對象包含嚴重性枚舉(信息,警告,錯誤,...)狀態對象名稱,如「電子郵件地址」和用戶可讀消息,如「格式不正確的電子郵件地址」

調用代碼將決定過濾到用戶界面以及自己處理的內容。

我個人認爲,例外的是嚴格的,當你無法實現正常的代碼解決方案。性能問題和處理限制對我來說有點太過分了。

另一個原因使用狀態的對象的列表是標識多個錯誤(例如,在驗證過程中)要容易得多。畢竟,你只能拋出一個例外,在繼續之前必須處理。

想象一下,一個用戶提交一個有畸形的目的地址,包含語言,你是阻止電子郵件。你會拋出畸形的電子郵件異常,然後,他們解決並重新提交後,拋出一個糟糕的語言異常?從用戶體驗角度來看,一次處理所有這些問題是更好的方法。

UPDATE:合併的答案

@Jonathan:我的觀點是,我可以評估的動作,在這種情況下,發送電子郵件,併發送回多失敗的原因。例如,「錯誤的電子郵件地址」,「空白郵件標題」等。

有一個例外,你只能滲透一個問題,然後要求用戶重新提交,他們發現了關於第二個問題。這是非常糟糕的UI設計。

重新發明輪子..可能。但是,大多數應用程序應該分析整個事務,以便向用戶提供最好的信息。想象一下,如果你的編譯器在第一個錯誤時停下來。然後修復錯誤並再次編譯,只是爲了讓它再次停止以發生不同的錯誤。屁股多麼痛苦。對我來說,這就是拋出異常的問題,也就是我說的使用不同機制的原因。

+1

例外情況非常有用,如果正確使用,使代碼更具可讀性。隨着每個現代虛擬機的發佈,語言功能(例如異常)的性能都會發生變化,所以您必須每次都對照if-子句(您顯然必須使用它來檢查方法的結果)來衡量它。如果檢查方法檢查結果混亂你的代碼,並使其難以維護。不要誤解我的意思 - 有時候狀態對象是一個很好的解決方案。特別是如果你處理多個錯誤(如你所提到的),它們比例外更有用。但是,這個決定應該是深思熟慮的。 – Mnementh 2009-08-14 11:01:38

2

@ Chris.Lively

你知道你可以在你的異常,甚至「狀態碼」傳遞的消息。你在這裏重新發明輪子。

0

我傾向於有更少的異常類型,雖然它不是真正的OO方法。相反,我把一個枚舉給我的自定義異常,它分類異常。大多數情況下,我有一個自定義的基本Exception,它可以保存到一些成員,這些成員可以在派生的Exception類型中被覆蓋或自定義。

幾個月前,我blogged關於如何國際化異常的想法。它包含了上面提到的一些想法。

-1

,我只想通過

throw new exception("WhatCausedIt") 
如果你想處理您的例外

去,你可以傳遞一個代碼,而不是「WhatCausedIt」的反應,然後用switch語句不同的答案。

+0

而不是將異常中的代碼作爲參數傳遞,您可以繼承異常並使用instanceof。 – Mnementh 2009-08-14 10:55:12

0

雖然可以differenciate代碼執行尋找的異常,如果它是由「抓exceptionType層次模式」或做並不重要,「如果(...)...其他異常代碼模式」

但是如果你正在開發將被其他人使用的軟件,比如圖書館,我認爲它是有用的創建你自己的異常類型,以通知其他人你的軟件可以拋出比正常軟件更多的異常,並且它們更好地捕捉並解決它們。

當我使用庫和他們的方法簡單地啓動一個'例外'我總是想知道:什麼會導致此異常?,我的程序如何反應?,如果有javadoc也許原因將被解釋,但必須有沒有一個javadoc或例外情況沒有解釋。使用WellChossenExceptionTypeName可以避免太多的開銷女巫

0

這取決於捕獲異常的代碼是否需要區分異常或是否僅使用異常來出錯到錯誤頁面。如果您需要區分NullReference異常和調用堆棧中較高位置的自定義MailException,請花時間寫出它。但是大多數時候程序員只是使用異常來捕捉網頁上的錯誤。在這種情況下,你只是在努力編寫一個新的例外。

1

我認爲上述的組合會給你最好的結果。

根據問題,您可以拋出不同的異常。例如缺少電子郵件地址= ArgumentException。

但是,在UI層中,您可以檢查異常類型,並在需要時檢查消息,然後向用戶顯示相應的消息。我個人傾向於只向用戶顯示一條信息消息,如果拋出某種類型的異常(我的應用程序中出現UserException)。當然,您應該儘可能多地清理並驗證用戶輸入,以確保任何異常都是由真正不太可能發生的情況生成的,而不是用於使用正則表達式可以輕鬆檢查的畸形電子郵件的篩選器。

我也不會擔心從用戶輸入中捕獲異常的性能影響。唯一一次你會看到異常中的性能問題是當它們被拋出並陷入循環或類似情況時。

2

我發現如果您需要讓CODE根據返回的異常決定要做什麼,請創建一個名爲異常的子類化常見基類型。通過的信息應該被認爲是「僅限人眼」,並且太脆弱以至於無法作出決定。讓編譯器完成這項工作!

如果您需要通過一種不知道檢查異常的機制將其傳遞給更高層,則可以將其包裝在RuntimeException(MailDomainException)的適當命名子類中,該類可能會被捕獲,並且原因會起作用根據。