簡體   English   中英

如何處理API方法拋出的基本異常?

[英]How to approach base exception thrown by API method?

假設我正在處理 強制使用庫API方法,該方法會拋出某種非描述性的基本異常; 例如,在Java中“拋出異常”。 假設我沒有修改庫源的選項,每次從我自己的方法調用API方法時,我都必須處理基本異常。 對於某些上下文,我的代碼看起來可能沒有干預:

public void myMethod() throws Exception { // I don't want to do this.
    someAPIObject.theirMethod(); // API method throwing base exception.
}

這里可能是我正在調用的API方法:

public void theirMethod() throws Exception { // This is my problem.
    // Does stuff that could cause problems, but is
    // lazy and implicitly throws base exception.
    // Now it's my problem!
}

我的問題是:我如何最好地處理我的方法拋出的這個基本異常? 我認為以某種方式保留所有原始異常信息同時傳播比基本異常更有用的東西符合我的最佳利益。 例如,我已經考慮過捕獲並將基本異常存儲在我自己的異常類型中並拋出它:

public void myMethod() {
    try {
        someAPIObject.theirMethod(); // API method throwing base exception.
    } catch (Exception e) {
        throw new MySpecificException(e); // Re-throw my own exception.
    }
}

我不是在尋找意見,而是尋找一些可靠且直截了當的證據(專業人員),為什么特定的解決方案是一個好的解決方案,以及任何cava(缺點)。 我的重點是Java,但我很好奇任何一般概念或“最佳實踐”。

毫無疑問,這個問題將被視為“太寬泛”或“基於意見”,但我會在它之前投入我的2c。

你的第二個代碼示例應該(幾乎)始終是要走的路:

public void myMethod() {
    try {
         someAPIObject.theirMethod(); // API method throwing base exception.
    } catch (Exception e) {
        throw new MySpecificException(e); // Re-throw my own exception.
    }
}

我的主要原因是我不想要泄漏抽象 例如,假設我有一些用於訪問具有以下界面的用戶的存儲庫:

public interface UserRepository {
    public User byId(UserId id);
}

我有一個MySql數據庫實現,所以有以下具體類:

public class MySqlUserRepository implements UserRepository {
    public User byId(UserId id);
}

在這個類中,我將需要處理JDBC異常。 如果我讓它們通過界面傳播,就像這樣:

public interface UserRepository {
    public User byId(UserId id) throws SqlException;
}

然后我的代碼的客戶端現在知道它在后台使用JDBC。 如果我像你一樣包裝它,那么底層數據存儲是完全封裝的,這是首先有一個抽象的點之一。 如果我提供一個使用其他數據存儲區的實現,例如Redis,那么SqlException就沒有任何意義了,但是我需要更新契約,現在讓方法拋出特定數據存儲可能拋出的異常。

假設您知道API可以拋出的異常子類的完整列表,您可能最好通過運行時檢查“破解”異常類型,並將方法包裝到引發特定異常的自己的包裝器中。

下面是一個示例:假設API可以拋出三個特定的Exception子類 - 即ExceptionOneExceptionTwoExceptionThree 你可以像這樣構建一個包裝器:

class SomeApiWrapper {
    public void myMethod() throws ExceptionOne, ExceptionTwo, ExceptionThree {
        try {
            someAPIObject.theirMethod();
        } catch (Exception e) {
            crackException(e);
        }
    }
    private static void crackException(Exception e) throws ExceptionOne, ExceptionTwo, ExceptionThree {
        if (e instanceof ExceptionOne) throw (ExceptionOne)e;
        if (e instanceof ExceptionTwo) throw (ExceptionTwo)e;
        if (e instanceof ExceptionThree) throw (ExceptionThree)e;
        throw new RuntimeException("Caught an exception of unexpected type", e);
    }
}

您的API的用戶不必捕獲Exception (這是一件非常糟糕的事情)並保留原始異常中嵌入的所有信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM