代碼那些事之命名 ——《可讀代碼的藝術》讀後感

一張圖引發的思考

085658825.jpg

1 食人植物


試想一下對於圖中植物我們如果正兒八經地說這是Corpse Flower(屍花),可能很難就一下子明白這是什麼並關聯相關意境,而食人植物一下子傳遞一些驚悚的場景,讓大家很警覺。因此命名就是傳遞信息和意境,好的命名就是要儘可能容易地傳遞準確的信息。同時命名需要考慮上下文,如果是做植物研究的,可能需要說學名是什麼,並且是哪個科哪個目。如果僅僅是參觀介紹,可能就需要側重生動、有意思了。同樣編程中也存在命名的問題。

問題出現的原因

編程當中命名是個辛苦活,但絕對是一個值得投入的辛苦活。好的命名可以極大提高代碼可讀性,甚至可以一定程度上彌補代碼結構、邏輯上的一些不足。結合我們目前的Code Review,其中命名問題的比例還是相對比較高,雖然沒有準確統計,但從摘要上分析差不多五個問題中就有一個命名問題,而且越是早期這塊問題越突出,甚至一部分Review感覺基本在糾結風格和命名問題,當然這不是什麼好事,但這類問題的突出不得不引起我們的反思。到底原因是什麼?總體上的原因可能有幾個:


命名需要用英文,可惜我們的母語不是英語,學校中的英語學習中基本應試,實際使用很少。這是很多人面對命名問題時的第一反應,而且感覺也是很容易從此獲得自我安慰。


重視度不夠。對於功能實現的急迫造成一種糾結命名就是浪費時間的錯覺,怎麼簡單怎麼來,不查字典、不穀歌,導致一些命名被簡化粗暴對待,諸如tempretget等一堆被用濫的詞不斷進入我們的視野。


缺乏編碼理論支持。命名難,所以可能不能很快搞定,也可能不能一次搞定,但我們經常遇到的問題是一直搞不定,而且是不斷在重複着原來的錯誤。除了重視的原因,還有一點就是我們接觸編程開始,就很少人告訴我們如何命名,知道的僅僅是不能數字打頭、不能用特殊符號等等,做到的僅是讓編譯器不抱怨而已。

幾點思考

翻了翻《可讀代碼的藝術》,同時結合自己的編程和Review實踐,有如下幾點思考:

選擇具體的詞

比如如下代碼的GetPage函數命名中Get就比較空泛,可能有幾種情況,比如從文件讀取、去遠處獲取、去數據庫查詢、或者就是簡單地從返回成員變量,如果一切都是Get就需要扒開具體實現纔可能確定到底用哪種方式。如果我們可以選擇更具體的詞,比如文件讀取用Read或者Load、遠程獲取用Fetch、數據庫查詢用Query、簡單返回成員變量時候採用Get,並且整個項目保持一致,可能僅僅看到名字就可以閃現出對應的場景。將信息塞進名字中的一部分就是選擇很具體、避免空泛的一些詞。


def GetPage(url):

...


多樣化選擇

英語的詞彙是很豐富多彩的,不同的詞可能有類似意思,同時也存在微妙的差別,因此希望命名選擇的時候可以多考慮一些方案,並且根據項目實際進行選擇,一旦選定了,就儘量保證一致性。同時必須牢記一點:清晰和準確比可愛更重要。一些常見單詞的替代詞事例參加下表:

單詞

替代詞

send

deliver, dispatch, announce, distribute, route

find

search, extract, locate, recover

start

launch, create, begin, open

make

create, set up, build, generate, compose, add, new

1 常見詞的替代詞

縮寫的困擾

在討論這點之前,我們首先要知道縮寫的目的:縮短單詞,便於記憶和拼寫,從而便於交流。在IDE沒有出現的時候,曾經出現過縮寫氾濫的年代,其影響延續至今。畢竟當時敲代碼是一件很苦力的事情,需要一個字母一個字母敲入,因此縮寫就可以極大緩解這塊的煩擾,同時也帶來了更大的煩擾:縮寫到極致後產生了記憶和理解的問題。因爲縮寫,大家需要更多記憶,同時誤解和衝突也更多。如今IDE普遍支持代碼自動補全,以至沒有這個功能都不好意思稱作IDE。因此過度縮寫已經沒有太多的意義,而合理地縮寫需要注意如下幾點:

1 避免單個字縮寫,畢竟給出a,不結合具體上下文很難猜出表示什麼,可能是表示啊america、也可能表示age,可能性多到僅只能表示這是個字母,給它加上任何具體含義可能都是危險的。


2 避免隨意縮寫,比如網絡連接的connection,可能目前比較常見的縮寫就是con,如果縮寫成connec就會感覺很奇怪,也很割裂。


3 避免縮寫下成了另一個意思。比如advertising,一旦縮寫成adv,就經常容易理解成advanced,畢竟很多設備的高級功能部分都是這樣縮寫的。同時類似的縮寫容易造成信息丟失以至於有多個還原的可能性。比如即使adv限定在廣告領域,那指的是Advertising(廣告)還是Advertiser(廣告主)呢?


4 建議建立部門和項目的“縮寫對照表”。試想下爲什麼銀行或者飛機航班的縮寫爲什麼可以保證全球統一,比如中國銀行的縮寫BOC是全球通用的,因爲有專門的機構負責這塊的規範,正式縮寫需要經過申請審批流程。編程中的縮寫如果有類似的流程,就能更好保證縮寫的規範一致,因此部門或者項目範圍內可以維護常用縮寫對照表,如需新的縮寫就可以在表中進行查詢、新增和發佈。

FLAG命名

Flag是一個令人又愛又恨的東西,代碼實現的時候是必須,但同時又經常濫用。Flag很方便,但一旦沒有控制住,數量一多很容易造成理解障礙。具體有幾個建議:


1 具體命名。最糟糕的就是都叫flag,不過很多FLAG變量的命名很容易造成歧義。比如“bool read_password = true;”,是需要讀取密碼,還是已經讀取密碼。在這種情況下need_password 或者user_is_authenticated會更好。


2是否進行了合理的狀態機分析。很簡單的一個例子,交通燈系統中大家經常根據當前需要不時添加isRedisGreenisYellow等等的標籤,可能使用時很便利,但是FLAG的排列組合會造成狀態數爆炸,其中很多組合是沒有意義的,比如(isRed && isGreen)。如果進行了合理的狀態分析,畫出狀態遷移圖,事情就會變得簡單很多,而且容易驗證很多。


3 是否使用不必要的否定。比如是否使用ssl命名時use_ssl要比disable_ssl好理解多,特別在試想下!use_ssl !disable_ssl的情況,否定的否定通常需要大腦更多的處理時間。因此爲了繞暈對手,詭辯的時候通常會巧妙地使用否定詞,比如“我不認爲這不是一個不好的方法”,不反覆思考可能不好弄清楚我是怎麼認爲的。代碼也是這樣,命名不合理,通常照成閱讀時候的卡殼和停頓。


bool disable_ssl = false;

VS

bool use_ssl = true;



4區分時態,主要體現在toishas,分別表示要做什麼、正在做什麼和已經做什麼,這些簡單的CET4英語知識對於命名同樣重要,合理區分可以讓代碼閱讀更流暢。如下代碼就說了一個故事:檢查當前狀態,看是否可以要啓動。如果要啓動,判斷是否正在運行,如果不是運行中就啓動,否則就什麼都不處理。最後根據是否判斷是否運行過,給出相應提示。其中toStartisRunninghasRun就體現了細微的差別。類似的還有canshould,分別表示能不能和應該不應該。


toStart = checkCondition();

if(toStart) {

if(!isRunning) {

start();

isRunning = true;

hasRun = true; // isRunning 不同,stop的時候不置成false

}

}

if(hasRun)

showTipMessage(“之前運行過”);


上述僅僅是示例,如果實際代碼這樣寫絕對是設計出現了問題,等着吐槽吧!

避免誤解。

被誤解是很受傷的一件事,但是我們的命名就嚐嚐別誤解,而且還常常是整個意思反過來了。因此在檢查名字的時候就是主動問下自己“別人對於這個名字是否有不同的解讀?”。比如如下代碼:


results = Database.all_objects.filter("year <= 2011")



其中,results會包含什麼呢?


year屬性<= 2011的對象?

year屬性不<= 2011的對象?


問題就出在filter上,可能是過濾掉、也可能是過濾出。建議就是如果要過濾出,select()會更好,如果要過濾掉,exclude()會更好。


Reserve for the future(爲將來預留)。

足球隊通常會特別慎重對待10號,基本是要努力等到那個絕對中場核心的人才可能賦予,否則提早給了後面更強大的中場加入的時候就難辦了,這不僅僅是號碼的問題,更多的是地位和認同的問題。編碼中也經常遇到這種情形,有些好詞想到就用,太揮霍了,比如EngineController等等,可能當時的場景下還是有些牽強但還是用了,到後來真正需要的時候就比較尷尬:調整傷筋動骨,不調整概念又不一致。排期開發中就遇到這個問題,初期的時候就早早將Order用掉了,當真正的訂單概念出現,需要用Order的時候已經很難調整了,直至現在還需要“忍”着。


幾點建議

當然做好命名需要長期刻意訓練,我個人也有一些小建議:

大量閱讀好代碼,學習一些精彩命名。

閱讀少量糟糕代碼,練習如何更好地命名。

Google幫忙,有些不確定的詞可以谷歌一下,看看搜索結果,判斷該詞是否常用。

閱讀代碼相關的書籍,比如《CleanCode》、《The Art of Readable Code》等等,形成一些對代碼的系統認識。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章