劉易斯.卡萊爾(Lewis Carroll):
“當(dāng)我選用一個詞語時,”矮胖的人以傲慢的語調(diào)說道,“它表達(dá)的就是我要它表達(dá)的意思——不多也不少?!?/em>
一、為什么我們應(yīng)該恰當(dāng)?shù)孛?/h3>
名字表明了事物的身份,暗示了行為,更易讓人記住并識別。
恰當(dāng)?shù)孛馕吨私饷Q就可以了解對象。
二、我們對什么進(jìn)行命名
編寫代碼時,最常命名對象:
- 變量
- 函數(shù)
- 類型(class, enum, struct和typedef等)
- C++命名空間和Java包
- 宏
- 源文件
另外還包括: 狀態(tài)機(jī)的狀態(tài)、消息傳送協(xié)議的各個部分、數(shù)據(jù)庫的元素、應(yīng)用程序的可執(zhí)行文件等。
三、好的名稱具有那些特性
-
描述性的
盡量做到能望文生義。 -
技術(shù)上正確的
只使用字母、數(shù)字(不能作開頭)、特定字符(下劃線);不使用空白(空格、制表符、換行符等);C/C++中不使用str開頭帶一個小寫字母或以下劃線開頭的全局標(biāo)識符,以及帶命名空間std的標(biāo)識符; -
符合語言習(xí)慣
了解語言的習(xí)慣與約定,如標(biāo)準(zhǔn)庫使用一種約定,而Windows Win 32 API使用另一種約定。 -
恰當(dāng)
根據(jù)使用范圍,權(quán)衡名稱長度;注意格調(diào),避免使用blah或wibble等不嚴(yán)肅與foo或bar等古怪的名字。
四、命名細(xì)節(jié)
-
命令變量
(a).與現(xiàn)實世界對象相對應(yīng)的變量,通常使用名詞,如GUI應(yīng)用程序中變量可以用ok_button和main_window;甚至一些概念類的變量,也被賦予名詞形式,如elapsed_time或exchange_rate;
(b). 如果不是名詞,變量通常使用名詞化的動詞,例如count;對于邏輯變量的名稱,通常使用一個條件語句形式的名稱,例如is_positive, 這樣容易判斷其值是true還是false。
(c).為了說明變量是成員變量而不是局部變量或全局變量,常常使用:(1)以下畫線作為前綴;(2)以下畫線作后綴;(3)以m_作為前綴 三種匈牙利命名法,其中(1)有風(fēng)險,受到反對;(1)(2)形式不自然。
(d).一些程序員使用類似_ptr的后綴來修飾指針類型;使用類似_ref的后綴修飾引用類型,這種命名有些多余。
(e).小范圍內(nèi),可使用首字母縮略詞作變量名。
(f).將類型名與變量名區(qū)分開來,變量以小寫字母開頭,類型以大寫字母開頭。 -
命名函數(shù)
(a). 函數(shù)是一種行為,名字在邏輯上更應(yīng)該是動詞。
(b).有意義的函數(shù)名應(yīng)當(dāng)避免使用be、do和perform等只帶無用信息的詞語。
(c).始終從使用者的角度為函數(shù)命名。如果用戶只看到一個函數(shù)計算蘋果的個數(shù),就不要管函數(shù)內(nèi)部是如何具體實現(xiàn)的,命名這個函數(shù)為countApples()吧。 -
命名類型
在C語言中typedef命名、定義結(jié)構(gòu)體時,在Java、C++和其他面向?qū)ο笳Z言中創(chuàng)建新類型時,需要定義一個好的類型名。
(a).描述具有狀態(tài)的數(shù)據(jù)對象的類,使用名詞命名,如Bird;
(b).仿函數(shù)類,使用動詞命名;
(c).接口類,按接口功能命名;
(d).類型命名中,避免使用class、data、object、type等詞。 -
命名名字空間
C++和C#語言中的命名空間和Java語言的包,主要用于對構(gòu)造分組,還用于防止名稱的沖突。
(a).遵照語言的命名約定,如Java語言定義了一種像互聯(lián)網(wǎng)域名一樣嵌套的包名稱的層次結(jié)構(gòu);
(b).為命名空間選擇名稱時,選擇反映其內(nèi)容的邏輯關(guān)系的詞語。如果內(nèi)容是某個大型系統(tǒng)的一部分,選擇描述這個部分的名稱,如操作系統(tǒng)中的UI、filesystem或controls都是很好的名稱;
(c).不要采用暗示命名對象是一個集合的名稱——controls_group就是一個不好的名字。 -
命名宏
(a).遵循傳統(tǒng),宏的名稱使用全大寫字母,并且其他任何地方不再使用全大寫方式;
(b).宏是簡單的文本替換工具,應(yīng)該賦予在其他地方不再出現(xiàn)的獨(dú)特名字
(c).使用唯一的文件名或項目名作為宏名稱前綴是非常有用的,而且 PROJECTNAME_MY_MACRO比MY_MACRO更安全。 -
命名文件
一些語言對文件名要求嚴(yán)格——Java語言的源文件明必須與其包含的公共類型名相對應(yīng);另一方方面,C/C++對文件名無任何限制,但實際上源文件名對編碼難度是有實際影響的。
(a).為了使文件更易命名,每個文件應(yīng)該只包含單個概念單元,將代碼分到盡可能多的文件,同時還能減少文件間耦合和使項目結(jié)構(gòu)更清晰。
(b).為窗口定義界面的C/C++文件應(yīng)該命名為widget.h,而不是
widget_interface.h、widget_decls.h或其他類似的變體。按照慣例,使用匹配文件widget.c或widget.cpp來平衡widget.h吧。
(c).由于有些系統(tǒng)對大小寫敏感有些卻無法區(qū)分,為了避免出錯和考慮代碼移植性,采用不同文件名時應(yīng)當(dāng)不以大小寫不同作為區(qū)分,如果可以的話,文件名都使用小寫字母吧。
(d).項目采用混合語言編程,不要同時創(chuàng)建foo.c、foo.cpp、foo.java,這樣很混亂。
(e).為了避免文件同名,向文件名中添加一些路徑信息是一種有效手段。
五、命名的主要規(guī)則
要起一個好名字,做到如下幾點(diǎn):
- 保持前后一致
請選擇一種命名約定,并堅持使用
使用一致的命名約定,會易于開發(fā)、拓展和維護(hù)
利用上下文
(a).明白命名對象所處范圍,盡量把對象放在最小范圍中,選擇一個在該范圍內(nèi)對上下文有意義的名字;
(b).每個對象都有類型,但命名時不要再聲明類型信息。使用對你有利的名字
(a).通過使用公共的前綴,可按相似的名稱對對象分組;
(b).通過函數(shù)名稱中包含函數(shù)參數(shù)類型信息,暗示輸入?yún)?shù)或輸出參數(shù)。
六、總結(jié)
《詩篇》(psalms):
我將寄希望于你的名,這名本為美好
好的名稱不僅僅是審美上的需要,還傳達(dá)了關(guān)于代碼結(jié)構(gòu)信息,還是不可或缺的協(xié)助理解和維護(hù)的工具。
七、建議
不要創(chuàng)建如下特征的名稱:
-
含義模糊
首字母縮略詞和簡寫太隨意,單個字母太神秘 -
啰嗦
不要創(chuàng)建the_number_of_apples_before_I_started_eating這樣的變量名 -
不準(zhǔn)確或使人誤解
一個對象與列表無關(guān),就不要起widget_list之類的名
不要拼寫錯誤,如把ignoramus寫成ignoramous -
有歧義
不要使用有多種解釋的名稱 -
太做作
有趣的小縮寫、自作聰明的簡寫和對數(shù)字的解釋性使用都應(yīng)該避免。
對于經(jīng)驗少的人,internationalization的常見縮寫i18n是不夠清晰的。
八、內(nèi)容相關(guān)
匈牙利命名法
由于它的創(chuàng)始人程序員Charles Simonyi是匈牙利人和變量名看起來像是匈牙利語書寫,被稱為匈牙利命名法。最初從Microsoft公司傳出,后被發(fā)展成多種匈牙利命名法;現(xiàn)在是一種很受爭議的命名法,因為它的基本原則是:變量名=屬性+類型+對象描述,而在名稱中添加類型是一種冗余。
大寫字母約定
- 20世紀(jì)70年代早期在Smalktalk第一次使用的camelCase型,現(xiàn)在廣泛使用于Java語言庫(一般用于類成員名)和許多C++代碼庫;
- .NET、Windows API以及Java類名使用的ProperCase(PascalCase)型
- C++標(biāo)準(zhǔn)庫和GNU Foundation中使用的using_underscores型。
文件后綴
選擇后綴也是文件命名的一部分。Java的編譯系統(tǒng)要求文件名以.java作為結(jié)尾;但C/C++對后綴無要求。但我們應(yīng)當(dāng)使用普遍的約定,如C++實現(xiàn)文件采用.C、.cc、.cpp、.cxx和.c++常見后綴;頭文件使用.h或.hpp后綴。