修復每個 bug 後都要問這 3 個問題

2021-08-10 20:35:41 字數 3272 閱讀 2818

你是否曾經修復了乙個 bug ,隨後又發現了乙個跟剛修復 bug 有關的 bug ,又或是修復 bug 的方式引起了另乙個 bug ?當我修改 bug 時,我會問自己三個問題,以確保我已經仔細考慮了它的意義。每次你認為發現並修改了乙個 bug 時,可以使用這些問題來提高生產力和**質量。

這些問題背後的主要思想就是:每乙個 bug 都是底層程序的乙個不良表現。你必須處理這些症狀,但如果你僅僅是處理這些外在症狀,你就會有永遠解決不完的問題。你應該找到產生 bug 的程序,並且修復這個程序。當你確定究竟發生了什麼和發生這些的原因時,也許你就會明白產生 bug 的基礎程序不是隨機的,而是可控的。

在問這三個問題前,你需要克服面對 bug 的這種天生的抗拒,仔細分析 bug 。檢視**並解發布錯的原因,從能觀察到的現象開始,向後分析,不斷地問為什麼,直到你可以找到產生 bug 的模式。通常,你該跟同事一起做這件事, 因為解釋你認為會發生的事情,將迫使你面對一些假設——這些程式是做什麼的。

「它溢位了,因為下標j越界了。」

「為什麼?」

「j 是 10,但陣列最大下標為 9。」

「為什麼?」

「j 是乙個字串長度,陣列的起始下標是 0,所以字串長度為 1 的最後乙個字元的索引是 0。」

找到 bug 後,查詢其他意外情況。檢查程式出錯時主要的程式變數的值,是否可以解釋這些值。

「為什麼 name 是 null?」

「為什麼它總是輸出錯誤資訊呢?」

記錄下你做了哪些操作,發生了哪些變化。你需要知道究竟發生了什麼,這樣做就意味著你時刻有一把標尺和歷史記錄。

當完成這些步驟後,你可以準備問第乙個問題了。

檢視**中使用相同模式的地方,系統地改變模式找出類似的 bug 。

「我還在其他什麼地方使用長度作為下標的嗎?」

「所有陣列的起始下標都一樣嗎?」

「對於乙個長度為 0 的字串會發生什麼?」

試著描述這部分**中應該是正確的,但是這些 bug 沒有遵循的規則。尋找這個不變數 [ 1 ]的過程將幫助你找到其他潛在的 bug 。

「起始偏移加上長度減去1就是結束的下標,除非陣列長度為 0」。
對於你發現的每乙個 bug ,你都可以解決一批 bug ,這是非常高效的。嘗試用概括性的語言描述這些 bug 也能提公升你對程式的理解程度,並幫助您避免在程式中引入更多的 bug 。

一旦你確定了如何修復這個 bug ,你就需要考慮一下修復後會發生什麼。這個執行失敗的語句後面的語句也可能有問題,但是程式還沒有執行到此就不知道有沒有 bug ,或者有些**因為你修復 bug 而第一次出現在程式中,這些**也可能有問題。檢視這些未執行的語句,檢查**中的 bug 。

「下一條語句會正常執行嗎?」
當你在想程式的控制流的時候,可以弄清楚還有哪些地方程式沒有執行到。

「是否有我從來沒有測試過的功能組合?」
在程式中插樁(instrumentation)並不會耗費太多時間,在執行程式各個部分的過程中就可以進行檢查,但是你會驚訝地發現開發者測試過的**還有很多都不能正常執行。

「我可以測試出所有的錯誤資訊嗎?」
注意乙個地方的改動可能會引起其他地方的 bug 。一些變數的區域性改動可能會在執行時違反後來的假設。

「如果僅是從 j 中減去 1,當長度為 0 時,後面的語句會運算元組中 -1 位置的元素。」
如果程式已經做了大量改動,就要仔細考慮是否有必要增加另外乙個補丁,或者是時候考慮重新設計和重新實現了。

(有時候調 bug 就是這樣的)

問問自己如何改變程式設計方法,根據定義避免 bug 的出現,通過改變方法或者工具,經常可以移除整個類的錯誤而不用乙個乙個的解決 bug 。

從「 bug 是何時引入的」這個問題開始:在程式開發生命週期的哪乙個階段可以阻止 bug 的產生?

「設計是沒問題的;我在程式設計時引入了 bug 。」
仔細檢查 bug 產生的原因,考慮 bug 產生時正在執行的程序,並想想怎麼改變它來阻止 bug 的產生。

「將偏移的資料型別和長度分離出來將會在編譯時捕獲這個錯誤。」

「每乙個文字項可以用隱藏了下標計算的巨集輸出,然後我就可以一次找到它。」

不要滿足於膚淺的答案。假如你對於乙個 bug 的解釋是,「我記不清了」,那還怎麼改進這個過程,讓你不再需要記住它?你可以更改程式語言,使被忽略的細節可以完全隱藏,否則你遺漏的部分會被檢測到從而導致編譯問題。對這個問題域,你可能使用了預處理器或者智慧型的編輯器,有預設值,錯誤檢查,智慧型提示和快速文件。這個 bug 可能是程式設計團隊溝通的問題,亦或是需要討論的設計衝突。

思考發現 bug 的方式,並問問自己如何能更早發現它。測試怎麼可以更嚴密一些?能否進行自動化測試?是否要新增**實時檢測功能,以便可以及時捕獲錯誤資訊?

「我應該在我的測試單元中嘗試長度為 0 的陣列」。

「我應該進行下標檢查,提前捕獲不符合的下標」。

有必要建立一些系統方法和自動化工具,用於編譯、構建和測試,它們可以減少長時間的除錯和查明具體事實的過程。

這個技巧的應用

養成這樣一種習慣:每當你發現乙個 bug 時,問自己這三個問題,甚至你不必等到有 bug 時才使用這三個問題。

設計評審和**審查[2]是找出 bug 的強有力手段,你可以對審查過程出現的每乙個缺陷都提出三個問題。如果審查徹底,前兩個問題不會出現太多新的 bug ,但第三個問題可以幫助你找到方法,用來避免未來可能會出現的 bug 。

參考 [1] hoare, c. a. r, proof of a program: find, comm. acm 14, 39-45, jan 1971.

[2] fagan, m. e., design and code inspections to reduce errors in program development, ibm systems journal 15(3), 1976.

[3] saltzer, j. h., repaired security holes in multics, mit csr-rfc-5, feb 27 1973.

程式設計師修復每個 bug 後都要問這 3 個問題

程式設計師修復每個 bug 後都要問這 3 個問題 你是否曾經修復了乙個 bug 隨後又發現了乙個跟剛修復 bug 有關的 bug 又或是修復 bug 的方式引起了另乙個 bug 當我修改 bug 時,我會問自己三個問題,以確保我已經仔細考慮了它的意義。每次你認為發現並修改了乙個 bug 時,可以使...

bug修復記錄

telnet ping netaddr traceroute netaddr 這是乙個linux下的命令可以通過vmmap觀察程式執行時所需要的依賴庫協議裡面涉及到陣列的,一定要判斷最大值 basegamelibdata stlibbasedata gamelib基本資料 uint32 t dwui...

修復bug及修復過程

cc.sys.localstorage.setitem scoredisplay this.score.tostring 遊戲gameover之後,不能載入出來得分情況場景 gameing場景 gameover場景 有bug 是黑屏,ie瀏覽器給的問題反饋是 gainscore function p...