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