1.不太久远的历史
匈牙利命名法(Hungarian Notation)最初雏形来自Charles Simonyi的一篇论文,后来Charles Simonyi进入Microsoft并担任Microsoft Office开发的要职后得到完善,并在M$内部得到推广,最终演变为当时Windows开发的一种既定编码风格。
Hungarian Notation得到普及另一个人也功不可没(难辞其咎?),Charles Petzold在编写他那本极具影响力的Programming Windows(Windows程序设计)时,将Hungarian Notation作为标准编写了示例代码。而Hungarian Notation也随着这些示例代码影响了好几代Windows上的C程序员。
2.应用型和系统性匈牙利
据传Simonyi最初在M$内部推荐使用的命名法称为“应用型匈牙利”。最显著的特点是,它并不表示数据实际类型,而是给出变量所代表的意义。
例如:
rw/col 表示行和列
us 表示非安全型字符串,且在使用前需要处理
s 表示安全型字符串
大多数的前缀都来自于自然语言的单词缩写。
但是不巧的是,Simonyi在编写文档时,用了“type”这个单词。其他的工程师在翻阅文档时,误以为type表示的是数据类型。纵使Simonyi在文档中非常详细且准确地揭示了type所代表的意义,一切都为时已晚。
经过错误理解的系统型匈牙利在M$内部飞速流传开来,Simonyi也意识到自己对此已经无能为力,最终也只能将错就错。
ps:以上故事来自Joel编写的More Joel On Software(软件随想录)
于是,Hungarian Notation就变成了现在这个样子,每个名字前都用前缀来表示数据类型。
例如:
int -> n
long -> l
char -> ch
unsigned * -> u
pointer -> p
char*/wchar_t* -> psz
char[]/wchar_t[] -> sz
HANDLE -> h
DWORD -> dw
….
系统型匈牙利的好处是,你可以一眼从变量名中获取变量的类型,这在IDE尚不是很强大的时代具有一定的作用。
于是,慢慢地,Hungarian Notation开始占据Windows开发的主流风格,影响了一代又一代的C/Windows程序员
3.(系统型)匈牙利命名的缺点
Hungarian Notation最大的缺点是:(现在而言)几乎没有优点
虽然可以一眼从变量名中获取类型,但是在实际开发中,强大的IDE可以马上显示变量的具体定义信息,这使得命名法的作用大大降低。
更恐怖的是,进入C++之后,随着数据类型的增加和template的出现,使得为变量加入类型前缀变得不靠谱。
例如:
如果有一个变量的类型是 std::map<std::vector<std::wstring>, std::vector<std::wstring> >,那么确定它的类型前缀是一件很痛苦的事情,其程度不亚于你要陪你的GF/WIFE去逛街挑选衣服。
在猛烈的抨击和强烈的抗议下,M$终于在进入.NET大潮时发表宣言,表示不赞成继续使用Hungarian Notation
除了Word和Excel开发团队外(当年Simonyi直接负责的团队,也只有他们才知道事情的个中缘由),几乎所有人都感到如释重负,因为他们终于可以不用再理会这种操蛋的命名了。
4.个人观点
作为一个在Windows上用C/C++写程序,且受到Charles Petzold熏陶的程序员来说,使用Hungarian Notation为变量命名几乎成为了一种本能。
第一次反思是否应该摒弃这种命名法是在高三阅读Steve McConnell那本Code Complete之时,有意思的是,McConnell也曾经在M$工作过一段时间。
第二次反思是在不久前阅读Joel的More Joel On Software之时,并且这次反思最终促使我写下这篇文章,表达一些极具个人角度的观点。
我的观点很简单(我把它称作最小化原则的匈牙利命名法),分为两部分:
(1)控件的命名依旧采用Hungarian Notation,例如:
Button -> btn
Label -> lbl
TextBox -> txt
…
控件上的Hungarian Notation要靠谱的多
(2)变量命名上,仅保留以下前缀
global -> g_
member -> m_
static -> s_
pointer -> p
char*/wchar_t* -> psz
char[]/wchar_t[] ->sz
m_能够与非成员变量区分,而且基本可以避免变量重名而需要使用this指针的情况
g_和s_的意图无需多说,臭名昭著的global和static从来都需要特别对待
有人可能会对剩下的三个前缀颇有微词,我的理由是,这三个类型(其实只有两个)实在太特殊而且需要引起足够的注意,加前缀的意图则是告诉你:be careful! be careful!be careful!
其他的类型都尽量不加前缀。