解bug的幾種思路

不完美

人無完人,人寫的程序天然免不了會產生各類各樣的bug。
它就像空氣同樣,包圍在咱們周圍,解bug能夠說是每一個程序員的屢見不鮮。css

解bug的過程

通常能夠分爲3步:前端

  1. 復現問題。若是問題能穩定重現,比較好說。對於很差復現的問題,筆者通常作法是在可疑代碼裏添加一些輔助日誌,而後將這些輔助日誌上線,等問題下次再次出現時,就能夠經過這些新增的日誌推測緣由。(若是日誌太多,刷的太快,日誌裏面能夠加上一些統一的關鍵字,這樣能夠經過grep查看本身關心的日誌)
  2. 定位問題。定位bug問題過程當中,會像偵探同樣,仔細尋找各類蛛絲馬跡。這個過程很關鍵,若是能很快的找到緣由,那麼解決問題就能駕輕就熟了。
  3. 解決問題。方法多種多樣,能夠本身尋找方案,能夠網上查閱,或者找他人討論等。

通常到這裏,就算是解決了這個問題。不妨在這個時候總結一下,在定位和解決這個問題的過程是如何的?筆者最近開始留意所經歷大大小小的bug,從中總結了一些通用的解決模式,這樣之後若是一條路走不通,能夠換下思路,以便可以更快的定位和解決問題。node

下面主要經過一些真實有趣的例子進行闡述,有些例子是開發過程當中遇到的問題或者需求,不必定是bug,但筆者認爲能夠做爲一種解bug的思路做爲參考。webpack

思路1-斷點調試

之前端爲例,能夠在瀏覽器裏設置斷點調試,
node.js的項目能夠在vscode裏進行調試,
其餘語言應該都有各自的調試方案。ios

斷點調試或者添加輔助日誌是最本能的一種方式了。git

思路2-縮小範圍

刪除法縮小範圍

好幾回遇到css樣式有問題,可是不知道究竟是哪裏的css產生的問題。程序員

舉個例子:
咱們的頁面使用了第三方ui庫iview的table組件,這個組件給table自帶了border樣式,它的樣子是這樣的: github

使用這個table組件有個問題是,border自帶的顏色和視覺稿的顏色不同,好比視覺稿的樣子多是這樣的:
因而但願經過覆蓋的方式改爲視覺稿的樣子,通常作法是先找到這個自帶的border在哪設置的,而後修改舊的css樣式去覆蓋它。

一開始的作法是每層元素找啊找,是哪一個元素作了設置呢?因爲border可能設置在不少元素上,好比div,table,thead,tbody,th,tr,td等等元素上,找了好久沒找到設置的地方....web

後來換了種方法找,在元素上右鍵"Delete Element",依次對可疑元素進行刪除。若是哪一個元素被刪除以後,border沒有了,那麼就說明border設置確定是在這個元素上設置的。 經過這樣排查後,最後發現這個border被設置在了2個地方。element-ui

border-top和border-left設置在table最外層的div上;
border-bottom和border-right設置在table某個外層的before和after僞類上。

找到了這些border設置的地方,就很好對其進行樣式覆蓋啦。

二分查找縮小範圍

若是某個問題是最近有次代碼提交引入的,但不知是哪次提交引入。好比,團隊有人說,"這個問題,以前都沒有的,最近纔出現...",能夠考慮這個辦法。

  1. 假設有問題的最新提交是commit1,
  2. 找到最近一次沒有問題的提交點,假設爲commit2,
  3. 那麼致使問題的應該是commit1和commit2之間的某次提交,能夠用二分查找辦法,查找這2個點之間的有問題的提交。
  4. 最後根據查看此次提交的內容,推測問題緣由

曾經嘗試過一次,使用這個辦法的前提是,須要肯定哪次commit是正常的,這個是關鍵。

思路3-對比法

前端有個特色,同一個功能,常常能夠有多種方式去實現,這個特色就爲咱們提供了一個很好解決問題的思路。
對比法是指,若是方法1有問題,那麼使用方法2,若是方法2能夠實現和方法1相同的功能,這樣經過對比一下這2個方法的區別,從而找到方法1的問題所在。

舉個例子:

先後端分離的項目,前端開發環境一般會經過webpack-dev-server,設置proxy和後端接口進行聯通。

有次遇到個問題是,前端代碼經過axios庫發請求到proxy對應的後端接口,但是接口請求返回顯示500,前端也沒有報錯信息。可是筆者經過postman直接調後端接口,返回正常的。
這說明接口是OK的,這就很詭異了,直接的辦法固然找後端開發看下後臺日誌,查一下是什麼致使的500,可當時後端開發不在,因而本身嘗試換了js原生的fetch接口發請求,更詭異的是fetch發請求成功了!

發現這個結果後,就開始對比經過這2個方式發送的請求有什麼不一樣。在對比請求header時,發現2者的cookie不同。而後手動清除cookie以後,從新用axios請求就正常了。

思路4-搜索關鍵字

搜索工具是個咱們的好夥伴,如何搜索倒是一門學問。若是搜索關鍵字選的好,有些問題都能快速找到解決方案,也有些問題,須要反反覆覆修改關鍵字,才能找到解決方法。

我在使用hightcharts繪曲線圖時,須要在series曲線點上hover時展現一個豐富數據的table和截圖,以下圖所示:

爲了實現這個功能,我在series上除了曲線xy軸須要的數據,還額外加了hover須要展現的數據,這樣hover時就能夠經過fomatter方法拿到這個點points上額外的數據,從而繪製tooltip。 可是好景不長,在我擴大x軸觀察範圍時,hover展現的各項數據都是爲undefined!!!

觀察到的狀況以下:

  • 當選擇時間區間較短時,小於8分鐘左右,大概400多個點,能獲取到point數據全部數據,包括x,y以及這個點上其餘自定義的數據
  • 當選擇時間區間較長時,大於8分鐘左右,能獲取到point數據,但只能獲取到x,y的值,沒法獲取到這個點上其餘自定義的數據。

大於8分鐘的效果以下:

因而開始搜索尋找問題所在和解決方案,嘗試過如下各類關鍵字:

  • highcharts width limit tooltip formatter points
  • highcharts 寬度 數據拿不到
  • highcharts pointer undefined
  • highcharts large data pointer undefined
  • highcharts large number of points(data)

這些都沒有辦法,在這個過程當中,又觀察到1個現象,若是把highcharts容器寬度width設大一些,就能夠獲取大於8分鐘時的hover數據,因而曾一度冒出偷懶的想法,但願能改下交互來解決這個問題,可是本着用戶體驗至上的想法,不能由於技術緣由讓用戶妥協,仍是繼續查查吧。

皇天不負有心人,終於在官方issues裏,經過下面這個搜索關鍵字下,總算找到了問題的答案!

  • highcharts points count less than data length

這個是highcharts官方issue裏的一個問題 查看地址

根據highcharts開發人員的回答,Highstock(這是highcharts下的產品之一,筆者繪圖也確實是使用的highstock,但若是用hightchats搜索應該更好)中有dataGrouping特性,默認是啓用的,這個特性將指定數量的數據合併展示爲一個點,顯示的值根據不一樣的圖表類型有所不一樣。因此多是由於不一樣的點的數據被合併了,才致使hover時,展現的是undefined。

所以咱們對應的解決方案就很簡單了,直接禁止這個特性就能夠了,設置dataGrouping.enable = false,便可關閉這個特性,只須要一個簡單的配置便可解決啦

在找到答案以前,也考慮過其餘解決方案,好比hover時想要的points數據不直接從曲線的points,而是將時間軸的x值做爲key,其它須要的數據做爲value存入1個變量,hover須要數據時根據拿到x值,從變量中獲取。(因爲後面找到最直接的方案,這個方案就未驗證了)

在這個例子中,筆者得到幾個想法:

  • 去issues裏搜索。這個適用於工程中使用了某些github上開源項目,若是遇到問題很差解決,優先考慮去github的issues裏搜索答案,由於這裏有來自開發者最直接的答案。這點在後好幾回我使用其它開源工具時遇到問題時,都是經過搜索issues快速的成功解決了問題。
  • 如何優化關鍵字,應該有不少方法。筆者未作深刻研究,一點淺顯理解是,英語要學好,多嘗試修改問題描述,或者根據上次搜索結果,參考新的關鍵字,總能找到一些蛛絲馬跡的。

思路5-查看源碼

對於有些網上也很差搜到的問題,有的時候,順着報錯信息去查看源碼,也不失爲一種好的思路。

好比我在使用element-ui樹組件時,使用了懶加載模式,其中有個問題就是,須要在最外層插入一個節點,天真的認爲調用它的一些已有的insert/append相似API應該能夠作到。好比在1個已有節點下加入了子節點,沒啥毛病,而後指望用一樣的想法實現最外層添加節點,嘗試以下:

issues上有人提過這個問題,開發者的回答是無計劃支持這個需求 地址

看着添加根節點時控制檯的報錯信息,要不就進去看看源碼如何寫的吧。因而找到報錯入口,進入源碼,大概研讀源碼,但願能找到一些但願。

從源碼分析來看,報錯的直接緣由是root節點的data爲undefined致使。爲了驗證這個,再次在斷點調試時,查看了節點data,和判斷一致。

查看root信息,發現root下有2個childnodes,可是data卻爲空

因而筆者想到的解決辦法是給root節點添加一個data,而後將須要新增的節點調用insertBefore加入,這樣接口就不會報data undefined的錯誤了。

解決了這個問題,API就能順利的在樹的最外層添加了新節點。

想必不少人也經歷過這些,若是源碼比較多,能夠看下關鍵的地方,另外邊調試邊看,效率會更高。

總結

以上即是我總結的幾個思路,相信在從此的工做中,可能還有更多的更廣闊的思路。 筆者水平有限,歡迎多多交流和指正,謝謝。

相關文章
相關標籤/搜索