匈牙利命名法的衰落和建议

首先要说明的是,此文只是一篇关于个人看法的随笔,不是paper。我也无意再次挑起这场旷日持久却已结束的争论。


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!

其他的类型都尽量不加前缀。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值