譯者 | 陳峻
審校 | 梁策 孫淑娟
眾所周知,干凈的代碼不但能夠讓閱讀者方便理解程序的意圖,而且也方便維護與迭代。總的說來,它能夠給軟件的開發(fā)與升級帶來如下好處:
- 在維護上花費更少的時間。干凈的代碼更易于被閱讀和領(lǐng)會,您可以花費更少的時間去弄清楚實際問題的來龍去脈,進而為修復(fù)、修改、以及擴展等操作留下更多的時間。
- 更清晰地交流想法。程序開發(fā)離不開協(xié)作。而干凈的代碼往往可以減少項目成員之間可能產(chǎn)生的誤解。而且從長遠來看,這也意味著更少的錯誤,更快地解決問題。
不過,正所謂“知易行難”,從某種程度上說,編寫干凈的代碼就像學(xué)繪畫、烹飪或攝影那樣--看起來比較容易,實踐起來則比較困難。下面,我將和您討論能夠編寫出優(yōu)秀且干凈代碼的十大技巧。
1.使用描述性名稱
程序中的變量、類和函數(shù),往往是給其他程序員、以及應(yīng)用程序底層邏輯之間的接口調(diào)用的。因此,當(dāng)您對變量、類和函數(shù)使用不明確且非描述性的名稱時,實際上就是在擾亂閱讀代碼者(包括開發(fā)人員自己)對應(yīng)用程序邏輯的理解。例如:您能一眼看出一個名為dxy的變量的實際含義嗎?想必,您必須閱讀整個代碼塊,才能對其含義進行“逆向工程”吧。不過,對于變量distanceBetweenXY,你我都能夠馬上領(lǐng)會到它代表的含義。
同理,類和函數(shù)也是如此。請盡量避免使用CalcTan(),而應(yīng)當(dāng)按需采用CalculateTangent()或CalcTangentAngle()??傊沟么a看起來整潔的基本技巧之一便是使用描述性名稱。
2. 讓每個類/函數(shù)都有實際意義
您一定看到過那些長達數(shù)百甚至數(shù)千行的函數(shù)吧?想必,您在瀏覽、理解、甚至是編輯的時候會覺得無比痛苦。就算行間有相應(yīng)的注釋,其實際效果往往也是“杯水車薪”的。而干凈的代碼則不然。它們會被分解成不同目的的代碼塊。其中,每個子函數(shù)都被設(shè)定為完成某個具體的任務(wù),而每個類也都代表了一個特定的概念。由此帶來的簡潔性,更適合局部調(diào)整,也更適合問題的定位與排查。
例如,在實踐中,諸如GetCreditScore()之類復(fù)雜的功能,有必要被分解成為GetCreditReports()、ApplyCreditHistoryAge()、以及FilterOutstandingMarks()等多個輔助函數(shù)。您可以參考《??每個程序員都應(yīng)該知道的基本編程原則??》一文,來進一步了解相關(guān)做法。
3.刪除不必要的代碼
不知您是否有過這樣的體驗:在修復(fù)或優(yōu)化某段代碼的過程中,您特意將其注釋掉,并在其下方開始動手重寫新的代碼。而且,您這樣做的目的,只是純粹為了保留舊的代碼,以備不時之需。不過,隨著時間的推移,您可能會不知不覺地積累了大量的、不再需要的、被注釋掉的代碼塊。這些代碼塊無疑會讓您的源代碼變得混亂不堪。而且,多數(shù)實際情況往往是:由于周圍的相關(guān)代碼、及其環(huán)境也早已發(fā)生了迭代,因此這些被注釋掉的代碼,其實并不可能再被恢復(fù)使用了。
當(dāng)然,這種注釋掉舊代碼的做法,完全可以被如今時尚的源代碼控制系統(tǒng)所取代。您可以通過使用Git或Mercurial之類的工具,及時、準確、自動化地開展源代碼管理工作。
同時,為了讓應(yīng)用服務(wù)輕便而敏捷,您也可以有意識地通過現(xiàn)成的Web框架,避免“重復(fù)造輪子”,進而利用由框架提供的類庫,來簡化自己的代碼。對此,您可以具體參考《??一些值得開發(fā)人員學(xué)習(xí)的Web框架??》一文。
4.可讀性
大多程序員會把“干凈的代碼”和“聰明的代碼(clever code)”混為一談,并簡單地認為“把十行代碼壓縮成一行,以減少屏幕空間的占用”,便是干凈的代碼。其實,在大多數(shù)時候,這樣的代碼不一定真的容易被理解。
在我看來,此類可解決某些專業(yè)難題的代碼,屬于“聰明的代碼”范疇。程序員們可以將其視為自己的獨門秘籍。它們往往被用來證明自己的編程技能,甚至被用作炫技之需。而對于干凈代碼的編寫,您應(yīng)該保持開放的心態(tài):代碼量的多少,并非代碼是否干凈的唯一衡量標準。除了實現(xiàn)代碼的功能,您的代碼還需要保持一定的可讀性。畢竟下一次閱讀該代碼段的很可能不是別人、正是你自己。畢竟,誰都不想給自己的將來刨坑埋雷。
5. 保持一致的編程風(fēng)格
每個程序員都有自己的編程風(fēng)格。在此,我并不想推薦或強求大家去遵從某種所謂最佳編程風(fēng)格。如果您習(xí)慣在行間使用大括號,如果您想在方法調(diào)用之前加上空格,如果您更喜歡使用制表符而不是空格的話,這些都可以。只不過,請保持此類用法的一致性。
同時,如果您打算將camelCaseNaming用作變量,那么就請不要將其與underscore_naming混為一談;如果您在某個地方使用了GetThisObject(),那么就請不要在其他地方采用FetchThatObject()。
此外,諸如Python和C#等編程語言,本身就帶有各種需要遵循的樣式規(guī)范,包括:絕不允許制表符和空格的混用等。
6. 選擇正確的架構(gòu)
您可以使用各種現(xiàn)成的范例和架構(gòu)來創(chuàng)建不同的項目。當(dāng)然,前提條件是,請選擇最適合的,并不是所謂最好的。例如,模型-視圖-控制器(Model-View-Controller,MVC)模式一直是Web開發(fā)領(lǐng)域最流行的架構(gòu)。畢竟,它不但有助于您保持代碼架構(gòu)的清晰合理,而且能夠使得后期的維護工作量最小。類似地,實體-組件-系統(tǒng)(Entity-Component-System,ECS)模式在游戲開發(fā)界也非常流行。畢竟它能夠協(xié)助實現(xiàn)模塊化的游戲數(shù)據(jù)和邏輯,使得維護更輕松,同時能夠生成更加易讀的代碼。
7. 掌握語言中的慣用法
我們所熟悉的Python、Java和JavaScript等不同的語言,都有著不同的編程思想與習(xí)慣。它們之間的差別或是巨大或是細微。例如:Python代碼會完全依賴緊湊代碼和鴨子類型(duck typing,基于“當(dāng)一只鳥走起來像鴨子、游起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子?!钡倪壿嫞覀儾槐仃P(guān)心對象是什么類型,只要關(guān)心它的動態(tài)行為即可。);而Java則更傾向于冗長和明確的代碼。同時,每一種語言都會鼓勵使用自己的慣用法,例如Python中的列表推導(dǎo)式。
與此同時,我們也要警惕所謂的“反面模式(anti-patterns)”。雖然那些由前人積累的、解決某些軟件開發(fā)特定問題的模式,會讓后輩獲益無窮;但是如果它們是一些狹隘的、僅對特定需求有效的模式的話,那么就應(yīng)該被避免繼續(xù)沿用。
8.學(xué)習(xí)大師寫的代碼
俗話說“有樣學(xué)樣”,如果您想編寫出干凈的代碼,那么您首先就要知道干凈的代碼應(yīng)該是什么樣子。而一些大師級前輩的程序作品,就能起到很好的示范作用,學(xué)習(xí)他們背后的編程思想、邏輯、以及代碼習(xí)慣。
顯然,您不可能隨便跑進微軟總部去“偷師”他們的項目,但是您可以通過Github上的各種??展示性項目??,隨時瀏覽到典型的行業(yè)應(yīng)用、以及各個開源項目的源文件代碼。畢竟,這也是開源項目的一個初衷:讓更多的人可以從中學(xué)習(xí)編程。通過這種社區(qū)互助的方式,您的代碼質(zhì)量會得以迅速提高。
9. 寫好注釋
“附上注釋”是編程世界中最古老的一項建議。不過在實際編程中,新手程序員一旦被建議要盡可能地留下注釋,他們就會樂此不疲。當(dāng)然,那些不必要的描述、甚至?xí)嘎睹舾行畔⒌倪^度注釋,也可能會帶來適得其反的效果。
我們該如何恰如其分地點到為止呢?我的一個經(jīng)驗法則是:注釋是被用來解釋為何需要這段代碼,而不是講解代碼實際能夠做什么。如果您的代碼寫得足夠干凈的話,其作用是不言自明的。例如:我們雖然可以用注釋來解釋“刪除它就會破壞A、B和C”的警告,但是在大多數(shù)情況下,我們應(yīng)該用注釋來揭示諸如:“使用此參數(shù),是因為X、Y和Z”之類,讀者無法從代碼中立即獲悉到的內(nèi)容。
10.重構(gòu)
正如編輯屬于文字寫作過程的一部分那樣,重構(gòu)也應(yīng)該是編程過程的一部分。其實,重構(gòu)能夠起到協(xié)助優(yōu)化代碼的作用,而不會影響其實際行為。同時,重構(gòu)也有利于提高代碼維護的效率。我在此方面的經(jīng)驗是:“不要僅僅注釋掉那些讓你覺得混亂、或者不夠好的代碼,請干脆重寫它們吧?!碑吘?,隨著時間的推移和經(jīng)驗的積累,您在回顧或維護整個軟件項目時,總能發(fā)現(xiàn)一些對于首次編寫不滿意、且值得重構(gòu)的代碼。
小結(jié)
正如我們學(xué)習(xí)如何寫出言簡意賅的說明文那樣,干凈的代碼本身并沒有絕對正確的參照標準。希望上文和您討論的十項技巧,能夠成為您避免寫出冗長且臃腫的代碼的實用參考。
譯者介紹
陳峻 (Julian Chen),51CTO社區(qū)編輯,具有十多年的IT項目實施經(jīng)驗,善于對內(nèi)外部資源與風(fēng)險實施管控,專注傳播網(wǎng)絡(luò)與信息安全知識與經(jīng)驗;持續(xù)以博文、專題和譯文等形式,分享前沿技術(shù)與新知;經(jīng)常以線上、線下等方式,開展信息安全類培訓(xùn)與授課。
原文標題:10 Tips for Writing Cleaner & Better Code,作者:JOEL LEE