我知道匈牙利语所指的内容 - 将有关变量,参数或类型的信息作为其名称的前缀.每个人似乎都狂热地反对它,尽管在某些情况下它似乎是一个好主意.如果我觉得有用的信息被传授,为什么我不能把它放在那里?
另请参阅:人们是否在现实世界中使用匈牙利命名惯例?
vusing adjHungarian nnotation vmakes nreading ncode adjdifficult.
大多数人以错误的方式使用匈牙利符号并且得到错误的结果.
阅读Joel Spolsky撰写的这篇优秀文章:错误的代码看错了.
简而言之,匈牙利表示法,你的变量名称前缀为type
(字符串)(匈牙利系统)是不好的,因为它是无用的.
匈牙利表示法,因为它的作者打算用变量名称作为前缀kind
(使用Joel的例子:安全字符串或不安全的字符串),因此所谓的Apps匈牙利语有其用途并且仍然很有价值.
乔尔错了,这就是原因.
他正在谈论的那个"应用程序"信息应该在类型系统中编码.您不应依赖于翻转变量名称以确保不将不安全数据传递给需要安全数据的函数.你应该把它变成一个类型错误,这样就不可能这样做了.任何不安全的数据都应该有一个标记为不安全的类型,因此它根本无法传递给安全函数.要从不安全转换为安全,应该要求使用某种消毒功能进行处理.
乔尔所说的"种类"的许多东西都不是种类; 事实上,它们是类型.
然而,大多数语言缺乏的是一种表达足以强制执行这些区别的类型系统.例如,如果C有一种"强类型定义"(其中typedef名称具有基类型的所有操作,但不能转换为它),那么很多这些问题就会消失.例如,如果您可以说,strong typedef std::string unsafe_string;
要引入一个unsafe_string
无法转换为std :: string 的新类型(因此可以参与重载解析等等),那么我们就不需要愚蠢的前缀.
因此,匈牙利人对于非类型事物的主要说法是错误的.它被用于类型信息.比传统的C型信息更丰富的类型信息,当然; 它的类型信息编码某种语义细节以指示对象的目的.但它仍然是类型信息,正确的解决方案一直是将其编码到类型系统中.将其编码到类型系统中是获得适当验证和规则执行的最佳方式.变量名称根本不会削减芥末.
换句话说,目标不应该是"让错误的代码看起来对开发者来说是错误的".它应该是"使错误的代码看起来错误的编译器 ".
我认为它大大混乱了源代码.
它也不会在强类型语言中获得太多收益.如果你做任何形式的类型不匹配tomfoolery,编译器会告诉你它.
匈牙利表示法仅在没有用户定义类型的语言中有意义.在现代函数或OO语言中,您可以将有关"类型"值的信息编码到数据类型或类中,而不是编码到变量名中.
几个答案参考了Joels的文章.但请注意,他的示例是在VBScript中,它不支持用户定义的类(至少很长一段时间).在具有用户定义类型的语言中,您可以通过创建HtmlEncodedString类型来解决相同的问题,然后让Write方法仅接受该类型.在静态类型语言中,编译器将捕获任何编码错误,在动态类型中您将获得运行时异常 - 但无论如何您都可以防止编写未编码的字符串.匈牙利语符号只是将程序员变成了一个人类型检查器,这种工作通常由软件更好地处理.
Joel区分"匈牙利系统"和"匈牙利应用程序",其中"匈牙利系统"编码内置类型,如int,float等,"apps hungarian"编码"种类",这是更高级别的元信息关于变量beyound机器类型,在OO或现代函数语言中,您可以创建用户定义的类型,因此在这种意义上类型和"种类"之间没有区别 - 两者都可以由类型系统表示 - 和"apps"匈牙利人和匈牙利的"系统"一样多余.
所以回答你的问题:系统匈牙利语只会在一种不安全的弱类型语言中有用,例如将一个浮点值赋给一个int变量会使系统崩溃.匈牙利的符号是在六十年代专门发明用于BCPL的,这是一种非常低级的语言,根本没有进行任何类型的检查.我不认为今天普遍使用的任何语言都有这个问题,但这种符号仍然存在于一种货物崇拜节目中.
如果您正在使用没有用户定义类型的语言(如旧版VBScript或早期版本的VB),匈牙利应用程序将有意义.也许早期版本的Perl和PHP也是如此.再次,在现代语言中使用它是纯粹的货物崇拜.
在任何其他语言中,匈牙利人只是丑陋,多余和脆弱.它重复了类型系统中已知的信息,你不应该重复自己.对描述此特定类型实例的意图的变量使用描述性名称.使用类型系统来编码变量的"种类"或"类"的不变量和元信息 - 即.类型.
Joels文章的一般观点 - 错误的代码看起来错了 - 是一个非常好的原则.然而,更好的防止错误的方法是 - 在可能的情况下 - 编译器自动检测错误的代码.
我总是在我的所有项目中使用匈牙利表示法.当我处理100个不同的标识符名称时,我发现它真的很有用.
例如,当我调用一个需要字符串的函数时,我可以输入's'并点击控制空间,我的IDE将向我显示前缀为's'的变量名称.
另一个优点是,当我为无符号和我签署的整数加上前缀时,我立即看到我在哪里以有潜在危险的方式混合有符号和无符号.
我记不起在一个巨大的75000行代码库中由于命名局部变量与该类的现有成员变量相同而导致错误(由我和其他人造成)的次数.从那时起,我总是在成员前面添加'm_'
这是一个品味和经验的问题.在你尝试之前不要敲它.
您忘记了包含此信息的首要原因.这与程序员无关.在你离开必须阅读这些东西的公司2到3年后,这与那些下路的人有关.
是的,IDE将为您快速识别类型.但是,当您阅读一些长批量的"业务规则"代码时,不必在每个变量上暂停以找出它是什么类型.当我看到诸如strUserID,intProduct或guiProductID之类的东西时,它可以更容易地"提升"时间.
我同意MS对他们的一些命名惯例走得太远了 - 我把它归类为"太多好事".
命名约定是好事,只要你坚持它们.我已经经历了足够多的旧代码,让我不断回头看看这么多类似命名的变量的定义,我推"骆驼套管"(因为它在之前的工作中被调用).现在我的工作有很多完全没有注释的经典ASP代码与VBScript,这是一个噩梦,试图解决问题.
在每个变量名称的开头处加密隐藏字符是不必要的,并且表明变量名本身不够具有描述性.大多数语言无论如何都需要声明变量类型,因此信息已经可用.
还有一种情况是,在维护期间,变量类型需要更改.示例:如果声明为"uint_16 u16foo"的变量需要成为64位无符号变量,则会发生以下两种情况之一:
您将通过并更改每个变量名称(确保不要使用相同名称的任何无关变量),或者
只需更改类型而不更改名称,这只会造成混淆.
乔尔斯波尔斯基写了一篇关于此事的好博文. http://www.joelonsoftware.com/articles/Wrong.html 基本上,它归结为如果你不记得,当一个体面的IDE会告诉你想要输入变量时,你的代码难以读取.此外,如果您使代码足够分隔,则不必记住将变量声明为三页的内容.
这些天不是范围更重要,例如
* l for local * a for argument * m for member * g for global * etc
使用现代技术重构旧代码,搜索和替换符号因为你改变了它的类型是繁琐的,编译器将捕获类型更改,但通常不会捕获不正确的范围使用,合理的命名约定在这里有所帮助.
你没有理由不正确使用匈牙利符号.这种不受欢迎的原因是长期反对误用匈牙利表示法,特别是在Windows API中.
在过去的糟糕日子里,在DOS之前存在类似于IDE的任何东西(可能你没有足够的可用内存来运行Windows下的编译器,所以你的开发是在DOS下完成的),你没有得到任何帮助将鼠标悬停在变量名称上.(假设你有一个鼠标.)你所要处理的是事件回调函数,其中所有内容都以16位int(WORD)或32位int(LONG WORD)的形式传递给你.然后,您必须将这些参数强制转换为给定事件类型的相应类型.实际上,大部分API实际上都是无类型的.
结果,一个带有如下参数名称的API:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
请注意,名称wParam和lParam虽然非常糟糕,但实际上并没有比命名param1和param2更糟糕.
更糟糕的是,Window 3.0/3.1有两种类型的指针,远近.因此,例如,内存管理函数LocalLock的返回值是PVOID,但GlobalLock的返回值是LPVOID(长度为'L').那可怕的符号,然后得到了扩展,从而一升翁p ointer字符串是前缀LP,从该是被人malloc分配的字符串区分开来.
毫无疑问,对这类事情有强烈抵制.
匈牙利表示法在没有编译时类型检查的语言中非常有用,因为它允许开发人员快速提醒自己如何使用特定变量.它对性能或行为没有任何作用.它应该提高代码的可读性,主要是品味和编码风格.由于这个原因,它受到许多开发人员的批评 - 并非每个人都有相同的大脑接线.
对于编译时类型检查语言,它几乎没用 - 向上滚动几行应该显示声明,从而显示类型.如果全局变量或代码块跨越多个屏幕,则会出现严重的设计和可重用性问题.因此,其中一个批评是匈牙利表示法允许开发人员设计糟糕并轻松逃脱.这可能是受到仇恨的原因之一.
另一方面,甚至可能存在编译时类型检查语言将受益于匈牙利表示法 - 虚拟指针或win32 API中的HANDLE的情况.这些混淆了实际的数据类型,在那里使用匈牙利表示法可能有一些优点.但是,如果可以在构建时知道数据类型,为什么不使用适当的数据类型.
一般来说,没有硬性理由不使用匈牙利表示法.这是喜欢,政策和编码风格的问题.
作为一名Python程序员,匈牙利表示法很快就会崩溃.在Python中,我不在乎某些东西是否为字符串 - 我关心它是否可以像字符串一样(即如果它有一个___str___()
返回字符串的方法).
例如,假设我们将foo作为整数,12
foo = 12
匈牙利表示法告诉我们,我们应该称之为iFoo或其他东西,以表示它是一个整数,以便稍后我们知道它是什么.除了在Python中,这不起作用,或者更确切地说,它没有意义.在Python中,我决定在使用它时我想要什么类型.我想要一个字符串吗?好吧,如果我做这样的事情:
print "The current value of foo is %s" % foo
注意%s
- 字符串.Foo不是字符串,但%
运算符将调用foo.___str___()
并使用结果(假设它存在).foo
仍然是一个整数,但如果我们想要一个字符串,我们将其视为一个字符串.如果我们想要一个浮点数,那么我们将它视为一个浮点数.在像Python这样的动态类型语言中,匈牙利表示法毫无意义,因为在你使用它之前它与什么类型无关,如果你需要一个特定的类型,那么只要确保将它强制转换为那种类型(例如float(foo)
)用它.
请注意,像PHP这样的动态语言没有这个好处 - PHP试图在后台基于一组几乎没有人记忆的模糊规则来做"正确的事",这通常会导致意外的灾难性混乱.在这种情况下,某种命名机制,如$files_count
或$file_name
,可以很方便.
在我看来,匈牙利表示法就像水蛭一样.也许在过去它们很有用,或者至少看起来很有用,但是现在它只是为了获得很多好处而进行的额外输入.
IDE应该传授有用的信息.当IDE不那么先进时,匈牙利人可能会做出某种意义(不是很多,但是某种意义上的).
作为一名工程师,而不是程序员,我立即接受了Joel关于Apps匈牙利语优点的文章:"使错误的代码看起来错了".我喜欢Apps Hungarian,因为它模仿工程,科学和数学如何使用子脚本和超脚本符号(如希腊字母,数学运算符等)表示方程式和公式.以牛顿万有引力定律为例:首先是标准数学符号,然后是Apps匈牙利语伪代码:
frcGravityEarthMars = G * massEarth * massMars / norm(posEarth - posMars)
在数学符号中,最突出的符号是那些代表存储在变量中的信息的类型:力,质量,位置向量等.下标是第二小提琴澄清:什么的位置?这正是Apps匈牙利人正在做的事情; 它告诉你样的存储在可变第一件事,然后进入细节-关于最接近的代码可以得到数学符号.
显然强类型可以解决Joel的论文中的安全与不安全的字符串示例,但是您不会为位置和速度向量定义单独的类型; 两者都是三号的双重数组,你可能对一个人做的任何事都可能适用于另一个.此外,连接位置和速度(制作状态向量)或取其点积非常有意义,但可能不会添加它们.如何打字允许前两个并禁止第二个,这样的系统将如何扩展到您可能想要保护的每个可能的操作?除非您愿意在打字系统中对所有数学和物理进行编码.
最重要的是,许多工程都是在像Matlab这样的弱类型高级语言中完成的,或者是像Fortran 77或Ada那样的旧版本.
因此,如果你有一个奇特的语言和IDE和匈牙利应用程序无法帮助你,那么就会忘记它 - 很多人显然都有.但对我而言,比使用弱动态或动态类型语言的新手程序员更糟糕的是,我可以使用Apps Hungarian更快地编写更好的代码.