2008-10-16 49 views
0

存在這種異常系統的風格,其中組件拋出特定於組件的異常。例如,所有數據訪問類別都會拋出DataAccessException從組件中包裝異常

在這種風格,我經常發現自己不得不趕上並重新拋出的成分具有特異性異常,因爲調用的方法是delcared爲throws Exception

try { 
    int foo = foo(); 
    if (foo != expectedValue) { 
     throw new ComponentException("bad result from foo(): " + foo); 
    } 
    bar(); 
} 
catch (ComponentException e) { 
    throw e; 
} 
catch (Exception e) { 
    throw new ComponentException(e); 
} 

你發現自己做同樣的?你覺得它很醜嗎?

這個問題不是關於這種風格的有效性,而是這種風格約束之內的東西。

回答

3

這就是地獄般的醜陋。我想,沒有太多的評論這種醜陋的風格。如果你已經有了所有的代碼來處理使用原因的不同問題,那就行了。這只是使用

try { 
    componentCall(); 
} catch (ComponentException e) { 
    Throwable t = e.getCause(); 
    //Handle each possible cause 
} 

少維護的,比其他方式更加混亂,主要的一點是,我看不出有什麼優勢,使用它。

鑑於你被限制使用它,我至少要儘量避免拋出ComponentException,無論是否有原因,這使得它比它需要更混亂,在你的例子中我會添加一個InvalidFooException並將其添加爲通用ComponentException的原因。

try { 
    int foo = foo(); 
    if (foo != expectedValue) { 
     throw new InvalidFooException("bad result from foo(): " + foo); 
    } 
    bar(); 
} 
catch (Exception e) { 
    throw new ComponentException(e); 
} 

getCause()旨在爲chains of exceptions是隻有因果,而不是語義相關的。

如果您需要它們來區分不同的異常(例如,應通過與AccessDeniedException不同的操作更正SQLExecutionException),那麼您的方法不適用(因爲強制在每個catch中使用getCause()需要做的事情非常糟糕,沒有任何好處,而只是在前面捕捉正確的例外)。

如果所有調用類都需要報告錯誤並取消,那麼包裝可能沒問題,但我不會這樣做,因爲它沒有什麼好處,如果以後需要區分會使您重寫很多東西。

什麼是有用的是創建同一類型的例外hierarchy of exceptions,在該行:

如果DataAccessException的將是根,那麼你就可以例如具有DataSourceUnavailableException,InvalidDataSourceException,InvalidDataException然後就可以決定只捕獲任一父母(如果行動相同)或分別捕獲每個異常。

順便說一句,你爲什麼需要這樣做?

+0

您所評論的風格:-)請假設我不得不跟進它(曾經在那種情況下?)。 問題是關於實際的第一次捕獲。它沒有用處,沒有它,我們得到一個ComponentException與另一個ComponentException作爲原因,這是不期望的。 – 2008-10-16 08:26:24

+0

如何拋出新的ComponentException(「來自foo():」+ foo)的錯誤結果; 拋出一個帶有ComponentException的ComponentException作爲原因? – 2008-10-16 08:35:57

0

這將可能不太難看這樣做(如果函數foo()是一個聲明爲拋出異常):

int foo; 
try { 
    foo = foo(); 
} 
catch (Exception e) { 
    throw new ComponentException(e); 
} 
if (foo != expectedValue) { 
    throw new ComponentException("bad result from foo(): " + foo); 
} 
bar();