1. 程式人生 > 其它 >6年開源經驗總結出的bug修復技巧,好用

6年開源經驗總結出的bug修復技巧,好用

  前言

  bug, 又名程式缺陷或者程式漏洞, 是每個程式設計師每天都回避不了的東西。

  程式設計師對bug的感情可謂是五味雜陳:一方面bug非常可惡,尤其是一些偶現的bug,它強大到可以摧毀一個優秀程式設計師的意志;另一方面很多bug又是程式設計師自己親手寫下的,無奈之餘只能自嘲一句:不寫bug我們就要失業了!

  作為一名職業程式設計師,同時也是一名開源創作者, 誇張點說,我解過的bug可以繞地球一圈, 每天寫bug解bug幾乎是我的日常。

  但是,作為一個善於思考和總結的技術up主,我怎麼能止步於每天寫bug和解bug呢?更何況,人生在世,總得有點追求。既然我不能夠阻止bug的產生,那麼就讓我總結一點bug的修復技巧,讓bug消失地更快點吧!

  一、bug修復的生命週期

  中醫講究"望聞問切",其實修復一個bug就像給病人看一場病,本質上是相通的。

  當我們遇到一個bug(問題)的時候,一般我們需要經歷如下6個步驟:

  瞭解bug。我們首先需要到底出了什麼bug,現象是什麼,怎樣發生的;復現bug。在瞭解了bug的大致情況之後,我們需要能夠找到復現的路徑,這就為後面bug的定位提供可靠的依據;定位bug。當有了穩定的復現途徑之後,要做的就是打斷點、打日誌進行除錯,來一步一步分析和定位bug,到底是那塊程式碼導致的錯誤;確認bug。當我們定位到bug出錯的地方之後,我們就需要分析這到底是不是bug。如果是bug,那麼這個bug出現的根源是什麼,到底能不能解決;修復bug。在明確了bug的根本原因之後,下面就需要發揮我們的聰明才智去修復這個bug了;驗證bug。並不是每次我們修復完bug之後就可以萬事大吉了,此時我們還需要去重現bug以確保bug被真正修復。除此之外,有條件的我們還需要去驗證相關場景,以保證修復該bug不會引入其他bug。

  以上可以總結為12字方針--"瞭解、復現、定位、確認、修復、驗證"bug。一般在稍微大一點的公司,都會有對應的流程對bug的修復進行流程控制,最終形成閉環。

  可以看到的是,其實修復bug只是解決一個bug的6個步驟中的其中一步。很多剛剛參與工作的程式設計師經常犯的錯誤就是一遇到bug,就開始漫無目的地看程式碼或者是上網各種瞎搜尋,又或者各種無腦問,最後搞了一圈可能連自己要解決的bug到底是什麼都不知道,這樣解決bug的效率可想而知。

  可能讀到這的你此刻非常想問:怎樣才可以更快地修復一個bug呢?那麼下面我就根據上面講的六個步驟來分別講解一下對應的技巧。

  二、解決bug的藝術

  在我看來,修復一個bug是相對容易的。因為修復一個bug的方法可能有很多種,但是如何從根本上解決一個bug,並保證這個bug下次不再復現的話,其實是非常難的,這就需要我們學習一下解決bug的藝術。

  1.瞭解bug

  俗話說,知己知彼百戰不殆。bug修復的第一步當然是先了解bug了。

  瞭解bug是解決bug最重要的一步,它直接決定了後面五步執行的效率和質量。糟糕的錯誤報告和不負責任的問題描述都是埋葬程式設計師修復bug意志的罪魁禍首。

  在瞭解bug之前,我們需要收集足夠的資訊,瞭解它產生的現象、描述、復現步驟、以及解決後的預期是什麼等等。那麼我們應該怎麼做才能更加全面地瞭解它呢?

  下面我給幾點建議供大家參考:

  1)觀察現象

  光憑文字說明是無法準確領悟到bug的精髓的。因為每個人思考問題的角度以及文字表達描述都是千差萬別的。

  如果說這個時候能提供一段出錯的視訊或者問題截圖,又或者能夠現場演示錯誤的話,這樣觀察現象,然後再結合問題描述之後,一定能夠幫助你快速地瞭解這個bug。

  2 ) 詢問相關人員

  這裡你詢問的可以不僅限於發現bug的人(一般是測試人員),當然你首先應當詢問的還是這個發現bug的人。

  這裡你需要著重詢問bug報告上你覺得迷惑的點,比如出現bug的應用版本、裝置型號、bug出現的頻率、bug產生的步驟和恢復的途徑、bug修復的預期效果等。這裡你需要進行刨根問底地詢問,因為可能bug發現人覺得一些無關緊要的細節,對你來說卻是至關重要的點。

  問完發現bug的人之後,我們還可以向bug對應模組的負責人(測試、開發、產品)詢問該模組的業務邏輯,說不定能夠獲取到有價值的資訊哦。

  3 ) 提供bug報告模板

  一份優秀的bug報告模板,可以讓程式設計師直接跳過bug修復的前三步,直接進入到確認bug步驟,從而能夠極大地提高bug修復的效率。那麼一份優秀的bug報告模板應當具備哪些內容呢:

  bug的標題和問題描述;出現bug的應用版本;出現bug的裝置資訊(型號、版本等);bug產生相關的視訊、截圖和錯誤日誌;bug復現的步驟;bug出現的必要條件(環境)和恢復途徑;bug修復後的預期效果;bug對應的模組或者關聯bug。

  有了以上的內容之後,相信程式設計師能夠很快地瞭解這個bug,定位出bug產生的原因並予以解決。

  2. 復現bug

  如果你在第一步瞭解bug中獲得了良好的bug報告的話,則此部分可以很容易。你只需要按照bug報告中的bug復現步驟,按順序操作即可穩定復現bug。

  當然,很多時候往往並不是一帆風順的,即使你手握bug報告,做了非常詳細的調查工作,然而bug就是無法復現,那麼這個時候我們應該怎麼做呢?

  1 )重新瞭解bug

  此時為了能夠復現bug,你可能需要回到上一步,重現去了解bug。因為你之前對bug的理解可能產生偏差,又或者你第一步並沒有做好才導致了bug未能復現。這個時候帶著疑問去重現瞭解bug,可能你會發現新的大陸。

  2)將偶現bug轉為必現bug

  偶現bug算是bug家族中最調皮的一個了。它們以沒有規律,難以復現等特性,經常能把一個好好的程式設計師給逼瘋。

  但是既然是要復現bug,那麼肯定要找到bug穩定復現的路徑,這樣才能方便下面bug的定位。這裡我推薦大家的一個做法就是想辦法把偶現的bug轉化為必現的bug。因為即使是偶現的bug,很多也是特定條件下必現的bug,只不過此時你還沒發現這個特定條件而已。

  那麼怎樣才能將偶現bug轉為必現bug呢?這裡我簡單介紹一下我常用的技巧:

  對比法:觀察並對比復現和不復現的各方面條件,找到那個必現的特定條件;註釋(刪除)程式碼法:對懷疑的程式碼進行註釋(刪除),直到徹底將偶現bug轉變為必現bug。

  3. 定位bug

  一旦我們找到了bug穩定復現的步驟之後,下面的工作就是開始定位bug產生的地方了。

  這一步可以說是解決bug的關鍵環節,這一步驟的難易程度一般取決於以下幾個因素:

  程式設計師自身的程式碼量(工作經驗);對專案程式碼(業務)的熟悉程度;分析問題和解決問題的能力。

  那麼我們如何才能更快地定位出bug產生的位置呢?下面我提供一些思路供大家參考:

  斷點除錯法。這是程式設計師通用,同時也是最有效的定位問題的方式。一個不會斷點除錯的程式設計師和瞎子沒有本質上的區別;

  日誌分析法。其實並不是所有bug都可以進行斷點除錯的。比如在一些迴圈呼叫或者業務較為複雜的場景下,打日誌分析定位是較為適合的方式;

  排除法。如果一個bug產生的原因可能有多種情況的時候,這個時候採取排除法的方式是最優的。你可以把可能導致bug產生的程式碼塊都打上日誌或者斷點,然後重現一下bug進行問題的定位;

  程式碼回滾法。如果你這個bug在之前的版本是好的,但是在現在版本上又出現了,這個時候就可以使用程式碼回滾大法。把你的程式碼回滾到你懷疑的版本,執行看bug是否消失,然後對兩個版本之前程式碼有何區別,最終定位出bug產生的位置。這裡我們可以使用二分法來提高程式碼的回滾效率;

  註釋(刪除)程式碼法。這個我在上一個步驟中也提到過。對於一些難以理解和定位的bug,我們可以使用這個方法進行嘗試。不過這個方法使用起來有一定的風險,因為可能你刪除的那一串程式碼雖然能夠解決bug,但是卻不是bug產生的根源,這個時候你可能會將必現bug改成了偶現bug,讓問題變得更加複雜;

  原始碼分析法。有的時候有些bug可能並不是你的程式碼導致的問題。可能是第三方庫本身的bug,又或者是系統本身的bug,又或者是你誤用api導致的問題,這個時候就需要你擁有原始碼分析的能力。深入原始碼中,一層層分析直到最終找到bug產生的原因;

  聯想法。通過一些類似的bug修改經驗從而聯想猜測出bug產生的位置。這個方法對使用者本身有較高的要求。需要使用者對專案程式碼和業務邏輯非常熟悉,同時對問題分析的能力有較高的要求。這就是我們常說的牛人能夠一眼就能看出問題,他們常用的就是這種方式;

  場外支援法。這是實在定位不出bug才採取的下下策。因為它並不能提高你定位bug的能力,同時請別人幫忙定位bug,你就需要把你之前所做的工作都要全盤地向他表述一遍,這樣不僅會降低bug修復的效率,同時還不一定能保證定位出bug產生的位置,它取決於你表述問題的能力和幫你的人分析和解決問題的能力。

  4. 確認bug

  在我們定位出bug產生的位置後,下面的工作就是分析bug產生的根源了。

  這一步可以說是bug修復6個步驟中最為關鍵的一步。這一步直接決定了這個bug能否被徹底地解決,同時也是最能體現bug修復藝術的步驟。

  但是很遺憾的是,這一步往往被很多人給忽視了。我為什麼會這樣說呢?因為很多時候我們修復bug的時候,都會受到各方面的限制:

  自身經驗水平的限制:一些初入專案的程式設計師經常因為修復一個bug而導致了另一個bug,又或者只是看到了bug的表象卻不能感知到bug產生更深層次的原因,所以10種產生bug的情況他可能只改了一種,將必現問題改成了偶現問題,讓bug變得更加複雜;

  時間限制:這是我們程式設計師經常碰到的限制。這在網際網路企業非常普遍,通常解決一個bug是有時間限制的,例如:這個專案明天就要上線了,並強制要求你今晚就得想辦法解決。這個時候你可能就被逼無奈,採取硬編碼的方式去臨時把這個bug給按住。其實這樣雖然bug是被臨時解決了,但是卻會讓這個bug變得愈加複雜。很多公司出現的那些祖傳程式碼就是在這種情況下產生的,動一下就可能產生無數未知的bug,令人絕望;

  業務限制:很多時候導致程式碼邏輯非常複雜難懂的罪魁禍首就是這種業務限制。我們在修復一個bug的時候,很多時候就是因為這種業務的限制,導致bug的修復一種不能從根源上予以解決,只要業務一調整就可能導致這個bug反覆地出現。

  說了這麼多限制,那麼我們如何才能找到問題的根源呢?

  多積累經驗,提升自身的水平:這是打破自身經驗水平的限制;及時處理bug:在收到bug報告的第一時間就去處理,儘可能打破時間的限制;多熟悉業務:有時間就多去了解和梳理業務,深入研究專案程式碼。這樣我們在解決bug的時候也不會因為對業務不熟悉而無法分析出bug產生的根源;準確定位bug:bug定位的準確性直接決定了你能否分析出bug產生的根源。因此你需要仔細分析和定位bug,使用我上面介紹的8種方式去定位bug。

  5. 修復bug

  其實前面的四步都是為這一步所做的鋪墊。有了前面四步的工作,相信到這兒也是相對微不足道的了,剩下的就是如何優美地解決這個bug了。

  到了這個階段,bug通常不需要大的修改來修復,因此這一步往往會非常快,當然也就沒有什麼好的技巧啦。

  6. 驗證bug

  作為bug修復的最後一步,它是確保bug被真正修復的最後保障。

  在這裡需要我們著重注意以下幾點:

  重複之前復現bug的步驟來驗證bug是否被徹底解決;驗證bug修復可能改動到的相關模組是否正常,保證bug修復不引入新的bug。

  如果上述有任何一點沒有達到的話,請返回步驟四和步驟五,重新修復bug!

  三、如何提高bug修復的效率

  上文我們著重講解了解決bug的藝術,為的是能夠更好地解決bug。但是如何才能保證既有效,又快速地修復bug,提高bug修復的效率呢?

  通過上面對於解決bug的藝術的講解,我們可以總結出以下影響bug修復效率的幾個關鍵點:

  bug資訊收集的效率以及有效性;時間限制的壓力;人員對專案程式碼(業務)的熟悉程度;人員自身經驗和分析問題的能力。

  以上4點可以說直接決定了bug修復的效率。那麼如何才能提高bug修復的效率呢?下面我將一一給出我的看法。

  1. 建立健全的資訊收集機制

  bug資訊的收集可以說是修復bug過程中最為耗時的環節。提升bug資訊收集的效率以及有效性可以大幅度地提升我們修復bug的效率。

  那麼我們應該如何建立健全的資訊收集機制呢?這裡我給出我的幾點建議:

  1 )提供優秀的bug報告模板

  上文我們在瞭解bug一步中提到過:一份優秀的bug報告模板,可以讓程式設計師直接跳過bug修復的前三步,直接進入到確認bug步驟,從而能夠極大地提高bug修復的效率。

  這裡我再次重複一步,一份優秀的bug報告模板應當具備哪些內容:

  bug的標題和問題描述;出現bug的應用版本;出現bug的裝置資訊(型號、版本等);bug產生相關的視訊、截圖和錯誤日誌;bug復現的步驟;bug出現的必要條件(環境)和恢復途徑;bug修復後的預期效果;bug對應的模組或者關聯bug。

  2 )建立完備的日誌體系

  一套完備的日誌體系,可以讓我們更加清晰地知道使用者到底做了什麼才導致bug的出現。

  在專案的初期,我們可能為了趕工期而常常忽視了日誌列印的重要性,這很可能就會導致該專案日後的維護將非常得艱難。

  那麼我們為什麼要建立一套完備的日誌體系呢?

  並不是所有的使用者(測試)都能夠給你描述清楚bug產生的資訊;即使使用者(測試)給你描述了bug產生相關的資訊,但是他們並不理解你的程式碼邏輯,他們只能根據bug出現的現象告訴你問題,可能他們的表述和你的理解不在一個頻道。

  如果你有這麼一套完備的日誌體系,那麼你就可以在使用者(測試)不用開口的情況下,直接get到使用者的操作行為以及對於的程式碼邏輯。同時,可能一句關鍵點的報錯日誌就可以幫你直接定位到bug產生的位置,從而直接進入第四步確認bug。

  說了這麼多,我們應該如何列印高效的日誌呢?

  在異常分支返回前列印日誌;在複雜業務流程的關鍵點列印日誌;在對外互動或者模組互動點列印日誌;在使用者互動或者生命週期的關鍵點列印日誌;對重要的資訊點列印日誌,記錄使用者畫像;按重要性分等級列印日誌;禁止在迴圈中列印日誌,禁止列印無效的日誌;禁止列印使用者隱私相關的資訊。

  2 .建立自動化測試機制

  建立自動化測試機制,可以讓突破時間限制成為可能。

  1)更早地發現bug

  很多時候來自時間限制的壓力,往往是測試不充分導致的。很多bug直到產品臨近上線或者交付的時候才被發現,這個時候唯一解決問題的方式就是在時間上做出限制,無情壓迫我們這些活在公司權力最底層的程式設計師們。

  如果這個時候能有一套自動化測試機制,每天下班後都進行自動測試的話,那樣很多bug就能被提前發現,從而為我們修復bug預留了不少寶貴的時間。

  2 )節約bug驗證的時間

  對於一些複雜難解、偶現的bug,我們往往會在確認bug到驗證bug之間花費大量的時間。這個時候如果有一套自動化測試機制或者工具幫助我們驗證bug的話,就可以極大地縮減我們修復bug的時間。

  3 .提高專案程式碼(業務)的熟悉程度

  提高人員對專案程式碼(業務)的熟悉程度,這樣就可以極大地提高人員定位bug的效率。

  1 )建立豐富的知識庫體系

  建立一套豐富的知識庫體系,可以幫助我們加深對自己責任內專案程式碼(業務)的理解,同時還能幫助我們快速瞭解我們所不瞭解的業務模組。

  那麼如何才能建立起豐富的知識庫體系呢?下面我給出我的幾點建議:

  對知識進行分類;定期新增和更新知識庫的內容;提高知識庫的檢索效率;定期組織知識的分享;激勵貢獻知識庫的人員。

  2 )建立責任田劃分機制

  劃分責任田的目的就是:讓專業的人做專業的事情。

  劃分責任田的好處:

  專業的人做專業的事情。劃分完責任田後,田主需要對自己負責的模組負責,這就必然要求其對模組內的程式碼(業務)更加熟悉;責任到人利於追責和bug跟蹤。

  當然責任田也不是想象中的那麼完美,它也存在一定的缺陷:

  職責明確之後可能導致缺少全域性視野。一些複雜的bug可能是幾個模組共同作用下才產生的,對於這類bug的定位勢必會大大增加難度;劃分責任田之後,可能導致踢皮球的情況。

  責任田劃分機制,它是一把雙刃劍。所以是否需要建立責任田劃分機制,還是需要結合企業自身的情況而定的。

  4. 提高人員的綜合素質

  提高人員的綜合素質,可以幫助我們提高定位bug、確認bug以及修復bug三個步驟下的效率。

  建立公平的員工晉升制度。這樣可以充分調動人員的主動性的積極性,提升人員的個人素質和業務能力;建立崗位輪換制度。讓人員定期負責不同的模組,可以極大地提升人員的綜合素質和全域性視野;定期組織培訓學習。

  四、最後

  以上內容,是我參與工作五年,開源六年以來所總結下來的全部經驗,喜歡的可以點選收藏或者三連支援一下!最後,還是祝福大家從此程式碼無bug,哈哈哈!!!