匈牙利命名法

匈牙利命名法(Hungarian notation)是電腦程序設計中的一種變數命名規則,此命名法又可細分為:系統匈牙利命名法匈牙利應用命名法

匈牙利命名法具備語言獨立的特性,並且首次在BCPL語言中被大量使用。由於BCPL這種低級語言只有機器碼這一種數據內容,因此這種語言本身無法幫助程式設計師來記住變數的類型。匈牙利命名法通過明確每個變數的資料型別來解決這個問題。

在匈牙利命名法中,一個變數名由一個或多個小寫字母開始,這些字母有助於記憶變數的類型和用途,緊跟着的就是程序設計師選擇的任何名稱。這個後半部分的首字母可以大寫,以區別前面的類型指示字母(參見駝峰式大小寫)。

歷史

編輯

原始的匈牙利命名法,現在被稱為匈牙利應用命名法,由1972年至1981年在施樂帕洛阿爾托研究中心工作的-程序員查爾斯·西蒙尼發明。此人後來成了微軟的總設計師。

這種命名法其實是對於西蒙尼祖籍的一種諷刺。匈牙利人名和大多數其他歐洲人名相比是反過來的,即姓氏在名字的前面。舉個例子,英語化的名字「Charles Simonyi」在匈牙利語中原本是「Simonyi Károly」。同樣的,在匈牙利命名法中,類型名在實際變量名前,而不是像大多數歐洲的Smalltalk那樣,類型放在變量名後,例如aPoint和lastPoint。後者在西蒙尼任職於施樂帕洛阿爾托研究中心時期非常流行。這種命名法的靈感,可能是受波蘭表示法的啟發。

匈牙利命名法的英文是Hungarian notation,這個詞能讓許多人記住,因為難發音的輔音字串有點像部份東歐語言中,輔音豐富的拼寫方式,儘管實際上匈牙利語是屬於芬蘭-烏戈爾語族,而不像斯拉夫語族那樣元音豐富。舉例來說,零結束字符串的前綴"sz"實際上就是匈牙利字母表中的一個合體字母(參看德語中的ß)。

系統匈牙利命名法與匈牙利應用命名法

編輯

系統命名法與應用命名法的區別在於前綴的目的。

在系統匈牙利命名法中,前綴代表了變量的實際數據類型。例如:

  • lAccountNum:變量是一個長整數("l");
  • arru8NumberList:變量是一個無符號8位整型數組("arru8");
  • szName:變量是一個零結束字符串("sz"),這是西蒙尼最開始建議的前綴之一。

匈牙利應用命名法不表示實際數據類型,而是給出了變量目的的提示,或者說它代表了什麼。

  • rwPosition:變量代表一個("rw")。
  • usName:變量代表一個非安全字符串("us"),需要在使用前處理。
  • strName:變量代表一個包含名字的字符串("str")但是沒有指明這個字符串是如何實現的。

西蒙尼建議的大多數前綴都是自然語義的,但不是所有。下面幾個是來自原始論文的: [1]

  • pX是指向另一個X類型的指針,這包含非常少的語義信息。
  • d是一個前綴表示兩個值的區別,例如,dY可能代表一個圖形沿Y軸的距離,而一個僅僅叫做y的變量可能是一個絕對坐標。這完全是自然語義的。
  • sz是一個無結束或零結束的字符串。在C中,這包含一些語義信息,因為C語言的char*類型的變量不確定是一個指向單個字符的指針,還是一個字符數組,或是一個零結束字符串。
  • w標記一個變量是一個字。這基本上沒有包含什麼語義信息,因此可以被看作一種系統匈牙利命名法。
  • b標記了一個字節,和w對比可能有一些語義信息,因為C語言中,只有char型(以及signed/unsigned char)是一個字節長的,這些類型有時候被用來保存數值而字符。這個前綴可以明確某個變量保存的是字符還是數值。

由於這種命名法通常使用小寫字母開頭用來助記,但是並沒有對助記符本身作規定。有幾種被廣泛使用的習慣(見下面的示例),但是任意字母組合都可以被使用,只要它們在代碼主體中保持一致就可以了。

在使用匈牙利應用命名法的代碼中有時候也可能包含系統匈牙利命名法,即在描述被單獨以類型方式定義的變量時使用。

示例

編輯

每一項示例的代碼塊表示實際生產環境代碼中可能出現的命名,示例後的兩項解釋分別為含義以及這一示例的前綴是哪一個英文單詞的簡寫

  • bBusy布爾型 bool
  • cApples:項目計數 count
  • dwLightYears:雙(系統) doubleword
  • fBusy布爾型浮點型 false&true或float
  • nSize整型(系統)或計數(應用)nature
  • iSize整型(系統)或索引(應用)int
  • fpPrice浮點數 floatpoint
  • dbPi雙精度浮點數(系統) double
  • pFoo指針 point
  • rgStudents:數組或範圍 range
  • szLastName:零結束字符串 ß
  • u32Identifier:無符號32位整型(系統) unsigned32
  • stTime:時鐘結構 struct
  • fnFunction:函數名 function

對於指針和數組來說,它們實際上並不是數據類型,因此通常在助記符後面跟着實際元素的類型。

  • pszOwner:指向零結束字符串的指針
  • rgfpBalances浮點值的數組

儘管匈牙利命名法可以被應用在任何程序設計語言和環境中,由於微軟在C語言項目中,特別是在Microsoft Windows里的大量應用,使得匈牙利命名法的應用大量存在於和Windows相關的領域:

  • hwndFoo:窗口句柄 handle window
  • lpszBar:指向零結束字符串的長指針 longpointß

這種命名法又是在C++中被擴展而包含變量的作用域,由一個下劃線隔開:

  • g_nWheels:全局命名空間的成員,整型
  • m_nWheels:結構體/類成員,整型

匈牙利命名法的優點

編輯

(其中一些只適用於系統匈牙利命名法) 支持者聲稱匈牙利命名法的好處包括:[2]

  • 不需要集成開發環境的支持,從名字中就可以看出變量的類型
  • 擁有類似語義的多個變量可以在一個代碼塊中使用:dwWidth,iWidth,fWidth,dWidth
  • 變量名在僅僅知道他們的類型時可以被輕易記住
  • 可以使變量名更加一致
  • 決定一個變量名的時候可以更機械化,更快
  • 不合適的類型轉換和操作可以在閱讀代碼的時候被檢測出來,而不需要編譯器的檢測
  • 在那些數字被當作字符串處理的基於字符串的語言中非常有用(例如Tcl
  • 在匈牙利應用命名法中,變量名確保不會犯以下錯誤:
heightWindow = window.getWidth()
  • 在使用動態類型語言或完全無類型的語言編程時,關於類型的修飾可以更簡化。這種語言一般不包含類型修飾(或者可選),因此唯一可以看出哪些類型是被允許的只有名字本身、文檔以及通過閱讀代碼來明白它們在做什麼。在這些語言中,包含對於變量類型的指示可能會有助於程序員。就像上面提到的,匈牙利命名法擴展了這樣的語言(BCPL)。
  • 在包含許多全局對象的複雜程序中(VB/Delphi Forms),擁有一個基本的前綴命名法可以簡化在編輯器中查找組件的工作。按btn<Ctrl-Space>可以使編輯器彈出一個Button對象的列表。

匈牙利系統命名法的缺點

編輯

批評者認為:

  • 匈牙利命名法在編譯器做類型檢查時是多餘的。一個提供類型檢查的語言在確定一個變量與其類型一致時,比人眼僅僅檢查變量的用法與變量名一致要強大的多。
  • 一些現代的集成開發環境,如Visual Studio在需要時可以顯示變量類型,並且自動標記不匹配的類型。使用這種命名法完全沒有必要。
  • 向標識符添加類型標識導致標識符冗長;同時縱容相同主體名而不同類型的變量導致的歧義,開發人員無法從sWidthnWidthfWidth中了解這幾個Width的用法區別,更好的寫法可能是string inputint widthfloat zoomedWidth
  • 匈牙利命名法在被用作代表多個屬性的時候會造成困惑,如 a_crszkvc30LastNameCol:一個常量引用參數,保存了一個varchar(30)類型的數據庫LastName的內容,而這列又是這個表的主鍵的一部分。
  • 在代碼更改後可能造成不一致。如果一個變量的類型改變了,不是變量名的修飾與新的類型不一致,就是變量名必須被改變。
  • 由於變量名和類型捆綁在一起,因此不利於代碼的移植。一個典型的眾所周之的例子就是WPARAM類型,以及在許多Windows系統函數聲明中使用的wParam參數。它原本是一個16位的類型,但是在後來的操作系統中被改成了32位或64位,但仍保留原來的名字(它實際的基礎類型是UINT_PTR,即一個大小足夠保存一個指針的無符號整型)。
  • 大多數時候,看到一個變量就意味着知道了它的類型。但是,如果你不知道一個變量是幹什麼的,知道了它的類型也沒什麼幫助。

.NET Framework,微軟新的軟件開發平台,除了接口類型一般不適用匈牙利命名法。在.NET中,習慣在接口類型前放一個I(例如Windows Forms中的IButtonControl接口。).NET Framework指導方針建議程序員不要用匈牙利命名法,但是沒有指明不要用系統匈牙利命名法還是匈牙利應用命名法,或者是兩者都不要用。但在JETBrains公司旗下C#編輯器中,匈牙利命名法卻屬於建議使用的命名法(.net使用C#語言開發)[3]與此對比,Java的標準庫中連接口類型也不加前綴。[4]

注釋和參考

編輯
  1. ^ 「匈牙利命名法」(defined), 查爾斯·西蒙尼Microsoft Corp.,1999年11月,MSDN Library,MSDN.microsoft.com 網頁:匈牙利命名法,查爾斯·西蒙尼,Microsoft Corporation頁面存檔備份,存於網際網路檔案館).
  2. ^ 匈牙利命名法,查尔斯·西蒙尼,Microsoft Corporation. [2022-02-19]. (原始內容存檔於2006-06-10). 
  3. ^ .NET Framework Developer's Guide General Naming Conventions. [2008-06-08]. (原始內容存檔於2008-08-21). 
  4. ^ Code Conventions for the Java Programming Language. Sun Microsystems. 1999-04-20 [2008-04-10]. (原始內容存檔於2009-02-27). 

內部連結

編輯

外部連結

編輯