Dan Bergh Johnsson

兩種原因導致執行時錯誤#

在執行時期出錯基本上有兩種原因:

  1. 技術問題(technical problems)——阻止我們使用應用程式的技術問題
  2. 商業邏輯(business logic)——阻止我們誤用應用程式的商業邏輯

大多數現代語言,如 LISP、Java、Smalltalk 和 C#,都使用**例外(exceptions)**來處理這兩種情況。然而,這兩種情境非常不同,應該被謹慎區分。將它們都用同一個例外繼承階層表示,甚至使用同一個例外類別,是一個潛在的混淆來源。

技術例外#

無法解決的技術問題可能發生在程式設計錯誤時——例如嘗試存取大小為 17 的陣列的第 83 個元素。更微妙的版本是呼叫某個函式庫程式碼時傳入了不適當的參數。這時程式明顯偏離了正軌,應該拋出某種例外。

另一種技術情境是程式因為執行環境的問題而無法繼續,例如資料庫沒有回應。在這種情況下,你必須假設基礎設施已經盡了力——修復連線並重試了合理次數後仍然失敗。

對於這些情況,不應該試圖自行解決。讓例外向上冒泡到最高的架構層級,讓通用的例外處理機制做它能做的事——例如回滾交易、記錄日誌、通知管理員,並(禮貌地)回報給使用者。

商業例外#

相比之下,商業例外是因為領域邏輯的原因而無法完成呼叫的情況。例如,嘗試從餘額不足的帳戶提款。換句話說,這種情況是契約的一部分,拋出例外只是一個替代回傳路徑(alternative return path),是模型的一部分,客戶端應該意識到並準備處理。

對於這些情況,適合建立一個特定的例外(specific exception)或一個獨立的例外階層(separate exception hierarchy),讓客戶端程式碼能以自己的方式處理。

為什麼要分開#

在同一個階層中混合技術例外和商業例外,會模糊界線並讓呼叫者困惑:方法的契約是什麼、呼叫前需要確保哪些條件、以及應該處理哪些情境。

將兩者分開可以帶來:

  • 清晰度:明確區分技術故障和業務規則
  • 技術例外更有可能被應用程式框架統一處理
  • 商業領域例外能被客戶端程式碼真正考慮並處理