perl除錯哲學(轉)

miguelmin發表於2009-01-17

描述 我的除錯哲學
我相信三件事情:

這不是個人問題

別老想著是你的程式碼。你可能覺得自己是個藝術家,但實際上就算是經驗豐富的大師也會寫出很多垃圾。每個人的程式碼都是垃圾,我的也是你的也是。要學著去喜歡它。當你碰到問題的時候,你應該想:“噢,我寫的垃圾程式碼出了點問題。”這說明你不再去責怪 Perl。不應該變成個人性的問題。

忘記你以前怎麼做的。如果不是你做事的方法有點問題,你也不會來讀這個。這並不是壞事,只是到了該有點長進的時間。我們都經歷過的。

[@more@]

個人責任感

如果你的程式碼出了問題那僅僅是——你的問題。你應該盡最大的力量自己解決。記住,每個人都有自己的程式碼,每個人都有自己的問題。自己的作業自己做,在麻煩別人之前先儘自己最大的努力。如果你老老實實地按照這個指南做了所有能做的事之後,依然不能解決問題,那麼你已經盡力了,應該找別人來看看。

改變你做事的方法

改正之後不要再犯同樣的錯誤。很可能是你寫程式碼的方法錯了,而不是你寫的程式碼錯了。改變你以前做事的方法,讓生活更容易些。不要指望Perl來習慣你,因為這是不可能的。你要習慣 Perl。它只是種語言,而不是種生活方式。

我的方法: 你用strictures編譯程式碼嗎?

如果你不用 strictures,請把它開啟。Perl 高手們之所以是高手,因為他們使用嚴格模式,使得他們有更多的時間解決其他問題,學新的東西,以及上載模組到 CPAN。

你可以使用 strict pragma 在程式碼中開啟 strictures

use strict;

也可以用perl的 -M開關在命令列中開啟它:

perl -Mstrict script.pl

你可能會被它搞怒,但是堅持用上它幾個禮拜之後,你會寫出更好的程式碼,花更少的時間來檢查低階錯誤,而且可能就不再需要讀這個指南了。

什麼是warning?

Perl 會對一些有問題的結構給你警告提示。把 warning 開啟,讓 Perl 來幫你。
你可以在第一行用 perl的 -w 開關開啟它:

#!/usr/bin/perl -w

也可以在命令列開啟warning:

perl -w script.pl

你也可以使用詞彙警告,它帶有許多有趣的特性。更多的資訊參看warnings 的幫助文件。

use warnings;

如果你不明白某個警告的意思,你可以使用 warning 的詳細模式,或者在你的程式碼中使用診斷 pragma:

use diagnostics;

解決第一個問題先!

你從 Perl 中得到警告或者錯誤資訊之後,先解決第一個,然後看Perl是否依舊報出其他錯誤。因為後續的錯誤很可能是由於第一個錯誤衍生而來的。

檢查錯誤資訊行號之前的程式碼!

Perl 在錯誤已經發生的時候才報錯,而不是在此之前。因此當 Perl 報出行號時錯誤已經發生了,而出錯的地方是在這之前。看看錯誤行號之前的程式碼和表示式是否有問題。

那個變數值是你想的那樣嗎?

不要亂猜!在表示式中使用某個值的時候先檢查它是否正確。世界上最好的偵錯程式就是 print。

print STDERR “The value is [$value]n”;

我用括號括住 $value 的原因是因為這樣我可以看見開頭和尾巴上是否有空格或者換行。

如果這個值不是標量,那麼我使用 Data:umper 來列印這些資料結構。

require Data:umper;
print STDERR “The hash is “, Data:umper:umper( %hash ), “n”;

如果列印出來的結果不是你所期望的,那麼移到前面幾句,再來!找到這個值最後正確的位置。也可以用 perl -d 開關開啟內建的 Perl 偵錯程式。更多資訊請參考perldebug。

perl -d script.pl

你也可以使用其他偵錯程式或者開發環境,想 ptkdb(一個基於Tk的圖形偵錯程式)或者是 Komodo( Active States 基於 Mozilla 的 Perl IDE)

你用的函式是正確的嗎?

我寫 perl 程式的時間已經不短了,可我還是幾乎每天都要查 perlfunc。有些東西我就是吃不準,而有時候我太缺乏睡眠了以至於沒了常識,然後總搞不懂為什麼 sprintf() 不列印到螢幕上。

你可以用perldoc命令和它的-f開關來查詢某個特定的函式。

perldoc -f function_name

如果你在使用一個模組,查詢它的文件,看看你是不是在用正確的方式使用它。你可以用 perldoc 查詢它的文件。

perldoc Module::Name

你用的特殊變數是正確的嗎?

同樣,我經常去查 perlvar。不過,當我發現 Perl 快速參考這本書(The Perl Pocket Reference)更加方便之後,我就很少查perlvar了。

你用模組版本正確嗎?

有些模組在升級版本的時候會有不少改變。你知道你用的模組是什麼版本嗎?你可以用一個一行的 perl 語句檢查你的模組版本:

perl -MModule::Name -le ‘print Module::Name->VERSION’;
如果你讀的文件不是你機器上的本地文件,而是像 或者 上的,那你就比較有可能碰到文件版本差異的問題。

你用小指令碼測試過了嗎?

如果你在嘗試新的東西,或者覺得某一小段程式碼很奇怪,你可以寫一個最短的程式執行一下這一個片斷。這個方法把所有其他的因素都排除在外。如果測試沒有問題,那說明問題可能不在這段程式碼裡面。如果測試結果不對,那你大概就找到了你的問題所在。

你檢查環境了嗎?

有些東西是依賴環境變數的。你確定你的環境變數都是對的嗎?程式執行的時候用到的環境變數是你現在看到的環境變數嗎?記住有些 CGI 程式或cron 可能用到的環境變數和 shell 裡的不一樣,尤其是在不同的機器上的時候。

Perl 講環境變數儲存在 %ENV 裡 。如果你需要某個環境變數,就算是在測試的時候,也記住先提供一個預設值,如果它原來不存在的話。

如果還有問題,檢視你的環境。

require Data:umper;
print STDERR Data:umper:umper( %ENV );

你試過Google了嗎?

其他人也許碰到過和你同樣的問題。用 Google Groups()搜尋看看是不是有人在 comp.lang.perl.misc 上發過類似帖子, 沒準還能發現其他人給出的解決方法。在新聞組裡問問題的人和回答問題的人的差別在於,他們使用Google Groups 的能力高底不同。

你對程式做過效能測試嗎?

如果你想知道是哪些部分讓你的程式變慢,試過效能測試嗎?可以讓Devel::Small Prof 幫你做這件事。它可以計算 perl 執行每一行程式碼的次數和花費的時間,然後列印一份漂亮的報告。

到底是那個測試沒透過?

如果你有一套測試,到底是哪個測試失敗了呢?你可以很容易的找到錯誤所在,因為每個小測試只執行一小段程式碼。

如果你沒有,為什麼不寫一個呢?如果你的程式碼很短很短,或者只是一個一次性的程式,那我不會建議你專門寫一套測試出來。但如果不是這樣的情況,那寫一些測試程式碼是很有幫助的。Test::Harness讓這件事變得太容易了,以至於你都找不到理由不做。如果你說你沒時間,那大概是因為你不用測試而在指令碼除錯上浪費了太多時間。

你和小熊說話了嗎?

把你的問題大聲說出來。把它變成語言。有幾年我很愉快地和一個很優秀的程式設計師一起工作,他幾乎能解決任何問題。當我被什麼問題堵住的時候,我總去請教他,跟他解釋我的問題。幾乎每次都是這樣的情況:我說不到第三句,就停下來,說:“噢我明白了,沒問題了。”他每次也都是這樣。

你可能需要做太多次這樣的事情,所以我推薦拿一個長毛絨玩具做為你的Perl 臨床診斷家,這樣你就不會惹怒你的同事了。我的桌子旁邊就有一隻小熊,我每次都把我的問題解釋給他聽。每次當我自言自語的時候,我女朋友跟本都不會注意,她習慣了。

這問題在紙上看起來有點不一樣了嗎?

因為你老是看著電腦螢幕,所以說不定一種新的媒介可以讓你從新的角度看這個問題。把程式列印到紙上試試看。

你看 Jon Stewart 的節目嗎?

說真的。可能你不太喜歡 Jon Stewart,那換一個其他的。休息一下,停一會,讓你的大腦放鬆放鬆。當你回來的時候說不定問題忽然就很容易解決了。

你認真檢查自己了嗎?

如果到了這一步你還沒有解決的話,這說不定是個心理問題。可能你對某段程式碼有特別的感情,所以不想改掉它。說不定你覺得只有你是對的,別人都錯了。當你有這種感覺的時候,你該考慮一下問題的來源—你自己。不要過於自負而不願認清自己的錯誤。

作者
brian d foy,

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16723161/viewspace-1016244/,如需轉載,請註明出處,否則將追究法律責任。

相關文章