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