成為高手的必經之路——學會除錯程式碼(菜鳥必讀)

recive發表於2014-04-23

       任何一個程式設計者都少不了要去除錯程式碼,不管你是高手還是菜鳥,除錯程式都是一項必不可少的工作。一般來說除錯程式是在編寫程式碼之後或測試期修改Bug 時進行的,往往在除錯程式碼期間更加能夠體現出程式設計者的水平高低以及分析問題的準確度。不少初學者在尋找錯誤原因時,總是不得要領,花費了大量時間卻無法解決一些最終證明是相當簡單的Bug。

        在長期解答 zTree 相關問題時,也的確發現很多的問題其實不算什麼問題,僅僅是程式設計者不會除錯造成的,通過自己日常工作觀察,這裡面有態度問題也有思考問題的方式方法,故總結一下自己經驗,以供大家參考(尤其是菜鳥), 對於高手來講,如果你願意看完這篇文章,也非常歡迎拍磚和提供建議,我相信這樣可以不斷讓這篇文章充實並完善起來,肯定也可以幫助到更多的朋友。

試想一下:出現了某個bug,有人用幾分鐘就搞定了,有人用了半天或者一天都找不到原因所在。你願意當前者還是後者呢?想當前者的就請好好看完本篇文章吧。

本篇文章主要是幫助大家在除錯程式碼時,如何建立解決問題的思路。所以並不會專門介紹不同瀏覽器的具體除錯方法。(在網上關於 chrome、firefox、ie 等瀏覽器的具體除錯方法已經有很多了,這裡就不一一描述啦。)另外,俗話說的好——“js、html 和 css 是一家”,因此在講述中也會稍帶有html 和 css 的內容。

 

一、 遇到錯誤怎麼辦?

辛辛苦苦寫了一大段程式碼卻無法執行,怎麼辦?……前兩天還正常的程式碼怎麼今天報錯了,怎麼辦?……同樣的程式碼在這個頁面正常怎麼到了另一頁面就出問題了,怎麼辦?……這些情況你都遇到過嗎?是否被錯誤搞得焦頭爛額、心情煩躁?(“不管路途有多麼遙遠,有多少艱難險阻,都不可能阻擋我前進的步伐!”——唐師傅)

 

1、 調整心態

出現問題很正常,其實不出問題反倒不太正常。所以當發現問題的時候我們需要冷靜。不要在乎身後站著的是誰,不要在乎距離上線時間還有幾個小時,讓自己平靜下來,深呼一口氣——來吧,不就是個小問題嘛。所有的Bug都在我的掌控之中!

禁忌:出了問題就找人幫忙,這樣會導致經常打擾別人,而且也不利於自己的技能提升。只有當自己經過一番努力後,的確找不到解決辦法時再去尋求幫助。而且提出問題時,也要儘量將問題描述清楚。

 

2、 尋找特徵

解決錯誤的前提是要發現錯誤,發現錯誤的前提嘛…當然是要去“尋找”嘍!對於簡單的報錯資訊完全可以利用除錯工具的提示:xxxx行出現什麼什麼錯誤。如果這則資訊100%有效,那麼你就不需要再看這篇文章了。

我們遇見的錯誤表象一般分為以下幾種

  • 直接報告 js 語法錯誤

這種一般最容易解決,不需要我來廢話了……

  • js 報錯,但報錯地點不是出問題的根源

這種情況大部分可以解決,但有時候完全不知道是從哪裡引用過來的,這種時候會相當的頭疼。

  • js 無報錯,但功能無效

這種情況更糟糕,完全沒有頭緒了……那我告訴你,往往這種時候最終解決錯誤的方法更容易。

根據特徵,往往能夠快速定位錯誤的大概位置,便於進一步查詢問題。

 

3、 懷疑一切

當有人告訴你程式碼有問題時,我們的第一反應經常是:“不可能!”,“你是不是看錯了?”,“我剛才執行還好好地呢!”如果你有以上想法,那麼需要注意嘍!這些想法很危險,如果想解決問題,那麼我們就要去懷疑任何有可能的事情,要以特徵為主,不要主觀斷定哪些地方肯定不會出錯。

 

二、 如何讓錯誤現出原形?

前面主要是為了讓我們能有一個良好的心態來處理問題,情緒保持冷靜可以讓我們的思維更加敏捷,抓住特徵可以讓我們更快的找到線索,懷疑一切可以讓我們有更多的思路去發現錯誤。(“不把妖孽打得顯出原形,就別想翻過這座山!”——猴哥)

 

1、 化繁為簡

臨床表現:莫名其妙的報錯,不方便除錯,單純看程式碼無法解釋出錯原因。

主要病因:js指令碼衝突、Css衝突、DOM的ID衝突、DOM標籤缺失等多種由於衝突產生的bug根源

排查方法:熟練使用 Delete / Backspace 鍵,對程式碼不斷進行區域刪除,直到症狀消失,最後一次刪除的區域很可能就是導致錯誤的根源。進一步查詢根源可以在目標區域使用更小單位的區域定義反覆使用此方法。

注意:

  • 對於 js 程式碼建議分別以類庫  功能  行 為單位進行刪除測試
  • 對於 HTML 程式碼建議按照頁面結構先刪除最內部的 tag,由內及外,這樣可以迅速發現由於 tag 缺失造成的錯誤,同時也能保證每次刪除的都是整段的程式碼,避免由於刪除產生新的錯誤。
  • 對於 css 程式碼建議按照css檔案  定義的class系列  行 為單位批量進行刪除測試

忌:對於確認與相關功能有關的部分不要隨便刪除。

副作用:使用此方法也可以很好的確認錯誤原因是js造成的還是css造成的。

 

2、 順藤摸瓜

臨床表現:錯誤資訊較準確,能夠按照提示的錯誤逐層跟蹤,使用“化繁為簡”能夠基本定位的錯誤型別

主要病因:基本語法錯誤、邏輯錯誤、不嚴謹(最常見的有:陣列下標越界,null空指標導致的物件找不到,undefined未初始化,NaN數字計算錯誤等)

排查方法:利用瀏覽器的除錯工具(F12是個很好的功能鍵):跟蹤程式碼;利用console.log 輸出監控物件(IE無效);利用 alert監控(最無奈的方法,用於極端情況);把除錯程式碼載入報錯命令列的前面,一般都會有奇效!

注意:

  • 對於無js 報錯的情況,直接除錯無效功能的程式碼即可。有時候會發現之所以功能無效的原因居然是沒有呼叫該程式碼!(是不是很可笑?我承認我犯過這種錯誤。)
  • 邏輯錯誤往往不太容易想清楚,這時候可以適當結合“化繁為簡”的思路進行除錯。
  • 當你使用的是類似於 jQuery 這種js庫時,如果報錯資訊處於js庫內,首先要更換為未壓縮的js程式碼進行除錯,然後分析是自己的哪段程式碼會呼叫相關功能。

忌:鑽牛角尖!當按照此方法仍無法找到錯誤根源時,說明這並不是一個準確的錯誤資訊,肯定有其他潛在的因素在產生錯誤。立刻更改切入點,不要在一個地方長時間浪費時間。(這種時候,可以參考下一個方法:“反覆對照”)

 

3、 反覆對照

臨床表現: 應用普通方法很難定位錯誤,前兩種方法怎麼用都還是找不到頭緒。

主要病因: 邏輯複雜、功能互相繫結難以剝離、頁面物件內容複雜、有的頁面正常有的頁面不正常、相容問題等

排查方法: 對付這種複雜的麻煩,排查方法也會很繁瑣,但並不是什麼特別高深的技術,只是需要多做一些體力活兒而已。

  • 方法一:檢查可疑的程式碼,細化功能點,每次只修改一個地方,修改一次就測試一次,直到發現導致錯誤的關鍵程式碼。
  • 方法二:製作最簡單的Demo 只實現需要的功能,當功能正常後,與出錯的正式程式碼進行比較(比較中可以適當使用方法一)
  • 方法三:以正常功能(或出錯)的程式碼為原型,修改一個地方就生成一個測試的備份,每個測試的案例都只有一處與原始程式碼不同,編上號碼,在特殊環境下逐一測試,檢查導致錯誤的根源(我曾經用這個方法解決了韓文系統下IE8載入公司內部flash 不能正常發聲的bug)

注意:

  • 使用此法一定要有耐心
  • 此方法技術含量低,任何人都可以快速掌握,解決某些疑難雜症基本上可以說是藥到病除!

忌: 急躁、馬虎

 

4、 積累經驗

臨床表現:部分瀏覽器報錯、事件響應異常、js操作DOM無效、PC 和 觸屏系統功能不一致等

主要病因:各種相容問題

排查方法:對於某些有明顯特徵的報錯要熟記於胸,看到這些情況能立刻想到應該是哪些原因導致的。(最明顯的例子:Json物件多了一個逗號的情況,只有ie報錯)

注意:

  • 有個很基礎的問題,但有很多初學者出錯——沒有搞清楚頁面 html、css、js 的載入順序,導致js 操作失敗。(去Google 或 Baidu 搜尋:“html css js 載入順序”)
  • 日常工作要細心,勤觀察。認真對待每一次查詢錯誤的工作,對於部分非常特殊的情況可以記下來。
  • 熟練利用 Google、Baidu 等搜尋引擎,有時候自己第一次遇到的情況,別人早都知道如何解決了。

忌:粗心大意、不求甚解

 

5、 細節決定成敗

以上四種查詢錯誤的方法全部都依賴於一個核心——細節!細節往往比你的技術水平更重要。說一句誇張點兒的話,能有多少那麼高深的技術等著你去做?好好把自己手上的工作認真完成吧!但請記住了,當你重視細節以後,你距離去做高深技術的機會應該也就不遠了。

 

三、 如何修正錯誤?

老程式設計師們應該已經深有體會,改Bug 最頭疼的還是找錯,一旦找到錯誤後,真正解決問題可能真的是隻有幾分鐘。下面針對一些常見的錯誤原因與修改思路總結一下:

 

1、 基本語法、語言基礎

逗號、分號、雙引號、單引號 以及 各種括號 估計都曾導致過你的程式碼錯誤吧?這些東西記牢,必須知道什麼時候應該使用什麼,不要為了簡化程式碼而精簡這些符號。

例如:if / for 等語句後面的 { } 最好還是帶上吧。

補充,對於js中的Number 數字的範圍希望大家有一定的瞭解,因為這個範圍肯定和後臺語言中的Long不一樣的。(已經有不止一個朋友跟我說 zTree 會自動修改節點的id,當我看到案例後,原來是數字溢位了!)

 

2、 條件嚴謹

對 Array 或者操作物件屬性時,儘可能讓條件判斷語句寫的完整、全面一些。

例如:判斷 a.abc 的時候,最好別忘了判斷 a 是否存在;或者操作Array時先判斷一下Array 是否存在,要操作的下標是否越界等。

 

3、 注意相容(css & js)

警惕部分瀏覽器不一致或者出錯的情況,很多情況都是相容造成的。如果自己經驗不夠,直接去Google 或者 Baidu。慢慢的自己經常接觸到的一些相容問題就會牢記下來了。

補充,有時候要注意頁頭 W3C的定義,曾經有朋友問我 zTree 異常的問題,最終發現是 W3C只寫了一半。

 

4、 邏輯陷阱

條件過於複雜;迴圈、判斷反覆巢狀都是容易導致邏輯陷阱的因素。遇到這種情況,如果自己實在無法解決那麼請個身邊的高手來吧,讓他幫你講解一下。我相信,除了那些有點兒自閉的人來說,別人都會願意幫助你解決問題的(前提是你自己別太遭人恨了,呵呵)

補充:多去看看有關 重構 的技術書籍!會讓你提高很多的。

 

5、 非同步載入

其實非同步載入出現的問題往往屬於邏輯陷阱,但我必須要提出來專門講述,因為在這上面犯錯的人太多了!!!!這裡專門詳細講述一遍處理方法:

  • 對於非同步載入出現了異常,請按照以下流程進行逐一排查:

1)頁面是否有報錯,是否執行到 ajax 部分的程式碼?(如果正常請看下一條)

2)用瀏覽器的除錯工具監控網路,ajax 載入的url 地址是否正確?(如果正常請看下一條)

3)用瀏覽器的除錯工具監控網路,傳遞給url 的引數是否正確?(如果正常請看下一條)

4)用瀏覽器的除錯工具監控網路,從url 返回的資料是否正確?(如果正常請看下一條)

5)在 ajax 的success中編寫除錯程式碼,除錯非同步載入後的處理方法是否正確

如果以上幾步都正常,那麼我可以告訴你非同步載入本身是一切正常的,還有錯怎麼辦?繼續往下看

  • 當非同步載入確定正常後,就需要考慮另一個重要問題,也就是我在上一篇文章《這些年我們愛犯的弱智錯誤(菜鳥必看)》中專門講述的易犯的錯誤——非同步載入的疏忽

1)千萬不要在執行了 ajax 之後立刻去執行應該在非同步載入完成之後再執行的程式碼。因為你執行這段程式碼的時候,ajax根本沒有完成呢。(最明顯的現象:執行時時好時壞,但如果我加入了alert 會發現每次都正常了)

這種情況,請將你的程式碼轉移到 ajax的 success 或 error 裡面去執行

2)當你設定了某些特殊開關時,一定不要忘了在 ajax 的error 裡面進行重置,否則很可能因為一次網路異常,就會造成你的頁面js 功能失效。這種錯誤常常是地雷級別的,很難被發現。

 

6、 神奇的setTimeout

對於移動裝置 或者 某些特殊情況,可以適當考慮使用 setTimeout 來解決問題。

我遇到比較特例的情況:有兩個js的事件因為不同的功能在同時對同一個DOM操作時會導致IE8崩潰,顯然這是IE的bug,但我無法去要求微軟做什麼…最終使用 setTimeout 讓其中一個功能延遲100-200毫秒再執行,輕鬆搞定!

 

7、 別在一棵樹上吊死

做前端的人都很鬱悶要適配n多的瀏覽器,往往會遇到一些自己無法解決的問題(因為是瀏覽器bug 造成的),遇到這種情況怎麼辦?一般來說尋找一下有沒有 hacker的方法,如果沒有,那麼就換一種思路,看看是否可以有其他方案來實現類似的功能。如果各種努力都做了…還有人不滿意的話,那麼告訴他瀏覽器的bug,讓專案管理者來決定到底如何處理吧——這種情況死而無憾了!

 

寫到這裡,基本上可以說是傾囊而出了,希望能有一點點引起你的注意,希望能夠讓你感到一絲的觸動,感到一些似曾相識。最主要的我還是希望你能夠快速提高自己的技能,拿到多多的工資,讓自己成為技術牛人!

 

轉載自http://www.iteye.com/topic/1124479  謝謝!

相關文章