iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0

定義例外類別

錯誤的分類有很多種方式。......然而,當我們在應用程式裡定義例外類別時,我們最關心的應該是,他們是如何被捕捉的

我們來看一個分類不佳的例子:

ACMEPort port = new ACMEPort(12);

try {
    port.open();
} catch (DeviceResponseException e) {
    reportPortError(e);
    logger.log("Device response exception", e);
} catch (ATM1212UnclockedException e) {
    reportPortError(e);
    logger.log("Unclock exception", e);
} catch (GMXError e) {
    reportPortError(e);
    logger.log("Device response exception", e);
} finally {
    ...
}

這段敘述有大量重複的程式碼,並且我們知道這類的處理程序,不論是哪種例外事件,所做的事大都相同。所以我們只要包裹 (wrap) 呼叫的 API,並確保其回傳共用的例外型態,便能大幅簡化程式。

LocalPort port = new LocalPort(12);

try {
    port.open();
} catch (PortDeviceFailure e) {
    reportError(e);
    logger.log(e.getMessage, e);
} finally {
    ...
}

而 LocalPort 只是一個簡單的包裹類別:

public class LocalPort {
    private ACMEPort innerPort;

    public LocalPort(int portNumber) {
        innerPort = new ACMEPort(portNumber);
    }

    public void open() {
        try {
            innerPort.open();
        } catch (DeviceResponseException e) {
            throw new PortDeviceFailure(e);
        } catch (ATM1212UnclockedException e) {
            throw new PortDeviceFailure(e);
        } catch (GMXError e) {
            throw new PortDeviceFailure(e);
        }
    }
    ...
}

包裹第三方 API 是非常好的技巧,能夠減少對其依賴。除了將來要更換不同函式庫時更加容易,在測試自己程式碼時也更方便模擬呼叫。

避免 null

昨天撰寫工作上的專案時,程式在運行中報了一些錯誤,源自於一些來自後端 API 回傳的資料,在前端做使用時沒有檢查 null 的情形。於是我添加了些函式運行時的 null 檢查,並補上了資料中的 null 型別,順利解決了這個小問題。

今天在閱讀錯誤處理篇章時,作者說:「我們很容易發現程式碼的問題,在於沒有進行 null 的檢查,然而事實上,我們的問題可能出在做了太多 null 的檢查。」

我認為原因是當我們要進行 null 檢查時,很容易因為疏忽而漏檢查,並且檢查 null 會使的程式變的冗長,進而模糊程式的意圖。所以最好的方法是,不要回傳 null 值

如果想用函式回傳 null,或是 null 來自第三方 API 的回傳,那不如拋出一個例外事件,或使用特殊情況模式 (Special Case Pattern),回傳一個 SPECIAL CASE 物件。而以我個人而言,若下一次接收 API 資料時收到 null,我可能會其做資料轉換,例如改成空字串或空陣列,以避免 null 的出現及後續判斷。

同理,既然要避免函式回傳 null,勢必也要避免函式傳遞 null。
只是我個人認為,在參數中傳遞 null 有時並非刻意,而是未預期的錯誤,所以在傳遞 null 這件事上,僅能盡量避免以減少錯誤狀況的發生,卻是難以杜絕。

小結

錯誤處理的議題在今天告一段落,明天將會開始聊聊關於程式與程式間的邊界話題。


上一篇
錯誤處理(一)
下一篇
邊界
系列文
重新開始學程式,【無瑕的程式碼:敏捷軟體開發技巧守則】共讀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言