命名規則 (程序設計)
程序設計的中命名規則(naming convention)是電腦程序設計的源代碼針對標識符的名稱字符串進行定義(即「命名」)而規定的一系列規則。通常是為了提高源代碼的易讀性、易認性、程序效率以及可維護性。命名規則根據各個程序語言的規格、內存大小等硬件制約、編輯器以及集成開發環境的功能等等會有各種制約。
制定命名規則的好處
挑戰
命名規則的選擇(及其執行的程度)通常是一個有爭議的問題,不同派系的人會覺得自己的觀點最好而其他人則是次等的。 而且,即使採用了已知且定義明確的命名規則,某些組織也可能無法始終如一地遵守這些規則,從而導致不一致和混亂。 如果命名規則在內部不一致、任意、難記,或者以其他方式顯得負擔大於好處,則命名規則會遇到更多的挑戰。
易讀性
精細挑選的標識符可以讓開發者和分析器更容易理解系統在做什麼,或者如何修改或將源代碼擴展運用到新需求上。 比如這句聲明
a = b * c;
在語義上是正確的,但是其目的卻不明顯。而相比較之下,寫成
weekly_pay = hours_worked * hourly_pay_rate;
則提示了源代碼的意圖和含義,至少對了解上下文的人來說更清晰。
典型要素
標識符長度
最基本的規則中包括對識別碼長度的規定。在某些情況下,上限是通過提供數值來設置的,而另一些情況下則使用了啟發式的方法或準則。
識別碼長度的規則是有爭議的,適當的長度應視具體情況而定。
要考慮的要點包括:
- 較短的識別碼可能比較好,因為它更容易鍵入。(儘管許多IDE和文本編輯器都提供了文本補全功能,這可以緩解這種情況)
- 太短的識別碼(例如a和i)很難使用自動搜索和替換工具來唯一區分。
- 在某些情況下,最好使用長識別碼,因為短識別碼無法包含足夠的語義信息。
- 縮寫可能令人困惑,應避免使用,但是太長的正式名稱也會因損害代碼可讀性而不受歡迎。
一些早期的鏈接器將變量名限制為6個字符或更少,以減少內存使用,這也是早期的程序會限制識別碼長度的原因之一。
大小寫和數字
一些命名規則對大小寫和數字的使用加以限制,比如只能用小寫字母,或者只能用大寫字母。有些場合雖然可以保留大小寫,但功能上並不賦予區別。
多個單詞組成的標識符
通常推薦使用「有實際含義的標識符」。如果單個單詞無法表述清晰則可以使用多個單詞,因此命名規則需要規定多個單詞如何連接。這樣還可以避免與各個程序語言使用的保留字衝突的問題。大多數語言的標識符不允許空格,而不加空格又會導致難以閱讀,因此需要制定空格的替代方式。
用符號區分
在字母數字的單詞裡使用制定的區分字符進行連接,常用有 連字符 ("-") 、下劃線 ("_"),比如兩個單詞的 "two words
" 可寫成 "two-words
" 或者 "two_words
"。連字符非常常用,包括 COBOL (1959), Forth (1970)以及 Lisp (1958),而在 Unix 命令和包里也很常見。在 CSS 中也是如此。[1] 這種做法沒有一個通稱,有人叫 lisp-case 或者 COBOL-CASE (是為了與 Pascal case 相區別),或者叫 kebab-case、brochette-case等等。[2][3][4][5] 但至少是從 2012 年之後,[6] kebab-case 這個叫法越來越流行。[7][8]
與此相比,在 FORTRAN/ALGOL 語言的傳統中,特別是 C語言 和 Pascal語言 家族,曾使用連接號用於 中綴表示法 的減法運算符,而且也不希望前後加空格, 因此就無法用此方法來命名標識符。而用下劃線連接小寫字母的方法則在 C 家族(包括 Python)里都很常見,比如《The C Programming Language》(1978)即可見到,通稱為蛇形命名法(snake_case)。而像 UPPER_CASE 這樣用下劃線連接大寫字母的做法則常見於 C預處理器 里的宏,所以被稱為 MACRO_CASE;以及 Unix 中的 環境變量,比如 bash 里的BASH_VERSION。有時會被幽默地稱作 SCREAMING_SNAKE_CASE。
用大小寫區分
另一種做法就是在單詞組合成一個字符串的中間使用大寫字母,被稱作駝峰式大小寫(camelCase)或者「Pascal case」等等,也就把 "two words
" 寫成 "twoWords
" 或者 "TwoWords
"。這種方式常見於 Pascal、Java, C#以及Visual Basic。而對於首字母縮寫詞的處理方式仍會不一樣。(比如 XMLHttpRequest
中的 "XML" 和 "HTTP),有些會用小寫以易於打字和閱讀(比如 XmlHttpRequest
)而有些會保持大寫以保證準確性(如寫成XMLHTTPRequest
)。
元數據與混合命名規則
有一些命名規則不僅是特定程序、某個特定項目和問題的規則和需求,還通過軟件架構稱為對其下層的程序語言和跨項目的一個方法論框架。
匈牙利命名法
最著名的命名規則包括匈牙利命名法,具體包括「系統匈牙利命名法」和「匈牙利應用命名法」[9]。比如變量 szName 中的前綴 "sz" 代表其是一個零結束字符串。
各種語言的命名規則
C 和 C++
原則上使用小寫字母。在C標準庫里,最常用的做法是使用縮寫名稱,如用於測試是字符是否為字母數字的函數寫成 isalnum
,而C++的標準庫了則常用下劃線作為單詞分隔符(如 out_of_range
)。而C預處理的標識符則只用大寫字母和下劃線(因為很多程序語言都用全大寫標示常量),帶兩個下劃線或者以下劃線和一個大寫字母打頭的名字都預留給編譯器,因此都不能用(比如 __reserved
或者 _Reserved
)。[10][11] 雖然這表面上與 stropping 類似,但語義上完全不同,因為下劃線是標識符的值的一部分,而不是 stropping 那樣只是表示引用: __foo
的值是 __foo
(被預留),而不是 foo
(但是在一個不同的命名空間)。
C#
C# 命名規則基本上遵循微軟的 .NET 語言的規範。[12] (詳見後續 .NET 章節),但 C# 編譯器並不強制使用命名規則。微軟推薦僅用 PascalCase
和 camelCase,後者僅用於方法參數和本地方法變量名(包括本地方法 const
值)。一個不適用 PascalCase 的特例,是標識符開頭的雙字母首字母縮寫詞,這時兩個字母都要大寫,如 IOStream
,但這不適用於更長的首字母縮寫詞裡,如 XmlStream
。該規範還推薦 interface
的名字要用 PascalCase
並在開頭加一個大寫字母 I
,如 IEnumerable
。
微軟規範對 filed 命名僅限於 static
, public
和 protected
,並明確指出如果非靜態、或者有其他可接入層級(比如 internal
和 private
)則不在規範範圍之內。[13] 最常用的做法是所有 filed 都使用 PascalCase ,而只有 private
(且 const
或 static
),這些例外使用 camelCase 並添加一個下劃線,如 _totalCount
。
標識符可以添加 @ 符號卻不改變含義。也就是說 factor
和 @factor
均指同一個對象。在規則上,這一前綴僅用於當該標識符是預留關鍵詞(比如 for
和 while
,不加前綴就不能當成標識符),或者是有上下文關鍵詞(比如 from
和 where
,並不嚴格要求有前綴,至少不是所有聲明都要求,比如儘管 dynamic dynamic;
聲明有效,但這會被看作 dynamic @dynamic;
以讓讀者立即知道後者是一個變量名)。
Java
Java的命名規則是由多個社區制定的,包括昇陽電腦[14]、網景[15]、AmbySoft[16] 等等。下述採用昇陽電腦制定規則的例子, 比如 "CamelCase",不用空格直接連起來,每個單詞首字母大寫,比如 "CamelCase".
標識符類型 | 命名規則 | 舉例 |
---|---|---|
類 | 應該為名詞,用 UpperCamelCase ,即每個詞首字母大寫,拼寫完整,不用簡稱、縮寫(除非縮寫比全名更常用,如 URL 或 HTML)
|
|
方法 | 應該用動詞,用 lowerCamelCase ,或者用一個小寫動詞打頭的詞組,即首字母小寫,之後的每個詞首字母大寫。
|
|
變量 | 本地變量、即時變量和類變量也用 lowerCamelCase 。變量名不能以下劃線 (_ ) 或美元符號 ($ ) 打頭,這與其他編碼規則里採用下劃線追尾所有即時變量前綴的規定不同。
變量名稱應該簡潔易懂,便於記憶。儘量避免使用單字母,除非一些臨時變量。臨時變量常用名,整數型一般用 i, j, k, m 或 n;而字符型則用 c, d 或 e。 |
|
常數 | 用大寫字母,並用下劃線隔開。 可以用數字,但不能為首字符。 |
|
縮寫詞長達三個字母及其以上時用 CamelCase 而不是全大寫(比如 parseDbmXmlFromIPAddress
不寫作parseDBMXMLFromIPAddress
),這個規則可以適用至兩個字母詞 (如 parseDbmXmlFromIpAddress
).
JavaScript
JavaScript 的內置庫採用與 Java 同樣的命名規則。數據類型和建造函數使用 upper camel case (RegExp, TypeError, XMLHttpRequest, DOMObject) 而方法使用 lower camel case (getElementById, getElementsByTagNameNS, createCDATASection)。為了保持統一,大部分 JavaScript 開發者都遵循此命名規則。[17]
.NET
微軟公司 Microsoft .NET 推薦大部分標識符都用 UpperCamelCase
(而參數和變量推薦用 lowerCamelCase) 這是所有 .NET 語言的通則,[18] 微軟還推薦無需使用(匈牙利命名法那樣的)前綴提示,[19] 而是推薦在後面加上基礎類名,如寫成 LoginButton
而不是 BtnLogin
。[20]
Objective-C
Objective-C 使用源於 Smalltalk 的代碼方式。通用的變量、函數的頂層條目,包括類、協議都用 UpperCamelCase 並用一個短的全大寫前綴標示命名空間,比如 NSString
, UIAppDelegate
, NSApp
以及 CGRectMake
。常量可以有小寫字母k打頭的前綴如 kCFBooleanTrue
。
即時對象的變量使用帶下劃線的 lowerCamelCase,如 _delegate
and _tableView
。Method 名使用多個 lowerCamelCase 並用冒號區分如 application:didFinishLaunchingWithOptions:
, stringWithFormat:
and isRunning
.
Perl
Perl 繼承了C中的一些規則。本地範圍內的變量和子程序名用小寫字母加下劃線。包變量採用 title case,聲明的常量全大寫。包的名字採用 camel case 但 pragmata 例外,比如 strict
和 mro
用小寫。
[21]
[22]
PHP
PHP 推薦方式寫在 PSR-1 (PHP Standard Recommendation 1) 和 PSR-12 中。[23] 根據 PSR-1,類的名字要用 PascalCase, 類的常數要用 MACRO_CASE,而 method 名要用 camelCase。[24]
Python and Ruby
Python和Ruby都推薦類名使用 UpperCamelCase
,常數名使用 CAPITALIZED_WITH_UNDERSCORES
,其他名字用 lowercase_separated_by_underscores
。
Swift
Swift語言的命名規則根據不同發布有所變化。但是隨着 Swift 3.0 的重大更新後,其命名規則規範更為清晰,希望能對所有第三方的 API 命名和聲明規則進行標準化[25]。變量、函數聲明的命名規則還是以 lowerCamelCase
為基礎。常數通常使用 enum 類型定義。類和其他類型的聲明採用 UpperCamelCase
。
參見
注釋
- ^ CSS reference. Mozilla Developer Network. [2016-06-18]. (原始內容存檔於2021-01-13).
- ^ StackOverflow – What's the name for snake_case with dashes?. [2020-05-21]. (原始內容存檔於2014-12-26).
- ^ Programmers – If this is camelCase what-is-this?. [2020-05-21]. (原始內容存檔於2016-08-07).
- ^ Camel_SNAKE-kebab. September 2019 [2020-05-21]. (原始內容存檔於2018-06-11).
- ^ UnderscoreVersusCapitalAndLowerCaseVariableNaming. [2020-05-21]. (原始內容存檔於2015-10-02).
- ^ jwfearn. Revisions to jwfearn's answer to What's the name for dash-separated case?. 5 September 2012 [2020-05-21]. (原始內容存檔於2017-05-10).
- ^ Living Clojure (2015), by Carin Meier, p. 91 (頁面存檔備份,存於網際網路檔案館)
- ^ lodash: kebabCase. [2020-05-21]. (原始內容存檔於2021-01-08).
- ^ Making Wrong Code Look Wrong. 11 May 2005 [2020-05-21]. (原始內容存檔於2016-11-22).
- ^ ISO/IEC 9899:1999 Programming languages – C. ISO. [2020-05-21]. (原始內容存檔於2017-01-29).
- ^ ISO/IEC 14882:2011 Information technology – Programming languages – C++. ISO. [2020-05-21]. (原始內容存檔於2013-05-17).
- ^ Naming Guidelines. Microsoft. [2020-05-21]. (原始內容存檔於2020-11-17).
- ^ Names of Type Members. Microsoft. [2020-05-21]. (原始內容存檔於2020-11-14).
- ^ "Code Conventions for the Java Programming Language", Section 9: "Naming Conventions" (頁面存檔備份,存於網際網路檔案館)
- ^ "NETSCAPE'S SOFTWARE CODING STANDARDS GUIDE FOR JAVA",Collab Software Coding Standards Guide for Java (頁面存檔備份,存於網際網路檔案館)
- ^ "AmbySoft Inc. Coding Standards for Java v17.01d". [2020-05-21]. (原始內容存檔於2020-08-20).
- ^ Morelli, Brandon. 5 JavaScript Style Guides – Including AirBnB, GitHub, & Google. codeburst.io. 17 November 2017 [17 August 2018]. (原始內容存檔於2017-11-12).
- ^ Microsoft .NET Framework Capitalization Styles. [2020-05-21]. (原始內容存檔於2017-03-24).
- ^ .NET Framework Developer's Guide – General Naming Conventions. [2020-05-21]. (原始內容存檔於2016-03-03).
- ^ [Framework Design Guidelines, Krzysztof Cwalina, Brad Abrams Page 62]
- ^ Perl style guide. [2020-05-21]. (原始內容存檔於2013-06-26).
- ^ perlmodlib – constructing new Perl modules and finding existing ones. [2020-05-21]. (原始內容存檔於2020-06-28).
- ^ PHP standards recommendations. [2020-05-21]. (原始內容存檔於2020-11-12).
- ^ 存档副本. [2020-05-21]. (原始內容存檔於2019-03-31).
- ^ swift.org API Design Guidelines. [2020-05-21]. (原始內容存檔於2021-01-12).
外部連結
- American Name Society(頁面存檔備份,存於網際網路檔案館) – promotes onomastics, the study of names and naming practices, both in the United States and abroad.
- coding-guidelines.com has a pdf(頁面存檔備份,存於網際網路檔案館) that uses linguistics and psychology to attempt a cost/benefit analysis of identifier naming issues