《編程匠藝》讀書筆記之四

來源:互聯網
上載者:User

第六章 人非聖賢

  • 錯誤可能而且必將發生。幾乎任何操作都會帶來意想不到的結果,這種結果與有缺陷的程式中的bug不一樣,因為你預先就知道錯誤會發生。
  • 如果你不編寫代碼來處理這些錯誤情況,那麼你幾乎肯定最終會遇到bug;你的程式不會總按你的意願執行。

    錯誤產生得原因可以分為以下三種:

  • 使用者錯誤。一個好的程式會指出錯誤所在,並協助使用者來改正它。
  • 程式員錯誤。由程式員引入的代碼缺陷。
  • 意外情況。
  • 我們需要一個定義良好的策略來應對我們代碼中的各種錯誤。不論是由人來選擇怎麼處理問題,還是由代碼來決定——一定要由某人或者代碼來負責確認錯誤和對錯誤作出反應。
  • 錯誤由下層組件提出並向上傳播,以便讓調用方來處理。

    錯誤以什麼方式提出,稱為錯誤報表機制,可以分為以下幾種:

  • 不報告。這是最簡單的情況。絕對不要忽視任何一種情況,如果你不知道如何處理這個問題,就向調用代碼發送一個故障訊號,不要對錯誤心存僥倖。
  • 傳回值。從函數返回一個表示成功或者失敗的值,一個更進階的方法是列舉出所有可能的退出狀態,並返回一個相應的原因代碼,一個值表示成功,其餘的值分別代表許多不同的異常終止資訊。
  • 錯誤狀態變數。這種方法試圖解決函數的傳回值和它的錯誤狀態報表之間的矛盾。函數將設定一個共用的全域錯誤變數,而不是返回一個原因代碼。但是這種方法在多線程時會很麻煩。從功能上講,這種技術與使用傳回值是等價的,但是它的缺陷之多足夠讓你放棄使用。
  • 異常。異常是一種管理錯誤的語言工具;不是所有的語言都支援異常。異常是不能被忽略的,如果沒有被捕獲和處理,異常就會傳播到呼叫堆疊的最高層,這通常會導致程式崩潰,這使得異常相對於手工編寫的錯誤處理代碼來說更加整潔和安全。處理一個異常的代碼與引發該異常的代碼截然不同,而且可以差的很遠;異常並非沒有開銷,語言對異常的支援會造成效能上的損失。
  • 訊號。它是一種更加極端的報告機制,主要用於由執行環境向運行程式報告錯誤,訊號是硬體中斷的軟體等價物。
  • 有恢複能力的代碼一定是針對異常安全的,不論出現什麼異常,它都必須正確的運行。
  • 異常中立的代碼將所有的異常都傳播到調用方,它不會隱藏或者改變任何東西。
  • 異常安全分為以下3個等級:1. 基本保證,如果異常在一個函數中發生,它將不會泄露資源,代碼的狀態將保持連貫,但是它不一定會保持一種已知的狀態;2. 強力保證,如果通過你的代碼傳播了一個異常,程式的狀態將保持完全不變;3. 不拋出保證,操作永遠不能拋出異常,如果我們是異常中立的,那麼就意味著函數不能執行任何可能會拋出異常的操作。

    根據不同的錯誤報表機制,我們有不同的檢測錯誤的方式:

  • 傳回值。
  • 錯誤狀態變數。
  • 異常。只有在知道可能會拋出異常的情況下,你才能作出明智的選擇,而只有這已被文檔化的情況下,你才能夠知曉。
  • 訊號。需要為其安裝一個處理常式。

    在對一個錯誤進行處理前,我們需要瞭解錯誤相關的一些關鍵資訊:

  • 錯誤來自何處。
  • 當時的上下文環境。
  • 為什麼會出錯。
  • 錯誤是何時發生的。
  • 錯誤的嚴重性。
  • 如何修正錯誤。
  • 我們在何時處理錯誤,可以分成兩派:1. 儘可能早的處理,因為錯誤是在其來源附近處理的,所以你可以留住重要的上下文資訊,從而使得你的代碼更加清晰,對於返回錯誤碼的函數來說通常是最佳的選擇;2. 儘可能延遲處理,因為檢測到錯誤的代碼很少知道應該怎樣進行處理,如何處理通常取決於錯誤出現的環境,即調用環境,異常對於這種處理方式很適合。
  • 我們在修正錯誤時可能會用到的技巧:1. 日誌,日誌的作用是記錄程式的生命週期中值得注意的事件,以使你可以深入研究程式內部工作方式和執行的重構路徑;2. 報告,程式應該只在已沒有什麼可作的情況下才向使用者報告錯誤;3. 傳播,如果你的代碼遇到了一個錯誤並且不知道該怎麼辦,那麼就把錯誤向上傳,很可能你的調用方有能力解決這個問題;4. 忽略,如果採取這種方法,必須在代碼中明顯的標記出來。

    如果你要提示使用者來解決問題,那麼首先應該在頭腦中有一些總體的思路:

  • 使用者並不像程式員那麼思考,所以以他們所期望的方式來呈現資訊。
  • 確保你的資訊不顯得高深莫測。
  • 不要呈現毫無意義的錯誤碼。
  • 將後果嚴重的錯誤與僅僅是警告區分開。
  • 只在使用者完全理解每種選擇的後果時在提出問題,如果需要的話,對問題進行一些解釋,使每種選擇的後果都非常清晰。

    每個函數中都應該執行的一些錯誤檢查:

  • 檢查所有的函數參數。
  • 檢查執行過程中關鍵點處的不變條件是否滿足。
  • 在使用任何來自外部的值之前都要檢查其有效性。
  • 檢查所有系統調用和其他下級函數調用的返回狀態。
  • 在編寫可能會失敗的代碼的同時,編寫所有的錯誤偵測和處理,不要拖延到以後做,如果你很不幸必須延遲處理,至少現在就編寫錯誤偵測部分。
  • 既考慮錯誤的引發又考慮錯誤的處理的一般原則是無論故障在什麼情況下出現,對於故障的處理都有一個一致的策略。
  • 你所編寫的每行代碼都必須在恰當和徹底的錯誤檢查與處理上取得平衡。
  • 我們應該如何處理在錯誤處理代碼中發生的錯誤?應該像對待其他任何錯誤一樣,處理那些在錯誤處理程式中發生的錯誤,你會得到一個多層嵌套的錯誤處理程式
  • 優秀的程式員:1. 將好的意圖與好的編碼習慣結合在一起;2. 在編寫主要代碼的同時編寫錯誤處理代碼;3. 在他們編寫的代碼中全面覆蓋了所有的錯誤可能性。
  • 糟糕的程式員:1. 編寫代碼時很隨便,既不思考也不檢查他們在做什麼;2. 忽略在編寫代碼時出現的錯誤;3. 最終不得不進行漫長的調試過程以找到程式崩潰的原因,因為他們從不預先考慮錯誤情況。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.