建立除錯的基礎措施,有一個很大的目的是為了在臭蟲被回報時,可以快速透過日誌檔,找出臭蟲的根本原因(Root Cause)。到目前為止,在除錯上反複進行的動作,是(1)試著重現(Reproduce)問題、(2)觀察程式的流程,以及狀態(3)逐漸縮小觀察的範圍,找出臭蟲的所在。
搜尋臭蟲的所在,大概占除錯70%以上的時間。大多數時候,要解決臭蟲,只需要更動少數幾行程式碼就可以辦到,但是尋找它們的時間,卻是相當的漫長。
除錯這一門技巧,很大的比重落在如何在茫茫大海般的程式碼中,找到臭蟲隱藏之處。
找到適合的起點很重要
程式員該如何加快找到臭蟲的速度呢?首先,選擇一個合適的搜尋起點是相當重要的。現代的軟體開發,在軟體架構設計上,多半都具某種程度的模組化。從出錯的症狀,大致上可以推論出可能隱藏問題的模組,此時便可以有一個適合的起點,例如,系統如果無法成功的建立網路連線,問題就可能網路通訊的模組或子系統。
接下來你會使用除錯器(Debugger)或日誌程式庫除錯。透過中斷點的設定,及變數值的監測,或是直接閱讀日誌記錄檔中的訊息,逐漸縮小可能的範圍。
你也可能發現,其實問題並不出在你所選的模組,而是另一個有交互影響關係的模組,例如,系統無法成功地建立網路連線,原因是系統組態設定的模組,某些情況下,不能正確的讀取網路連線的IP及Port值,因而提供了錯誤的輸入值給網路通訊模組,引發網路連線無法建立的問題。所以,問題也許就剛好發生在你所判斷的區域之內,但也可能恰好不是。
經驗是除錯最大的資產
搜尋臭蟲需要幾個要素:經驗、耐心、謙虛、好運氣。有經驗的程式員,對於何種症狀是由什麼臭蟲造成,基本上他腦海裡已建立一個資料庫。看到某一類的症狀,大概就可以猜得出可能的原因。
好比過去我們曾經開發過一個系統,在測試時,一切都好好的,但系統上線後,每天早上登入的第一個使用者,一定會需要十分漫長的等候時間,才能夠完成登入的動作。
經過診斷,我們發現是該系統所用的Connection Pool(一種重複運用資料庫連線的機制)發生了問題,Connection Pool所持有的資料庫連線,因為閒置過久(此系統夜間通常不會有使用者)已經被伺服器切斷,但Connection Pool卻沒有將它移除,使得系統在服務每天早上第一個登入的使用者時,從Connection Pool中取出的資料庫連線,都是不能使用的。
系統必須要等候該連線回應逾時,才能取得下一個可用的資料庫連線。這樣特別的問題,往往需要花費一段時間才能搞清楚真正的原因。之後,我又遇上另一個系統,也有相同的症狀,便能夠很快地猜測,是Connection Pool的機制所引起的,查證後,事實果真如此。
經驗是程式員很大的資產,累積足夠多的經驗,對於診斷問題,有極大的幫助。經驗能給程式員一個好的起點,而好的起點就支配了解決問題的速度及效率。
搜尋臭蟲的過程是枯燥乏味的
Perl之父Larry Wall曾說:「程式員的三大美德是:懶惰、沒耐心、還有傲慢。」雖然我頗為認同上述的看法,但是除錯和撰寫程式碼的態度,卻有可能不同。例如,要有耐心就是一點。
沒耐心之所以是程式員的三大美德之一,是因為好的程式員對於效率不夠好的程式缺乏耐心,渴求迅速地執行,因而不斷改善程式效率。但這種急迫的心情,到了除錯階段,反而必須轉變。
愈是藏在隱晦不明處的臭蟲,愈需要耐心找尋。倘若不能仔細觀察每一段流程,或每一個可能影響的狀態或變數值,便有可能在搜尋的過程中,錯失幾乎垂手可得的臭蟲。
另一方面,搜尋臭蟲的過程,不像撰寫程式碼時那樣創造新事物的感覺,過程往往是枯燥乏味的。因此除錯時,必須忍受煩悶,細心而且耐心地檢查每個需要檢查的事物。除錯缺乏耐心,在反覆檢查的過程中,反而會把時間浪費掉。
過度自信可能把心力花在錯誤的地方
雖然Larry Wall告訴我們,程式員應該要傲慢,不過除錯時卻需要一顆謙虛的心。程式員在除錯時會有一種心理上的障礙,也就是過度有自信,不相信某一段程式碼(尤其是自己負責寫的那一塊)會有問題,因此也不願意花心思及時間去檢視這一段程式碼,把時間及心力耗費在其他的地方。
不幸的是,問題時常就恰好出現在最不可能出現的地方。所以除錯時,應該放下傲慢的心情,將大腦歸零,所有先入為主的想法及假設也都歸零。倘若跳脫不出這個框架,很難找到問題。
例如,我們有一個產品的開發,是和另一個團隊合作的,由他們提供所需的核心部份,而由我們開發應用端的程式。在測試的階段,由測試人員回報了一個臭蟲,而負責解決這個臭蟲的成員,由於過去(不好)的經驗,先入為主地認為,這個問題必然是由核心程式碼所引發,因此,把時間耗費在檢查核心及應用程式之間的介接部份,結果花了相當長的時間,仍然徒勞無功。
為什麼不好好檢查自己所負責的部份呢?因為基於過去核心部分品質不佳的經驗,因而假設問題仍是核心所引發,也因為過度自信,相信自己的程式碼不會出錯,所以才把心力花在錯誤的地方。
天外飛來的靈感也會立下功勞
我認為,除了除錯的種種技巧之外,克服此類心理障礙是很關鍵的。程式員會基於自己對系統或專案的熟悉及經驗,而做出種種的判斷及推論。但很不幸的,系統之所以會發生無法預期的情況,正是因為這些判斷及推論有問題。
假若程式員對自己的假設深信不疑,那麼自然找不到真正的問題所在。所以在除錯時,心中必須放下所有既定的成見,讓自己變成一張白紙,只從變數及狀態觀察,並檢視日誌記錄檔的訊息,收集賴以診斷、搜尋問題的線索及證據,再基於這些線索及證據來推論,才可以避免除錯的思緒,受到既有的成見污染,而被引導到錯誤的方向。
有足夠的工具(除錯器、日誌程式庫)、有熟練的技巧、有好的心理建設,臭蟲大多能乖乖束手就擒。面對頂級困難程度的臭蟲,你還需要一點好運氣和第六感。除了好運氣外,天外飛來的靈感偶而會立下功勞,也許早晨起床刷牙刷到一半,腦中靈光乍現,猜出了臭蟲的位置也不一定。
在程式碼中搜尋臭蟲,就像是在迷宮中尋找出口。得細心地在牆上標記必要的記號,藉以逐漸描繪出迷宮的地圖。你所能賴以指引方向的,便是這份地圖,除了技巧的挑戰,尚有心魔必須克服。
《作者簡介》王建興
清華大學資訊工程系的博士研究生,研究興趣包括電腦網路、點對點網路、分散式網路管理、以及行動式代理人,專長則是Internet應用系統的開發。曾參與過的開發專案性質十分廣泛而且不同,從ERP、PC GAME到P2P網路電話都在他的涉獵範圍之內。
熱門新聞
2025-01-13
2025-01-15
2025-01-14
2025-01-14
2025-01-13