匈牙利命名法

匈牙利命名法（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"）但是沒有指明這個字串是如何實現的。

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

```
   [[Microsoft]] Corp.，1999年11月，MSDN Library，''MSDN.microsoft.com''
   网页:[https://msdn2.microsoft.com/en-us/library/aa260976(VS.60).aspx 匈牙利命名法，查尔斯·西蒙尼，Microsoft Corporation] .</ref>
```

- 不需要集成開發環境的支持，從名字中就可以看出變量的類型
- 擁有類似語義的多個變量可以在一個代碼塊中使用：dwWidth，iWidth，fWidth，dWidth
- 變量名在僅僅知道他們的類型時可以被輕易記住
- 可以使變量名更加一致
- 決定一個變量名的時候可以更機械化，更快
- 不合適的類型轉換和操作可以在閱讀代碼的時候被檢測出來，而不需要編譯器的檢測
- 在那些數字被當作字串處理的基於字串的語言中非常有用（例如Tcl）
- 在匈牙利應用命名法中，變量名確保不會犯以下錯誤：

heightWindow = window.getWidth

- 在使用動態類型語言或完全無類型的語言編程時，關於類型的修飾可以更簡化。這種語言一般不包含類型修飾（或者可選），因此唯一可以看出哪些類型是被允許的只有名字本身、文檔以及通過閱讀代碼來明白它們在做什麼。在這些語言中，包含對於變量類型的指示可能會有助於程式設計師。就像上面提到的，匈牙利命名法擴展了這樣的語言（BCPL）。
- 在包含許多全局對象的複雜程序中（VB/Delphi Forms），擁有一個基本的前綴命名法可以簡化在編輯器中查找組件的工作。按`btn<Ctrl-Space>`可以使編輯器彈出一個Button對象的列表。

## 匈牙利系統命名法的缺點

批評者認為：

- 匈牙利命名法在編譯器做類型檢查時是多餘的。一個提供類型檢查的語言在確定一個變量與其類型一致時，比人眼僅僅檢查變量的用法與變量名一致要強大的多。
- 一些現代的集成開發環境，如Visual Studio在需要時可以顯示變量類型，並且自動標記不匹配的類型。使用這種命名法完全沒有必要。
- 向標識符添加類型標識導致標識符冗長；同時縱容相同主體名而不同類型的變量導致的歧義，開發人員無法從`sWidth`、`nWidth`、`fWidth`中了解這幾個Width的用法區別，更好的寫法可能是`string input`、`int width`、`float 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#語言開發）與此對比，Java的標準庫中連接口類型也不加前綴。

## 內部連結

- 駝峰式大小寫
- 蛇形命名法

## 外部連結

- Meta-Programming: A Software Production Method Charles Simonyi, December 1976 (PhD Thesis)
- https://blogs.msdn.microsoft.com/larryosterman/2004/06/22/hugarian-notation-its-my-turn-now/ – Larry Osterman's WebLog
- Hungarian Notation (MSDN)
- HTML version of Doug Klunder's paper
- RVBA Naming Conventions
- Coding Style Conventions (MSDN)