Pete Goodliffe

太多程式設計師忽略錯誤#

我走在路上要去酒吧見朋友。匆忙之中,我被路緣絆倒,臉朝下摔了一跤。腿很痛,但我趕著見朋友,就繼續走。走得越遠,痛得越厲害。到了酒吧,我因為太分心而沒有好好享受。隔天早上去看醫生,發現脛骨骨折了。如果我當時停下來,就能避免繼續走路造成的額外傷害。

太多程式設計師寫程式就像作者那次糟糕的夜出——「錯誤?不會很嚴重吧。我可以忽略它。」 這不是一個可靠程式碼的策略,這只是懶惰(而且是錯誤的那種)。

永遠檢查,永遠處理#

無論你認為程式碼中出錯的可能性有多低,你都應該永遠檢查並處理錯誤。每一次。你不是在節省時間,而是在為未來埋下隱患。

錯誤回報的常見方式#

我們在程式碼中以多種方式回報錯誤:

  • Return codes(回傳值)——用函式的回傳值來表示「失敗」。錯誤回傳碼太容易被忽略了。你多常檢查 printf 的回傳值?
  • errno——C 語言一個特殊的全域變數。容易被忽略、難以使用,在多執行緒環境中還可能造成問題
  • Exceptions(例外)——一種更結構化的、語言支援的錯誤處理方式。你不可能忽略它們……真的嗎?常見的反模式:
    try {
        // ...do something...
    }
    catch (...) {} // ignore errors
    這個結構唯一的「優點」是清楚地表明你在做一件道德上有問題的事。

忽略錯誤的後果#

如果你忽略一個錯誤、視而不見、假裝什麼都沒發生,你就是在冒很大的風險。就像作者的骨折一樣,如果當時就處理,本可以避免更多的傷害。

不處理錯誤會導致:

  • 脆弱的程式碼(brittle code)——充滿令人興奮的、難以追蹤的 bug
  • 不安全的程式碼(insecure code)——駭客經常利用糟糕的錯誤處理來入侵系統
  • 糟糕的結構(poor structure)——如果你的程式碼中充滿了處理起來很煩人的錯誤,你的介面可能設計得不好。讓錯誤處理更不突兀、更不繁重

你需要在介面中暴露所有潛在的錯誤狀態。不要隱藏它們,不要假裝你的服務永遠正常運作。在最早的機會處理問題,保持短帳。

常見的藉口#

為什麼我們不檢查錯誤?常見的藉口包括:

  • 錯誤處理會打亂程式碼的流程,讓「正常」的流程更難閱讀
  • 這是額外的工作,而我有截止日期
  • 我知道這個函式呼叫永遠不會回傳錯誤
  • 這只是個玩具程式,不需要寫成生產品質

這些藉口都站不住腳。每次你遇到錯誤處理的問題時,反駁這些藉口,然後正確處理錯誤