如何能出令自己满意的代码
1. 數(shù)據(jù)結(jié)構(gòu)和核心算法
關(guān)于數(shù)據(jù)結(jié)構(gòu)的重要性,大神Linus Torvalds講過(guò)這樣的話,我覺(jué)得非常贊同:”Bad programmers worry about the code. Good programmers worry about data structures and their relationships.” (低水平程序員總在考慮代碼,高水平程序員總在考慮數(shù)據(jù)結(jié)構(gòu)及其之間的關(guān)系)
數(shù)據(jù)結(jié)構(gòu)考慮清楚了,核心的算法自然就出來(lái)了,這就是關(guān)于每個(gè)類(lèi)的每個(gè)方法如何實(shí)現(xiàn)的問(wèn)題。比如需要實(shí)現(xiàn)一個(gè)中位數(shù)查詢方法,如果你前面確定了數(shù)據(jù)保存的格式是一個(gè)列表,那么你可以考慮采用插入排序法;如果數(shù)據(jù)格式是自平衡二叉排序樹(shù)(AVL),則只需直接返回根節(jié)點(diǎn)就可以了。
數(shù)據(jù)結(jié)構(gòu)決定算法,所以你在考慮數(shù)據(jù)結(jié)構(gòu)的時(shí)候,一定要盡可能地使數(shù)據(jù)的結(jié)構(gòu)和它的自然屬性相匹配,不然后面的實(shí)現(xiàn)就會(huì)是一場(chǎng)噩夢(mèng)。比如,你把一個(gè)多層級(jí)的結(jié)構(gòu)定義成二維數(shù)組,看上去也靠譜,相當(dāng)于在一個(gè)表格里維護(hù)一個(gè)組織結(jié)構(gòu)圖,可是當(dāng)你做到部門(mén)增減的時(shí)候,本層級(jí)的數(shù)組元素移動(dòng)自不必說(shuō),下面各個(gè)層級(jí)的元素移動(dòng)就很容易亂套,而且性能很差,可能你寫(xiě)了2000行代碼還有很多邊界條件會(huì)出錯(cuò)。相反,如果用一個(gè)孩子兄弟鏈表來(lái)表示這個(gè)樹(shù)型結(jié)構(gòu),操作起來(lái)就非常容易,可能100行都足夠了。
2. 功能實(shí)現(xiàn)
思路確定后,實(shí)現(xiàn)過(guò)程也需要大量的構(gòu)思活動(dòng)。碰到你比較熟悉有經(jīng)驗(yàn)的領(lǐng)域,你自然可以輕車(chē)熟路,但難免會(huì)有一些你不太熟悉的技術(shù)需要嘗試。有的同學(xué)比較排斥這種領(lǐng)域,比如我好不容易才掌握了Struts 2,領(lǐng)導(dǎo)又讓我去學(xué)習(xí)Grails框架,我就會(huì)覺(jué)得很不爽,大概看了看就挑出它的一堆問(wèn)題,然后能躲多遠(yuǎn)就躲多遠(yuǎn)。可是我要說(shuō),這樣的心態(tài)會(huì)阻礙自己不斷提高技術(shù)水平。作為一個(gè)程序員,最大的挑戰(zhàn)也是最大的樂(lè)趣所在,就是不斷學(xué)習(xí)新的技術(shù),沒(méi)有這樣的心態(tài),很快就會(huì)落后。
好,那么遇到不熟悉的技術(shù)怎么辦?我的體會(huì)是,先不要急著實(shí)現(xiàn)項(xiàng)目中的代碼,自己另外維護(hù)一個(gè)測(cè)試項(xiàng)目,在里邊邊查文檔邊學(xué)習(xí),邊做一個(gè)小功能,把所有需要在項(xiàng)目中實(shí)現(xiàn)的功能先在測(cè)試項(xiàng)目里跑通,然后再寫(xiě)項(xiàng)目里的代碼。這樣做的好處是把單個(gè)技術(shù)問(wèn)題和其他潛在的bug隔離開(kāi)來(lái),便于快速學(xué)習(xí)新技術(shù)。否則,你直接在項(xiàng)目里寫(xiě)代碼出錯(cuò)以后,要判斷問(wèn)題的源頭都要多費(fèi)好幾倍的精力。
3. 測(cè)試
測(cè)試很重要,設(shè)計(jì)測(cè)試用例就像開(kāi)發(fā)時(shí)設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)一樣,也是很關(guān)鍵的。在設(shè)計(jì)測(cè)試用例的時(shí)候,要把當(dāng)時(shí)自己設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)的思路全部忘掉,或者找別人來(lái)設(shè)計(jì)測(cè)試用例,不然會(huì)不由自主地測(cè)試那些你已經(jīng)考慮到了的地方。這樣測(cè)試是跑通了,用戶一用起來(lái)可能各種邊界條件會(huì)到處出問(wèn)題。
有人會(huì)推崇TDD的方法,先設(shè)計(jì)好測(cè)試用例,然后在開(kāi)發(fā)過(guò)程中確保所有測(cè)試通過(guò)。我個(gè)人不喜歡這種方法,雖然承認(rèn)從開(kāi)發(fā)質(zhì)量管理和長(zhǎng)期維護(hù)的角度來(lái)說(shuō)TDD是很有必要的,但我個(gè)人嘗試的結(jié)果是,設(shè)計(jì)完測(cè)試用例后,想到開(kāi)發(fā)的目標(biāo)不是實(shí)現(xiàn)功能,而是為了跑通測(cè)試,就感到毫無(wú)樂(lè)趣可言。這一點(diǎn)我自己也覺(jué)得很矛盾。
寫(xiě)到這里我又想到大神Linus說(shuō)過(guò)的另一句話:”Regression testing” What’s that If it compiles, it is good; if it boots up, it is perfect. (“回歸測(cè)試”?這是什么東西?如果代碼能編譯就是好的,如果它啟動(dòng)了,那就是完美的。)
當(dāng)然了,大神水平擺在那里,他有資本目空一切,咱確實(shí)沒(méi)資格仿效。但是我還是覺(jué)得TDD也有TDD的問(wèn)題,測(cè)試是很重要,但把它擺到驅(qū)動(dòng)開(kāi)發(fā)的高度,就有點(diǎn)本末倒置了。這個(gè)是我自己的一點(diǎn)看法,本人對(duì)TDD了解得不深入,如果有謬誤之處,請(qǐng)多多指教。
4. 代碼可讀性
要想自己滿意,代碼的可讀性一定要好。要做到一年后甚至幾年后你拿到自己寫(xiě)的代碼,還能很容易看明白當(dāng)時(shí)的思路和實(shí)現(xiàn)。這就涉及到命名和注釋的問(wèn)題。
命名就像超市里的商品標(biāo)簽一樣,要讓看得人一目了然就知道這是個(gè)什么東西,比如你在員工類(lèi)里定義了兩個(gè)屬性是到崗日期和離職日期,定義成date1和date2就沒(méi)有多少可讀性,定義成dateOnBoard和dateQuit就比較清晰一些。
注釋也是很重要的,它可以用來(lái)說(shuō)明一段代碼的作用,算法的設(shè)計(jì)思想,或者是方法調(diào)用的參數(shù)格式要求等。有人覺(jué)得命名就是注釋,代碼本身就為自己代言了。我覺(jué)得這種說(shuō)法用來(lái)強(qiáng)調(diào)命名規(guī)范的重要性是很好的,但是因此說(shuō)不需要注釋則有失偏頗。試想,如果Dijkstra首次發(fā)明最短路徑算法的時(shí)候,他給出的代碼里沒(méi)有一行注釋,即使所有的變量命名都定義得準(zhǔn)確而嚴(yán)謹(jǐn),又有幾個(gè)人能看懂他的算法呢?所以,在重要或者復(fù)雜的地方,都需要詳細(xì)地寫(xiě)一些注釋,便于看代碼的人清晰地了解你的思路。
最后總結(jié)一下:要想寫(xiě)出自己滿意的代碼,首先不要急于動(dòng)手,要先仔細(xì)想清楚思路性的東西,尤其是數(shù)據(jù)結(jié)構(gòu),然后在實(shí)現(xiàn)過(guò)程中大膽嘗試小心驗(yàn)證,設(shè)計(jì)好測(cè)試用例,確保代碼的可讀性,就可以在代碼中表現(xiàn)出自己的最高水平。但畢竟各人水平是有差異的,自己滿意并不等于其他人欣賞。我對(duì)此的看法是,不求盡如人意,但求無(wú)愧我心,足矣。最后再
總結(jié)
以上是生活随笔為你收集整理的如何能出令自己满意的代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 神经网络不收敛的 11 个原因及其解决办
- 下一篇: [线性代数]Note4--A的LU分解转