(Don't Ignore that Error!)
老規矩,先分享書裡這個章節的大意,再寫「命題作文」 不處理程序的錯誤會導致脆弱的、不安全的甚至無法維護的代碼。 https://97-things-every-x-should-know.gitbooks.io/97-things-every-programmer-should-know/content/en/thing_26/個人簡評:它講了一個非常普通的道理——小錯不改會鑄成大錯。然而,我覺得作者有些混淆了代碼錯誤和技術債務:錯誤就是錯誤,而債務並不一定是錯誤。不要忽略代碼執行的錯誤
一般來說,代碼執行的錯誤是無法避免的,因為代碼的執行無法脫離外部依賴。再簡單的代碼至少還依賴著本地的I/O,更不用說現在的網際網路服務背後的系統架構了——每一個核心模塊都有著大量的外部依賴。 然而,即使代碼執行出錯如分布式架構中單機故障那般平常,我們還是需要正視和處理這個問題。嚴格來說,我們是無法忽略程序的錯誤的。哪怕我們寫出如下鴕鳥策略的代碼,這個錯誤始終會轉變成另一個錯誤的形式表現出來,而且很可能是一種我們難以捉摸的形式出現。 注意,忽略程序錯誤和積累技術債務並不是一回事。前者是試圖去掩蓋問題,掩耳盜鈴之舉;而後者更多是對現有局限的妥協,卻不意味著不處理已知的錯誤,只是無法系統性或者完備地解決問題。債務的問題在於積累多了還的代價太大,而不是它現在就造成問題;而錯誤已經造成問題了,個人掩蓋只是蒙蔽一部分人而言。處理代碼執行錯誤需要根據業務需求而定:要不消除它對正常業務邏輯的影響,要不將它當作業務錯誤進行處理。比如,外部服務調用出錯,如果業務需求不苛刻,我們能使用簡單的重試(re-try)方式提高業務可用性;如果業務邏輯本身是錯誤的,即有bug,修復就可以了;如果錯誤無法修正,那麼將其作為一種業務錯誤場景進行處理。有的時候我們希望能在業務整體上考慮業務錯誤場景的處理,然而在現實的工程研發中我們往往很難也沒必要做到這一點。作為研發的個體或具體小團隊,我們負責的研發工作往往只是系統架構的一部分,而不是整體。這是符合複雜系統或應用的高內聚低耦合設計的。在架構設計的時候,每個模塊的職責範圍本該明確,包括對功能錯誤的定義。如果每次考慮錯誤都需要對從整體架構進行優化,這是一種比較低效的做法。對於具體功能模塊內的錯誤,我們要不試著在保證模塊功能需求的情況下提高模塊的健壯性,要不將模塊錯誤向上層調用匯報。而將錯誤隱藏起來,向上層匯報業務正常,這對於最終用戶而言這依然會是一個業務錯誤;而對於調試業務錯誤的人來說這是一個噩夢,因為無法直接發現錯誤信息去定位原因。隱藏服務的初始化錯誤是一個常見的反例。在大多時候服務的初始化錯誤意味著服務無法正常工作。與其讓壞掉的服務繼續啟動,不如直接讓服務啟動失敗。前者往往會產生許多意想不到的奇怪錯誤,白白耽誤錯誤定位的工夫,後者則能夠讓錯誤在第一時間暴露。如果是代碼改動導致的初始化錯誤,這往往危害不是很大,只要代碼籤入前有基本的模塊功能的自動化驗證過程;這只是讓發現問題難一些些。然而,有的服務初始化錯誤只會在產品環境出現,比如產品環境的資源配置出問題了,隱藏服務的初始化錯誤的後果往往是嚴重的。分布式服務的初始化錯誤,如果單機因為本地資源問題無法初始化成功,一般會觸發架構級別的容錯機制確保用戶請求不再分發到故障的單機。然而,如果服務初始化錯誤後服務依舊正常啟動,它可能還是接受用戶請求卻無法正常服務,成為一個不易發現的壞點。如果是多輪的會話業務場景,而且負載均衡建立在簡單的無狀態輪詢策略上,少數的壞點便足以讓整個會話業務達到不可用的嚴重程度。關於業務錯誤和異常錯誤的處理,之前的文章《理解業務錯誤才能做好異常處理》做過一些介紹。感興趣的可以看看那篇文章,在此便不複述了。
來個「分享、點讚、在看」吧👇
想了解叻道?請看此處!
感謝你的關注!