Nov. 18 16:35~17:35
上禮拜六「第二梯次例外處理設計與重構實作班」課程中,有一位學員問了Teddy一個問題…
學員:你上課的時候提到catch block的責任之一是負責「錯誤處理(error-handling)」,也就是說如果系統狀態不對了,要想辦法將系統恢復到一個正確的狀態。
Teddy:對啊。
學員:我們之前有遇到一個錯誤處理的問題,團隊成員和主管討論了很久都沒有結論。
Teddy:什麼問題?
學員:如果錯誤處理的程式也發生錯誤,那該怎麼辦?
Teddy:很簡單,三秒鐘就可以回答你。如果錯誤處理的程式也發生錯誤,無法將系統回復到正確的狀態,就丟出一個ErrorHandlingException來代表這樣的異常狀況。
***
上述問題可以用下列例子來思考。有遊客在海邊溺水發出求救訊號(丟出例外),這時候「救生員」(例外處理程式)要去搶救這位溺水的遊客。如果救生員搶救失敗,自己也溺水了,那怎麼辦?
- 假裝什麼事都沒發生,把求救訊號(例外)吃掉。
- 繼續向外發出求救訊號。
現在答案就很明顯,應該是要選2,繼續向外發出求救訊號。但是接下來還是有一個問題需要考慮,那就是例外蓋台的問題:
- 如果救生員直接發出ErrorHandlingException,那麼這個例外會覆蓋掉原本遊客溺水的例外,產生「例外蓋台」的問題。
所以說,這個ErrorHandlingException應該成為一個suppressed exception,被加入到原本遊客溺水的例外身上(代表遊客溺水的例外在這裡稱為function failure)。
***
下圖說明了當例外處理失敗(包含cleanup失敗)的時候要如何處理的作法。
簡而言之,鄉民們需要:
- 自己定義ErrorHandlingException、FaultHandlingException、CleanupException、這三種runtime exception。
- 如果catch block需要做error-handling或是fault-handling的工作但卻失敗了,則產生ErrorHandlingException、FaultHandlingException來表示這種例外狀況。
- 如果finally block需要做cleanup的工作但卻失敗了,則產生CleanupException來表示這種例外狀況。
寫到這裡鄉民們可能會想:「丟出了ErrorHandlingException、FaultHandlingException、CleanupException難道就沒事了嗎?要不要在caller的程式碼中去處理這些例外?」
這個問題要看鄉民們對於程式強健度的要求有多高,以及這些例外產生的機率。雖然「理論上」程式運行的時候有可能會發生ErrorHandlingException、FaultHandlingException、CleanupException,但「實際上」這些例外發生的機率與頻率有多高,有時候在設計階段並不容易預測。如果針對每一個function或是method都要去思考要如何處理它們「可能」會丟出來的所有例外,那麼可能會造成不必要的過度設計,浪費太多資源。在這種情況下,開發人員只要確定:
- 所有的例外狀況都有被回報。
- 回報語意清楚的例外,以便協助開發團隊縮短事後除錯時間。
這樣的例外處理策略就可以應付大部分的情況,也可以避免過早且過度設計例外處理方法的問題。
***
友藏內心獨白:例外處理的例外,還是例外。
我已經等不及想買這本書了 ^ ^.
回覆刪除