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,哈哈哈!!!

 

作者丨 xuexiangjys 來源丨公衆號:我的Android開源之旅(ID:openandroidxx) dbaplus社羣歡迎廣大技術人員投稿,投稿郵箱: [email protected]
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章