對于IT相關(guān)從業(yè)人員來說,看別人代碼是必不可少的磨難。在學(xué)習(xí)階段,我們經(jīng)常需要從書上看別人的代碼以吸取寶貴經(jīng)驗,這是相當枯燥無趣的過程,也時常無法領(lǐng)會作者的意圖。在實際工作中,不可避免的出現(xiàn)需要接手做到一半的項目或是團隊合作的項目,這時候就必須看以前的工程師的代碼。如果說看書上的代碼用痛苦來形容的話,那么這種情況時遇到代碼不夠規(guī)范或者設(shè)計不合理,簡直就是苦不堪言。還有一些神一般的選手,設(shè)計者在編寫代碼時的“靈機一動”,其結(jié)果只有他自己和上帝才看得懂。這些代碼能看得你覺得生不如死,甚至開始懷疑人生:到底是代碼寫得混亂or我水平不行?!你以為這是最痛苦的嗎?NO!還有一種情況足以令你看得生不如死,甚至開始懷疑人生。那就是遇到運行不正常的代碼,對問題排查錯誤花的時間和精力還不如重新寫一遍,這時你的內(nèi)心完全是崩潰的! 有一件事非常無奈,我們不可能要求別人的代碼都非常規(guī)范。所以,正確的學(xué)習(xí)方法和思維方式尤為重要。怎樣看他人代碼才是正確的方式?看代碼之前應(yīng)該做些什么準備工作?看代碼用正向思維還是逆向思維?如何判斷代碼中哪些地方是否值得借鑒?由此,掌握到一種通用的去看懂別人代碼的技巧顯得非常重要。下面我們就來談?wù)勥@方面。 我們知道,而實現(xiàn)功能可能有很多種方法,所以不同的人寫出的代碼不相同。通過看代碼去知道它要實現(xiàn)的是什么功能是一件很困難的事情。有些初學(xué)者會想到采取仿真一下、看電路圖、流程圖、時序圖、注釋等等方法,都是不可取的,通過這些你還是無法知道它的功能,以及有沒有錯誤。 那么正確的方法是什么呢?我們采取一種可稱之為“反推法”或是“逆向法”的方式,這個問題就迎刃而解了。要知道,代碼的目的是實現(xiàn)功能。無論你用那種代碼,有一點完全相同的就是“實現(xiàn)功能”這個最終結(jié)果。了解到這一點,我們就可以通過結(jié)果(功能)去反推過程(代碼),代碼的思路、流程、用途就抽絲剝繭清晰的顯露出來。好的,下面我們舉個實例來說明怎么通過反推法有步驟的去看懂別人的代碼。 代碼1。 如果我們按照自上而下的順序去看這個代碼,通過代碼的過程去看實現(xiàn)的功能會是很困難的事,甚至看不明白它要實現(xiàn)的是什么功能。Ok,我們現(xiàn)在從功能看起,這個代碼要實現(xiàn)的是“幀率采樣計算”這個功能,可以理解為圖片每秒顯示多少幀數(shù)。 1. 從代碼中我們可以看出,CMOS_FPS_DATA這個信號是我們所要求的信號(一秒內(nèi)的幀數(shù)率); 2. CMOS_FPS_DATA<= fps_data >>1在一段時間內(nèi)保持不變,才是我們所要的結(jié)果; 3. 從CMOS_FPS_DATA<= fps_data >>1中可以看出,CMOS_FPS_DATA是通過fps_data 這個信號來實現(xiàn); 4. fps_data這個信號是怎么來的?反推到fps_data <= 0和fps_data<= fps_data + 1'b1這兩個信號。fps_data復(fù)位為零,在else if(Frame_valid)條件下加1;因此fps_data為幀數(shù)率標志信號; 5. 從CMOS_FPS_DATA<= fps_data >>1中可以看出是通過<= fps_data>>1右移一位,也就是說除以2得到這個值的; 6. 為什么要fps_data除以2來得到這個值?于是反推到if(delay_2s == 0)這個條件。 現(xiàn)在作者的意圖就非常清晰了。滿足幀數(shù)率的情況下不斷+1,到2秒時間時根據(jù)統(tǒng)計結(jié)果除以2,由此得到1秒時間的幀數(shù)。到此為止,我們已經(jīng)可以非常容易的看懂這個代碼了。 通過反推法我們也能比較容易的去看代碼是否有錯誤。首先我們?nèi)ブ来a需要實現(xiàn)的功能,通過反推法得知是通過什么方法實現(xiàn)的,進而仿真時定位其目標,去看該代碼是否完成了功能。如果沒有完成功能,那么代碼就有誤。 對于學(xué)習(xí)者來說,反推法的意義還不僅在此。在本例中,這個設(shè)計思路完全滿足功能要求。這時,我們應(yīng)該擴展思考,本例是通過2秒來實現(xiàn)功能,為什么要用2秒?是否可以直接通過1秒,或是3秒,或是其他方案來實現(xiàn)呢?各種方法的優(yōu)缺點在哪里?通過反推法得知作者實現(xiàn)項目的方法并思考,這種方法正確還是錯誤?如果是錯誤或者這種方法不太好,那么我們?nèi)绾伪苊?如果是?yōu)秀的代碼,我們?nèi)绾谓梃b并能舉一反三地運用到其他項目中去?本例只是選取項目中的一個小的節(jié)點,對于看整個項目的代碼來說可以運用反推法嗎?敬請關(guān)注下一節(jié):《如何看懂別人的代碼(下)》。 |