告別狗屎代碼,請(qǐng)記住這11條編碼秘訣!
這是一篇值得收藏起來,隔三差五就拿來重讀的文章!因?yàn)樽髡呦蚰惚WC,他“遇到的所有糟糕的代碼,都是因?yàn)闆]采納這些實(shí)踐經(jīng)驗(yàn)。而任何一段優(yōu)秀的代碼,都采納了至少部分實(shí)踐經(jīng)驗(yàn)。”
還等什么?趕快看看這些經(jīng)驗(yàn)就是什么吧?
我已經(jīng)寫了20年代碼了,在此期間曾與17個(gè)團(tuán)隊(duì)共事過,使用不同的語言做過數(shù)百個(gè)項(xiàng)目。
這些項(xiàng)目從最簡(jiǎn)單的博客網(wǎng)站,到支持每秒3000多次請(qǐng)求的API,還有曾經(jīng)熱賣過的應(yīng)用。
根據(jù)這些經(jīng)驗(yàn),再結(jié)合我讀過的書,我認(rèn)為編程中最重要的是:可讀性。
1.可讀性
表面上看來,可讀性似乎很主觀。不同語言、代碼、和團(tuán)隊(duì)對(duì)于可讀性的定義不盡相同。但如果深入本質(zhì)的話,就會(huì)發(fā)現(xiàn)代碼可讀性有一些非常關(guān)鍵的因素。
許多程序員太傾向于計(jì)算機(jī)了,只要程序能運(yùn)行就一了百了。盡管是老生常談,但這種方式完全斷絕了人參與的可能性。
最近幾個(gè)月, 我在努力將這些人為因素提煉成11條寫程序的實(shí)踐經(jīng)驗(yàn),專門討論如何增強(qiáng)可讀性并降低復(fù)雜度。
我在BaseCode中寫過這些詳細(xì)內(nèi)容,并將其應(yīng)用到真實(shí)世界的代碼片段中。
許多人會(huì)認(rèn)為這些太基礎(chǔ)、無關(guān)緊要,可以忽視。但我可以向你保證,我遇到的所有糟糕的代碼都是因?yàn)闆]采納這些實(shí)踐經(jīng)驗(yàn)。而任何一段優(yōu)秀的代碼都采納了至少部分實(shí)踐經(jīng)驗(yàn)。
2.格式
我們?cè)诟袷缴舷牧颂嗑ΑV票矸€是空格,Allman還是K&R??倳?huì)有一天,你會(huì)意識(shí)到格式在編程中并不是最重要的。
選擇一種格式,應(yīng)用到代碼中,然后將這個(gè)過程自動(dòng)化。然后就可以重新專注于寫代碼本身了。
3.代碼
所有注釋掉的代碼塊、未使用的變量和無法到達(dá)的的代碼都是垃圾。他們就像在對(duì)讀者說,“我不關(guān)心這段代碼”。
于是惡性循環(huán)開始了。日復(fù)一日,死代碼最終會(huì)埋葬你的代碼。這正是經(jīng)典的破窗效應(yīng)。
必須要找出并干掉死代碼。雖然不需要把精力主要放在這里,但一定要時(shí)時(shí)留意。更多代碼規(guī)范請(qǐng)看這篇文章《優(yōu)秀 Java 程序員寫代碼的風(fēng)格》。
4.嵌套代碼
邏輯幾乎是一切代碼的基礎(chǔ)。我們寫代碼是為了做決策、迭代和計(jì)算。一般情況下都會(huì)導(dǎo)致分支或嵌套,從而造成嵌套得很深的代碼塊。
雖然計(jì)算機(jī)很容易閱讀這種代碼,但對(duì)于人類則是非常大的精神負(fù)擔(dān)。因此,代碼會(huì)變得復(fù)雜、難以閱讀。應(yīng)該通過防御語句、提前返回或使用函數(shù)式編程等方式消滅嵌套代碼。
5.使用對(duì)象
盡管現(xiàn)在是面向?qū)ο缶幊痰臅r(shí)代,我們依然使用了過多的原始指令。
長(zhǎng)長(zhǎng)的參數(shù)列表,雜亂的數(shù)據(jù),自定義的數(shù)組或字典結(jié)構(gòu)等。這些都可以重構(gòu)成對(duì)象。
這樣不僅能讓數(shù)據(jù)結(jié)構(gòu)變得正規(guī),還能容納所有重復(fù)的、使用原始數(shù)據(jù)的重復(fù)的邏輯。
6.大型代碼塊
雖然沒有具體的數(shù)字,但代碼塊的長(zhǎng)度應(yīng)該是有限制的。如果你認(rèn)為你的代碼塊過大,就應(yīng)該對(duì)其進(jìn)行識(shí)別、重組并重構(gòu)。
這個(gè)簡(jiǎn)單的過程可以讓你確定代碼塊的上下文和抽象級(jí)別,以便正確地找出代碼的任務(wù),并將代碼重構(gòu)到更加易于閱讀、更簡(jiǎn)單的代碼塊中。
7.命名規(guī)則
當(dāng)然,好的命名很困難,但只是因?yàn)槲覀內(nèi)藶樵黾恿穗y度。有個(gè)小技巧在編程的許多方面都能用得上,包括命名,那就是——延后。不要糾結(jié)某個(gè)東西的命名,繼續(xù)寫代碼就好。
就算是用一整句話命名一個(gè)變量都沒問題,繼續(xù)寫代碼就好。我可以保證,當(dāng)你完成整個(gè)功能之后,更好的名字就會(huì)浮出水面。
8.刪除注釋
在我看來這一條至關(guān)重要,刪了注釋我才能把精力放到可讀性上。不管我如何解釋刪除注釋的必要性,總會(huì)有人跟我抬杠,然后舉出一個(gè)絕對(duì)需要注釋的例子。
當(dāng)然,如果哈勃望遠(yuǎn)鏡要和古老的適配器連接,而后者返回一個(gè)意思不明的687,這種情況肯定需要注釋來說明。但大多數(shù)其他情況下,你應(yīng)該盡量重寫代碼使得它不需要注釋也能看懂。
9.合理的返回
我們總是選擇返回最奇怪的值,特別是對(duì)于邊界條件的情況。像-1、687或null。然后就得寫很多代碼來處理這些值。實(shí)際上,null的創(chuàng)造者稱它為“10億美元的錯(cuò)誤”。
應(yīng)該努力返回更有意義的值。理想情況下,***是即使在反面情況下也能讓調(diào)用者繼續(xù)執(zhí)行的值。如果真的是異常情況,那么***用其他方式來通信,而不是使用null。
10.三的原則
考慮一下數(shù)學(xué)上的序列。給出數(shù)字2并問你,“下一個(gè)數(shù)字是什么?”可能是3可能是4,但也可能是1或2.1。實(shí)際上你沒辦法知道。然后我提供了序列中的下一個(gè)數(shù)字2, 4然后問,“下一個(gè)是什么?”可能是6,8,也可能是16。
同樣,盡管猜對(duì)的可能性增加了,但還是不能確定。然后我提供了數(shù)列中的第三個(gè)數(shù)字,2, 4, 16,然后問“下一個(gè)是什么?”有了三個(gè)數(shù)字之后,程序員的大腦很容易看出這是個(gè)平方序列,于是確定下一個(gè)數(shù)字是256。這就是三的原則。
這個(gè)例子雖然跟編程沒關(guān)系,但它告訴我們,我們不應(yīng)該太早做抽象。三的原則能阻止我們過早消除重復(fù)的努力,直到有了足夠多的信息后再做出決定。用Sandi Mets的話說,“重復(fù)的代價(jià)遠(yuǎn)遠(yuǎn)低于錯(cuò)誤的抽象。”
11.對(duì)稱性
***一條實(shí)踐經(jīng)驗(yàn)?zāi)芙o所有代碼的可讀性帶來詩一般的潤(rùn)色,那就是對(duì)稱性。這條來自Kent Beck的《實(shí)現(xiàn)模式》一書,書中說到:
代碼中的對(duì)稱性是說,同樣的思想在任何地方都使用同樣的實(shí)現(xiàn)。
不過說起來容易做起來難。對(duì)稱性體現(xiàn)了編程的創(chuàng)造性。它是許多其他實(shí)踐的基礎(chǔ):命名、結(jié)構(gòu)、對(duì)象、模式等。不同語言之間、不同代碼之間和不同團(tuán)隊(duì)之間對(duì)于對(duì)稱性的定義都可能不一樣。
因此,你需要花上許多年去追求對(duì)稱性。但是,一旦開始在代碼中使用對(duì)稱性,就會(huì)迅速呈現(xiàn)純粹的形式,代碼的形狀也會(huì)迅速變好。更多代碼規(guī)范請(qǐng)看這篇文章《優(yōu)秀 Java 程序員寫代碼的風(fēng)格》。






