#如何解決程序問題
在實現階段的程序員,也會經常遇到寫的程序出錯,然后就束手無策,不知道怎么去查找程序問題,我總結一些查找程序問題的方法,希望能幫到大家。
##不要向小白用戶那樣提問
很多人一遇到問題就問人,而且描述不清楚問題,只說簡單的問題現象,比如問“網站訪問不了怎么回事?”,“連接不上服務器怎么辦?”, “程序啟動不了,怎么辦?”,“程序在本地運行沒有問題,上傳到服務器運行就有問題,怎么回事?” 。 這些問題讓人無法回答,哪位技術大牛能回答這些問題呀?
大家要知道你是程序員不是小白用戶,不懂程序的小白用戶,看見網站訪問不了,他只能反饋給你網站訪問不了, 作為一個程序員,只拿這樣的現象去問人,技術大牛也不知道怎么解答,因為網站訪問不了可能的原因太多了。作為程序員,你是可以提供更多的信息的,比如程序的錯誤信息、錯誤碼、是在運行哪行代碼時出錯的,有了這些信息別人解答問題就更容易了。
我們在學校時,老師引導我們有問題就問,然后在編程時,有問題馬上問,只看見個現象就問,反而溝通效率低,自己成長也慢。有問題要先自己找問題。
##首先要重現問題
如果同事給你反饋產品有bug,不要光靠猜測代碼可能哪兒有問題就去改代碼了, 改好了還自己不測試就告訴同事說改好了, 結果同事測試后告訴你“還是有問題呀!”,你告訴同事說“哦,我知道哪兒問題了,我再改改”,然后還是靠猜測去改代碼,改好后還是讓同事測試。如果這樣往復幾次程序都改不好,你的同事就會極其煩你。而且這樣靠猜測修改代碼,很容易引起更多的bug。
大家在找問題上不要偷懶,先問一下同事是怎么操作出的問題,自己也按他的步驟把問題重新顯現一次,這一步我們簡稱“重現”,這樣能幫助自己更了解問題,知道是在什么情況下出現的,在運行什么程序時出的問題,從而找出程序的報錯的錯誤信息、錯誤碼以及 報警的文件地址和行數,然后解決bug就很容易了。解決完bug后還要自己測試一下,確認問題真的解決了再告訴同事。
##找程序報錯信息
每種編程語言看錯誤信息的方法都不一樣,我們要知道怎么看錯誤信息。比如PHP語言需要開啟報錯,才會顯示錯誤,在配置文件php.ini 中的設置配置項 display_errors 設置為on時才會把錯誤信息顯示在頁面中,不然的話,有錯誤也是顯示500錯誤的空白頁面。
如果是正式環境,開啟報錯并不安全,黑客可以通過報錯信息猜測程序哪兒可能有漏洞,從而攻擊我們的程序。正式環境下我們不開啟報錯,也可以通過查看錯誤日志文件知道錯誤信息, php的錯誤日志文件,可以通過php.ini配置設置
```log_errors = On
error_log = /var/log/php-error.log
```
然后在查找程序問題時,可以先查看看`/var/log/php-error.log`日志文件中是否有錯誤信息。
每種程序語言查看報錯的方式都有所不同,JavaScript會把報錯輸出到瀏覽器的控制臺,需要打開瀏覽器控制臺才能看見報錯信息。Android的報錯可以在eclipse中看到。 iOS的調試中的應用報錯可以在Xcode中看到。程序出錯總是有錯誤信息的,即使表面上看不見,也要想想是否有錯誤日志,去查日志文件,不知道錯誤日志文件在哪兒,就去問搜索引擎。
做iOS開發的朋友可能遇到過這樣的情況往往在安裝應用的時候,只是彈出一個安裝失敗的提示框,根本不知道什么原因,很多做iOS開發人員遇到這種情況束手無策,豈不知這種錯誤也是記錄到iPhone上一個錯誤日志里的,,用Log Guru這個工具可以抓取iPhone手機上的錯誤信息。
你不管在學習哪種編程語言,都要掌握查看錯誤信息、錯誤日志的方法。
往往找到了錯誤信息,在用搜索引擎搜索就會找到解決問題的方法。
但注意,有時候找的的錯誤信息可能不是真正的問題原因,比如報錯信息是內存不足,報錯所指向的程序文件第幾行代碼,那行代碼可能并沒有使用多少內存,它只是壓死駱駝的最后一根稻草而已,真正占用內存很大的代碼在前面。
我們沒有做好防衛性編程,也會導致報錯的信息不是真正的問題原因,比如某個變量我們認為它肯定不為空,在賦值時沒有做判斷, 在使用時程序才報錯。問題原因不是變量使用時的問題,而是賦值時的問題,我們在賦值時沒有做好判斷。就好比飛機遭到恐怖襲擊爆炸了,不一定是飛機的問題,可能是安檢的問題。
關于防衛性編程,我們會在以后的章節詳細講解。
##排除法找問題
有時候我們實在找不到錯誤信息,或者找到的錯誤信息對解決問題幫助不大,可以先列出問題可能的原因,用排除法按著一個一個排除,先查找認為最可能的原因。
比如一個有問題的程序,他涉及到查數據庫、調用接口、讀取緩存等操作, 可能導致問題的因素太多了, 我們要讓一些因素固定不變,比如查詢數據庫,我們可以把數據庫查詢結果寫死為一個固定的值,不讓程序真的去查詢數據庫,如果這樣程序還有問題,就排除了是查數據庫導致的問題,再繼續查其他問題。
這有點像做物理實驗,我們在研究摩擦力是否有重力有關的時候,一定要固定其他元素,要在相同的桌面上做試驗,只改變物體的重力大小。
用排除法讓問題的范圍慢慢縮小,慢慢我們肯定能找的導致問題的代碼在哪個文件的第幾行。
在修復問題的時候可以把有問題的代碼從復雜的環境獨立出來,做一個簡單的demo,然后來測試和修復問題。復雜代碼環境不利于我們測試,比如有一處代碼需要在產品上面操作好幾步才能觸發,每次測試十分麻煩,不然就把問題代碼獨立出來做一個簡單的demo單獨測試。等問題修復好了,再把代碼復制到原來的復雜環境中,再最終測試一遍。
##奇怪問題一般是因為粗心
有時候我們感覺遇到的問題很奇怪,比如:“我之前這么做都沒有問題,為什么今天會有問題。”
奇怪問題往往是因為粗心導致, 有可能只是少了一個標點符號。在PHP的判斷語言中應該有兩個等號卻只寫了一個等號。
```
if($num == 100){
echo '100';
}
```
經常粗心會寫成
```
if($num = 100){
echo '100';
}
```
判斷語句少了一個等號,變成了賦值語句,而賦值語句的條件永遠都會為true,粗心范的錯很難被發現,你會很奇怪“明明num的值不為100,為什么一直輸出100”
如果你覺得問題很奇怪,一定要想想是不是粗心的原因,去找找你認為不可能出錯的地方。
為了預防上面舉例中的粗心問題,所以很多開源PHP程序,都這樣寫條件判斷語句
```
if(100 == $num){
echo '100';
}
```
將判斷值現在雙等號前面,這樣如果粗心少寫一個等號會報語法錯誤。
##用好搜索引擎
找到了程序的錯誤信息或具體出錯代碼,再用搜索引擎上搜索很容易就能找到解決方法。程序的問題建議大家用Google搜索,會比百度準很多的, 但由于國內特殊原因Google不能正常訪問,可以使用aolsearch.com , 他的搜索結果是和Google一樣的。還可以在stackoverflow.com搜索一下,國外的程序員遇到問題喜歡在這里提問。
有時候整段話復制到搜索引擎去搜索,搜出來的結果比較少,可能找不到想要的解決方案。這時候要把整句話拆成關鍵詞去搜索,用關鍵詞搜索出來的結果比整段話多很多,更容易找到問題的解決方法。還有看看搜索引擎提示你的相關的關鍵詞,可以換換其他相關的關鍵詞去搜索。
##求助別人
如果上面的方法都不能讓你解決問題,這時候再找技術大牛問吧。
問人的時候不要只拿表面的問題現象問人,也不要問搜索引擎能搜到的問題。 你通過前面的方法已經找到了報錯信息,是運行哪段代碼出錯的,拿這些詳細信息問人,對方如果有經驗,很快就能告訴你怎么解決。
##解決問題后
我們千辛萬苦的把問題解決了,一定要做好筆記,不然下次遇到相同問題可能還是忘了怎么解決,可以總結一下寫在自己的博客中。
另外當我們解決一個問題后,想想我們的代碼中其他地方還有沒有類似的問題,把類似的問題都修正了,不要只修復發現的這一處。