|
(給伯樂在線加星標(biāo),看經(jīng)典文章)
你是否曾經(jīng)修復(fù)了一個(gè) bug ,隨后又發(fā)現(xiàn)了一個(gè)跟剛修復(fù) bug 有關(guān)的 bug ,又或是修復(fù) bug 的方式引起了另一個(gè) bug ?當(dāng)我修改 bug 時(shí),我會(huì)問自己三個(gè)問題,以確保我已經(jīng)仔細(xì)考慮了它的意義。每次你認(rèn)為發(fā)現(xiàn)并修改了一個(gè) bug 時(shí),可以使用這些問題來提高生產(chǎn)力和代碼質(zhì)量。 這些問題背后的主要思想就是:每一個(gè) bug 都是底層進(jìn)程的一個(gè)不良表現(xiàn)。你必須處理這些癥狀,但如果你僅僅是處理這些外在癥狀,你就會(huì)有永遠(yuǎn)解決不完的問題。你應(yīng)該找到產(chǎn)生 bug 的進(jìn)程,并且修復(fù)這個(gè)進(jìn)程。當(dāng)你確定究竟發(fā)生了什么和發(fā)生這些的原因時(shí),也許你就會(huì)明白產(chǎn)生 bug 的基礎(chǔ)進(jìn)程不是隨機(jī)的,而是可控的。 在問這三個(gè)問題前,你需要克服面對 bug 的這種天生的抗拒,仔細(xì)分析 bug 。查看代碼并解釋出錯(cuò)的原因,從能觀察到的現(xiàn)象開始,向后分析,不斷地問為什么,直到你可以找到產(chǎn)生 bug 的模式。通常,你該跟同事一起做這件事, 因?yàn)榻忉屇阏J(rèn)為會(huì)發(fā)生的事情,將迫使你面對一些假設(shè)——這些程序是做什么的。
找到 bug 后,查找其他意外情況。檢查程序出錯(cuò)時(shí)主要的程序變量的值,是否可以解釋這些值。
記錄下你做了哪些操作,發(fā)生了哪些變化。你需要知道究竟發(fā)生了什么,這樣做就意味著你時(shí)刻有一把標(biāo)尺和歷史記錄。 當(dāng)完成這些步驟后,你可以準(zhǔn)備問第一個(gè)問題了。 1. 其他地方也會(huì)出現(xiàn)這個(gè)錯(cuò)誤嗎?查看代碼中使用相同模式的地方,系統(tǒng)地改變模式找出類似的 bug 。
試著描述這部分代碼中應(yīng)該是正確的,但是這些 bug 沒有遵循的規(guī)則。尋找這個(gè)不變量 [ 1 ]的過程將幫助你找到其他潛在的 bug 。
對于你發(fā)現(xiàn)的每一個(gè) bug ,你都可以解決一批 bug ,這是非常高效的。嘗試用概括性的語言描述這些 bug 也能提升你對程序的理解程度,并幫助您避免在程序中引入更多的 bug 。 2. 這個(gè) bug 后面隱藏著什么其它的 bug ?一旦你確定了如何修復(fù)這個(gè) bug ,你就需要考慮一下修復(fù)后會(huì)發(fā)生什么。這個(gè)執(zhí)行失敗的語句后面的語句也可能有問題,但是程序還沒有執(zhí)行到此就不知道有沒有 bug ,或者有些代碼因?yàn)槟阈迯?fù) bug 而第一次出現(xiàn)在程序中,這些代碼也可能有問題。查看這些未執(zhí)行的語句,檢查代碼中的 bug 。
當(dāng)你在想程序的控制流的時(shí)候,可以弄清楚還有哪些地方程序沒有執(zhí)行到。
在程序中插樁(instrumentation)并不會(huì)耗費(fèi)太多時(shí)間,在運(yùn)行程序各個(gè)部分的過程中就可以進(jìn)行檢查,但是你會(huì)驚訝地發(fā)現(xiàn)開發(fā)者測試過的代碼還有很多都不能正常運(yùn)行。
注意一個(gè)地方的改動(dòng)可能會(huì)引起其他地方的 bug 。一些變量的局部改動(dòng)可能會(huì)在執(zhí)行時(shí)違反后來的假設(shè)。
如果程序已經(jīng)做了大量改動(dòng),就要仔細(xì)考慮是否有必要增加另外一個(gè)補(bǔ)丁,或者是時(shí)候考慮重新設(shè)計(jì)和重新實(shí)現(xiàn)了。 (有時(shí)候調(diào) Bug 就是這樣的) 3.我應(yīng)該做些什么防止類似 bug 的產(chǎn)生呢?問問自己如何改變編程方法,根據(jù)定義避免 bug 的出現(xiàn),通過改變方法或者工具,經(jīng)??梢砸瞥麄€(gè)類的錯(cuò)誤而不用一個(gè)一個(gè)的解決 bug 。 從“ bug 是何時(shí)引入的”這個(gè)問題開始:在程序開發(fā)生命周期的哪一個(gè)階段可以阻止 bug 的產(chǎn)生?
仔細(xì)檢查 bug 產(chǎn)生的原因,考慮 bug 產(chǎn)生時(shí)正在運(yùn)行的進(jìn)程,并想想怎么改變它來阻止 bug 的產(chǎn)生。
不要滿足于膚淺的答案。假如你對于一個(gè) bug 的解釋是,“我記不清了”,那還怎么改進(jìn)這個(gè)過程,讓你不再需要記住它?你可以更改編程語言,使被忽略的細(xì)節(jié)可以完全隱藏,否則你遺漏的部分會(huì)被檢測到從而導(dǎo)致編譯問題。對這個(gè)問題域,你可能使用了預(yù)處理器或者智能的編輯器,有默認(rèn)值,錯(cuò)誤檢查,智能提示和快速文檔。這個(gè) bug 可能是編程團(tuán)隊(duì)溝通的問題,亦或是需要討論的設(shè)計(jì)沖突。 思考發(fā)現(xiàn) bug 的方式,并問問自己如何能更早發(fā)現(xiàn)它。測試怎么可以更嚴(yán)密一些?能否進(jìn)行自動(dòng)化測試?是否要添加代碼實(shí)時(shí)檢測功能,以便可以及時(shí)捕獲錯(cuò)誤信息?
有必要?jiǎng)?chuàng)建一些系統(tǒng)方法和自動(dòng)化工具,用于編譯、構(gòu)建和測試,它們可以減少長時(shí)間的調(diào)試和查明具體事實(shí)的過程。 這個(gè)技巧的應(yīng)用養(yǎng)成這樣一種習(xí)慣:每當(dāng)你發(fā)現(xiàn)一個(gè) bug 時(shí),問自己這三個(gè)問題,甚至你不必等到有 bug 時(shí)才使用這三個(gè)問題。 在設(shè)計(jì)和審查過程中,你都可以用這三個(gè)問題來處理你得到的每一條意見。審閱意見是潛在的溝通過程的結(jié)果,使你可以有所改進(jìn)。如果你認(rèn)為讀者評論是錯(cuò)誤的,比如,你可能會(huì)問是什么使你的文章沒被理解,如何更好地與審稿人溝通。 設(shè)計(jì)評審和代碼審查[2]是找出 bug 的強(qiáng)有力手段,你可以對審查過程出現(xiàn)的每一個(gè)缺陷都提出三個(gè)問題。如果審查徹底,前兩個(gè)問題不會(huì)出現(xiàn)太多新的 bug ,但第三個(gè)問題可以幫助你找到方法,用來避免未來可能會(huì)出現(xiàn)的 bug 。 致謝:感謝那些教給我這些經(jīng)驗(yàn),豐富了我生活和工作的朋友和同事。感謝Jay O’Dell、Rick Berman 和 Tom DeMarco 對本文早期版本的寶貴的批評和建議。 參考 [1] Hoare, C. A. R, Proof of a Program: FIND, Comm. ACM 14, 39-45, Jan 1971. |
|
|