C++ 程序员要像医生一样调试代码?
作為 C++ 程序員,你對(duì)調(diào)試代碼是一種什么態(tài)度?英文原文:Debug like a doctor
“現(xiàn)在的編程工作就像是對(duì)你需要解決處理的部分做科學(xué)研究。”
——Gerald Sussman
設(shè)計(jì)和維護(hù)好的軟件就像是一個(gè)抵制復(fù)雜度的永無(wú)止境的奮斗過(guò)程。任何足夠大小的應(yīng)用程序的代碼路徑和組件都能迅速成長(zhǎng)成令人眼花繚亂的組合爆炸。
一點(diǎn)都不簡(jiǎn)單。
當(dāng)部署類似于 Heroku 和 AWS 的平臺(tái)時(shí),單服務(wù)器的 Web 應(yīng)用程序成為了分布式系統(tǒng)。現(xiàn)代瀏覽器模糊了客戶端和服務(wù)器之間的界線。當(dāng)簡(jiǎn)單程序在多個(gè) CPU 內(nèi)核上運(yùn)行時(shí),它們就會(huì)成為復(fù)雜的協(xié)調(diào)問(wèn)題。雖然像測(cè)試驅(qū)動(dòng)開(kāi)發(fā)等實(shí)踐和 SOLID 原則等指導(dǎo),可以幫助我們模擬問(wèn)題,簡(jiǎn)化解決方案,但大多數(shù)軟件應(yīng)用程序都是一些復(fù)雜的系統(tǒng),每個(gè)組件也會(huì)以意想不到的方式進(jìn)行交互和組合。
當(dāng)軟件系統(tǒng)中發(fā)生意外情況時(shí),會(huì)造成很嚴(yán)重的后果。幸運(yùn)的是,軟件開(kāi)發(fā)人員可以借鑒另一門更古老的學(xué)科,來(lái)應(yīng)對(duì)對(duì)于復(fù)雜系統(tǒng)的關(guān)注、維護(hù)和調(diào)試,這門學(xué)科就是:醫(yī)學(xué)。
鑒別診斷是醫(yī)生用來(lái)匹配系列癥狀及其可能病因的系統(tǒng)化方法。一個(gè)好的鑒別診斷包括以下 4 個(gè)步驟:
雖然上面這 4 個(gè)步驟是為醫(yī)生而整理的,但是我們同樣可以像一個(gè)醫(yī)生一樣思考,用一種強(qiáng)有力的方式來(lái)找到并消除軟件缺陷。將診斷過(guò)程分解為一個(gè)一個(gè)目的單一的步驟,確保每個(gè)步驟都能得到應(yīng)有的重視。按照優(yōu)先順序是為了保證專注檢查的重點(diǎn),并作出務(wù)實(shí)的干預(yù)措施。然后進(jìn)行測(cè)試,排除假設(shè),以確保調(diào)試的嚴(yán)謹(jǐn)。
白板是個(gè)好東西
當(dāng)錯(cuò)誤發(fā)生時(shí),我們大多會(huì)想也不想地立馬去調(diào)查最可能的原因。懂得向后跟蹤和少許背景知識(shí),人性就會(huì)趨向于投機(jī)主義。但是好的診斷始于列出的癥狀,而不是病因。寫(xiě)下可以觀察出來(lái)的所有癥狀,無(wú)論是異常處理,還是錯(cuò)誤代碼,哪怕只是異常的行為,都可以。可以使用文本編輯器或者白板,但是,你最好能對(duì)診斷過(guò)程中的每一個(gè)步驟做筆記,這很重要。從假設(shè)出發(fā)分開(kāi)觀察,有助于確保你不會(huì)排除或忽視潛在原因。并且多數(shù)時(shí)候,列出更多的癥狀反而會(huì)縮小可能范圍,避免你將時(shí)間浪費(fèi)在測(cè)試不正確的假設(shè)上。
寫(xiě)好了一系列癥狀,那么接下來(lái)就可以開(kāi)始考慮原因了。
斑馬和馬
“當(dāng)你聽(tīng)到馬蹄聲的時(shí)候,找的應(yīng)該是馬,而不是斑馬。”
在應(yīng)用程序中出現(xiàn)代碼 bug 的可能性比在 Web 框架中出現(xiàn) bug 的可能性要大,而在 Web 框架中發(fā)現(xiàn) bug 又比在操作系統(tǒng)中發(fā)現(xiàn) bug 更容易。當(dāng)然讓別人來(lái)審查代碼是個(gè)好主意,但事實(shí)是,大多數(shù) bug 審查起來(lái)特別無(wú)聊。所以在開(kāi)始考慮進(jìn)階到更復(fù)雜的問(wèn)題之前,先給出最簡(jiǎn)單的解釋。
話又說(shuō)回來(lái),正如同一個(gè)癥狀卻又可能是完全不同的病因引發(fā)的,所以我們應(yīng)該將所有能想到的相關(guān)病因都寫(xiě)下來(lái)。就像原先我們對(duì)癥狀直接描述為“what”,后來(lái)用“how”區(qū)分開(kāi)來(lái),頭腦風(fēng)暴解釋法的目的是用“how likely”來(lái)區(qū)分“how”。捕捉任何看似合理的要點(diǎn),以便于節(jié)約分析。
重中之重,不能有害
鑒別診斷與其他的演繹方法不同,因?yàn)獒t(yī)生必須不斷地評(píng)估風(fēng)險(xiǎn),并權(quán)衡對(duì)病人生命的影響。當(dāng)然如果我們的產(chǎn)品中存在著 bug,雖然不會(huì)像醫(yī)生那樣負(fù)有生命責(zé)任那般嚴(yán)重,但是停頓修復(fù)會(huì)產(chǎn)生既現(xiàn)實(shí)又痛苦的成本費(fèi)用。就像威脅生命的疾病事件一樣需要立即進(jìn)行干預(yù),嚴(yán)重的 bug 可能需要粗暴的簡(jiǎn)單修復(fù),例如回滾和重新啟動(dòng)。將假設(shè)按優(yōu)先順序排列,然后再考慮權(quán)衡,并判斷決定是否啟動(dòng)測(cè)試假設(shè)或立即進(jìn)行干預(yù)。
準(zhǔn)備圖表
正如患者會(huì)有醫(yī)院病歷和其他背景信息的圖表,你的軟件系統(tǒng)可能也需要具備圖表。從日志和錯(cuò)誤報(bào)告系統(tǒng)收集信息,來(lái)說(shuō)明你的分析。至于系統(tǒng)指標(biāo)和跟蹤誤差,你不妨將它們當(dāng)作是明智的預(yù)防性藥品。
如果你的病人尚未處于嚴(yán)重危險(xiǎn)之中,那么可以先進(jìn)行假設(shè)-演繹。從你定義的優(yōu)先級(jí)最高的假設(shè)開(kāi)始,一個(gè)一個(gè)地證明它們是錯(cuò)誤的。雖然支持性證據(jù)有時(shí)候或許能有助于你找到 bug 的所在,但是失敗的測(cè)試驅(qū)動(dòng)了演繹過(guò)程。這乍一看上去似乎有悖直覺(jué),但是測(cè)試-消除假設(shè)策略是追溯 bug 到它的起因的最快方式。在許多情況下,一些簡(jiǎn)單的測(cè)試就可以一次消除幾個(gè)假設(shè)。當(dāng)然,也有時(shí)候,為了否決假設(shè)你就得執(zhí)行更多的測(cè)試。
實(shí)驗(yàn)室工作
不同于醫(yī)療世界的令人難以接受,只要你愿意,你隨時(shí)都可以克隆軟件應(yīng)用程序,執(zhí)行可怕的人體實(shí)驗(yàn)。如果你有足夠的信息來(lái)觸發(fā)你要診斷的 bug,那么可以將它復(fù)制到受控環(huán)境中,例如一個(gè)有著最新數(shù)據(jù)庫(kù)備份的臨時(shí)服務(wù)器。當(dāng)你消滅原因,收集到新的數(shù)據(jù),并完善假設(shè)之后,你的 bug 的真正原因線索將變得更加清晰。
清楚地思考復(fù)雜系統(tǒng)需要的關(guān)心和專注。采用結(jié)構(gòu)化的診斷過(guò)程來(lái)指導(dǎo)檢查可以節(jié)省時(shí)間和避免挫折感。最重要的是,它很有用。下次你再陷入 bug 之中時(shí),那么不妨試試拋開(kāi)鍵盤,將步驟一步一步寫(xiě)到白板上,像一個(gè)醫(yī)生診病一樣進(jìn)行調(diào)試。
來(lái)源:U8K8.com
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的C++ 程序员要像医生一样调试代码?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 我感到很惭愧的飞鸽传书
- 下一篇: [转]50个c/c++源代码网站