@程序員,不會 Debug 還做什麼開發?

“每個大程序裏都有一個不安分的小程序”,想要成爲一名好的開發人員,你得先真正學會 Debug 才行。

以下爲譯文:

總結我的編程生涯,可以得出如下兩個硬道理:

  • 任何代碼都可能出錯,而且肯定會出錯。

  • 代碼有味道。

而中和這些苦澀現實的唯一方法就是調試(Debug)。

沒錯,就是調試。在剛開始接觸編程的時候,沒人會喜歡調試。相反,調試往往是沮喪和恐懼的根源。很多人心裏說:“我要浪費多少時間才能改好這個bug?”我們更加願意去構建很酷的東西。(試問誰不喜歡構建很酷的東西!?)

然而,所有我們欽佩的開發人員都認爲調試很重要。那是因爲他們知道調試對他們來說是提高自身實力的寶貴資源。在有些情況下,調試能夠反映出開發人員的能力。

調試的真正問題在於無法規劃所需的時間。所有編程活動——從設計到開發都可以有時間規劃。但調試卻完全不同,調試可能會花費一個小時、一天、甚至不知不覺一週就過去了,卻還是未能發現問題的根源並修復問題。

這就是你應該把調試作爲學習良機的原因。當然調試很痛苦,但是通過正確的方法你也可以控制調試。

以下是一些可以更好地進行調試的方法。

首先了解系統

我們經常會犯一個錯誤:“先理解出現的問題”然後再“理解系統”,實際的順序應該反過來。

曾經有一段時間,我調試過一個 SAP 智能表單的問題。表單上的有些值顯示不正確,我花了兩天的時間調試整個表單,仍然茫無頭緒。不用說,我的心情很沮喪。這個表單看起來似乎根本沒問題,後來我突然來靈感了——

我注意到主代碼中有兩處同時調用了該表單。通過進一步分析,我發現問題出在調用該表單的代碼中。我迅速解決了這個問題。我之前兩天的努力全白費了,事實上只需要在別的地方做一處小小的改動就可以解決問題。

那麼,我哪裏做錯了?

如果不理解這個系統的工作原理,那麼我就無法調試這個問題。一旦明白了系統以後,問題就很明顯了。

請時刻牢記,你需要了解系統的應有行爲、系統的設計,以及在某些情況下系統如此設計的原因 。如果你不理解系統的某些部分,那麼問題往往就會出現在你不瞭解的這些部分上。

分而治之

我付出了很大代價才明白了這個道理。

有一段時間,我參與了一個大型的 SAP 數據遷移項目。當時的時間非常緊迫,而且有很多代碼塊同時開發。在這個節骨眼上,我遇到了數據損壞的問題。

一些遷移的客戶數據遭到了破壞,從幾百萬條記錄中找出哪些出了問題是一項無比艱鉅的任務。雖然我知道問題是什麼,但是問題出在什麼地方纔是關鍵所在。

最後,我通過原型製作解決了這個問題。我創建了一個很小的原型,通過一套子數據集重現了類似的症狀。我通過這個原型找到了根本原因,並最終解決了問題。

解決問題的關鍵在於縮小搜索範圍。

大型系統都很複雜,系統的運行涉及許多因素。從整體上來看系統,你很難區分出影響特定問題的細節。

解決方法是分而治之。不要着急着眼於整個系統,將有問題的組件或模塊從代碼中分離出來,才能進行嚴謹的調試。

分離問題有許多優點。你可以只關注與問題相關的部分,由於代碼量很少,所以你可以快速解決問題。

請時刻牢記,通過剝絲抽繭,逐步縮小範圍,最終 bug 將無藏身之處。

一次只做一個改動

就好比使用步槍,一槍一個眼;而不是霰彈槍,一槍炸一片。

想象一下,你去牙醫那裏拔牙。你的牙醫爲了“設法”找到問題,開始對着你滿嘴的牙下手。他手中的錘子每敲一下,你就痛苦地呻吟一聲。

這時,你有何感受?你心裏肯定在犯嘀咕:“什麼情況啊?這個混蛋會不會給人看病啊?”

錯誤的調試方式亦是如此。

一次只改動一個地方。如果你手中拿的是一把好步槍,那麼你可以更好地修復 bug。我見過有些開發人員試圖通過交換或修改其他組件來修復錯誤的代碼。可能在他們改動了三四處代碼後,發現可以正常工作了。這看似很酷,但是他們完全不知道哪個部分有問題。更糟糕的是,他們所做的這些改動很有可能破壞本來運行得好好的代碼。

在很多情況下,你需要改動系統的不同部分,來看看是否對這個問題有影響。一般來說,這是一個警告,你並沒有充分地瞭解代碼,而是在猜測。你只是在改變問題發生的條件,而不是尋找問題自然發生的原因。

這種做法會隱藏第一個問題的原因,還會導致更多問題的發生。這是開發人員都需要避免的錯覺陷阱。

請時刻牢記,如果一次只做一個改動,那麼你可以確切地知道哪個參數有效。如果改動看似沒有效果,那麼請立即恢復原樣!

檢查是否真的是由於你的改動才修復了 bug

調試的一個黃金法則是:如果不是你的改動修復了 bug,那麼這個 bug 就沒有得到修復。

每個人都願意相信 bug 不藥而癒了——“似乎我們無法再重現這個 bug”——“這個 bug 出現了幾次,但後來不知道發生了什麼,不再重現了。”當然,合乎邏輯的結論是,“也許這個 bug 不會再發生。”但是,你猜怎麼着?它還會發生。

很抱歉讓你們失望,但現實世界中沒有神仙。

如果你覺得你已經修復了某個 bug,那麼你需要確保去掉你的改動後,這個 bug 會再次重現;還要確保加上改動後,bug 就會被修復。你需要重複從改好到重現再到改好的過程,只改動與修復 bug 有關的代碼,否則就不能證明你修復了這個 bug。

修復 bug 往往很有意思。有時 bug 只是“隱藏了起來”而不是真正被解決了。有時候,當我們意識到我們的改動與要修復的 bug 無關時,產品早已發給了客戶,顯然他們不會滿意這種產品。所以,千萬不要掉入這樣的陷阱中。

請時刻牢記,如果去掉你改動的代碼,那麼系統就會重現之前的 bug,只有這樣才能確保你的修改確實有效。

最後,記錄你的解決方案

這項工作看似無關緊要,但其實是一個常常被忽略的非常重要的問題解決工具。問題在生活、工作甚至是長期的人際關係中反覆重演,我們沒必要一次又一次地重複造輪子。

關於解決方案日誌中實際記錄的信息類型而言,考慮到業務之間的需求不同,所以很難下結論。但是,通常可以考慮如下幾項:

  • 問題編號

  • 彙報人(記錄通話的人)

  • 彙報人的分機號碼或電話號碼

  • 創建日期/時間

  • 概要描述

  • 影響/重要性

  • 故障類型

  • 系統的所有者

  • 當前狀態(開放,正在處理,已關閉)

  • 下一步

  • 下一步的日期

  • 完成日期

  • 解決方案,開發請求編號或供應商支持請求的鏈接

不要在同一個地方跌倒兩次。爲了提高工作效率,請記錄所遇到的問題以及最終的解決方案。遇到問題時,我們不必再說:“我以前見過這個問題,但我不知道怎麼解決。”你可以快速查找過去使用過的解決方案。不用說,這種做法不僅可以節省你的時間,還可以大大地提高你的自尊和自信。

請記住,調試是一個學習的良機。當然,有時你會意識到你犯了一個本不應該犯的愚蠢錯誤。但這也是成長爲一名更好的開發者的必經之路,因爲你可以藉機學習新知識。

Richard Pattis 有一句話說得很好:

新手調試時會添加矯正代碼;而專家調試時會刪除有缺陷的代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章