我知道什么匈牙利是指给予的信息有关的变量、参数或类型作为前缀为它的名称。似乎每个人都被狂热地反对它,即使在某些情况下,这似乎是一个很好的想法。如果我觉得有用的信息正在传授,为什么我不应该把它就在那里,这是可用?

参见: 做人使用匈牙利的命名约定在现实世界?

有帮助吗?

解决方案

大多数人以错误的方式使用匈牙利表示法并且得到错误的结果。

阅读Joel Spolsky撰写的这篇优秀文章:使错误的代码看错了

简而言之,使用 type (字符串)(系统匈牙利语)为变量名称添加前缀的匈牙利表示法很糟糕,因为它没用。

匈牙利表示法,因为它是作者的意图,你的变量名称前缀为 kind (使用Joel的例子:安全字符串或不安全的字符串),因此所谓的Apps匈牙利语有其用途,仍然是是有价值的。

其他提示

vUsing adjHungarian nnotation vmakes nreading N-代码adjdifficult。

乔尔错了,这就是原因。

那个“应用程序”他正在谈论的信息应该在类型系统中进行编码。您不应依赖于翻转变量名称以确保不将不安全数据传递给需要安全数据的函数。您应该将其设置为类型错误,以便不可能这样做。任何不安全的数据都应该有一个标记为不安全的类型,因此它根本无法传递给安全函数。要从不安全转换为安全,应该要求使用某种消毒功能进行处理。

Joel谈到的很多事情都是“种类”。不是种类;事实上,它们是类型。

然而,大多数语言缺乏的是一种表达足以强制执行这些区别的类型系统。例如,如果C具有一种“强类型定义”,那么(其中typedef名称具有基类型的所有操作,但不能转换为它),那么很多这些问题都会消失。例如,如果你可以说, strong typedef std :: string unsafe_string; 引入一个无法转换为std :: string的新类型 unsafe_string (等等)可以参与重载决议等。)那么我们就不需要愚蠢的前缀了。

因此,匈牙利人对于非类型事物的主要说法是错误的。它被用于类型信息。比传统的C型信息更丰富的类型信息,当然;它的类型信息编码某种语义细节以指示对象的目的。但它仍然是类型信息,正确的解决方案一直是将其编码到类型系统中。将其编码到类型系统中是获得适当验证和规则执行的最佳方式。变量名称根本不会削减芥末。

换句话说,目标不应该是“使错误的代码看起来对开发者而言是错误的”。它应该“使错误的代码看起来错误到编译器”。

我认为它大大混乱了源代码。

使用强类型语言也不会带来太多好处。如果你做任何形式的类型不匹配tomfoolery,编译器会告诉你它。

匈牙利表示法仅适用于没有用户定义类型的语言。在现代功能或OO语言中,您将编码关于“种类”的信息。值的数据类型或类而不是变量名。

有几个答案参考 Joels文章。但请注意,他的示例是在VBScript中,它不支持用户定义的类(至少很长一段时间)。在具有用户定义类型的语言中,您可以通过创建HtmlEncodedString类型来解决相同的问题,然后让Write方法仅接受该类型。在静态类型语言中,编译器将捕获任何编码错误,在动态类型中您将获得运行时异常 - 但无论如何您都可以防止编写未编码的字符串。匈牙利语符号只是让程序员变成了一个人类型检查器,这种工作通常可以通过软件更好地处理。

乔尔区分“匈牙利系统”和“匈牙利系统”。和“匈牙利应用程序”,其中“匈牙利系统”和“匈牙利系统”编码内置类型,如int,float等,以及“apps hungarian”等。编码“种类”,这是关于变量beyound机器类型的更高级元信息。在OO或现代函数语言中,您可以创建用户定义类型,因此类型和“种类”之间没有区别。在这个意义上 - 两者都可以由类型系统表示 - 和“应用程序”。匈牙利语与“系统”一样多余。匈牙利语。

所以要回答你的问题:系统匈牙利语只适用于不安全的弱类型语言,例如:将float值赋给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位无符号,将发生两件事之一:

  1. 您将通过并更改每个变量名称(确保不要使用相同名称的任何无关变量),或
  2. 只需更改类型而不更改名称,这只会造成混淆。

Joel Spolsky撰写了一篇关于此事的好博文。 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')。那个可怕的符号然后被扩展,以便 l ong p ointer字符串以 lp 作为前缀,以区别于仅仅是malloc的字符串“d。

对这种事情产生强烈反对并不奇怪。

匈牙利表示法在没有编译时类型检查的语言中非常有用,因为它允许开发人员快速提醒自己如何使用特定变量。它对性能或行为没有任何作用。它应该提高代码的可读性,主要是品味和编码风格。由于这个原因,许多开发人员批评它 - 并非每个人都有相同的大脑接线。

对于编译时类型检查语言,它几乎没用 - 向上滚动几行应该显示声明,从而显示类型。如果全局变量或代码块跨越多个屏幕,则会出现严重的设计和可重用性问题。因此,其中一个批评是匈牙利表示法允许开发人员设计糟糕并轻松逃脱。这可能是受到仇恨的原因之一。

另一方面,甚至可能存在编译时类型检查语言将从win32中的匈牙利表示法 - void 指针或 HANDLE 中受益的情况API。这些混淆了实际的数据类型,在那里使用匈牙利表示法可能有一些优点。但是,如果可以在构建时知道数据类型,为什么不使用适当的数据类型。

一般来说,没有硬性理由不使用匈牙利表示法。这是一个喜欢,政策和编码风格的问题。

作为一名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这样的动态类型语言中,匈牙利表示法毫无意义,因为在你使用它之前,什么类型的东西并不重要,如果你需要特定的类型,那么只需确保将它强制转换为该类型(例如你使用它时浮动(foo)

请注意,像PHP这样的动态语言没有这个好处 - PHP试图在后台基于一组几乎没有人记忆的模糊规则来做“正确的事”,这通常会导致意外的灾难性混乱。在这种情况下,某种命名机制,如 $ files_count $ file_name ,可以很方便。

在我看来,匈牙利表示法就像水蛭一样。也许在过去它们很有用,或者至少看起来很有用,但是现在它只是为了获得很多好处而进行了大量的额外打字。

IDE应该传授有用的信息。当IDE不太先进时,匈牙利人可能会做出某种意义(不是很多,但是某种意义上的)。

Apps匈牙利语对我来说是希腊语 - 以一种很好的方式

作为一名工程师,而不是程序员,我立即接受了Joel关于Apps匈牙利语优点的文章:”使错误的代码看起来错误“。我喜欢Apps Hungarian,因为它模仿工程,科学和数学如何使用子脚本和超脚本符号表示方程式和公式(如希腊字母,数学运算符等)。举一个牛顿万有引力定律的一个特例:首先是标准数学符号,以及然后在Apps匈牙利语伪代码中:

frcGravityEarthMars = G * massEarth * massMars / norm(posEarth - posMars)

在数学符号中,最突出的符号是那些代表存储在变量中的信息的符号:力,质量,位置向量等。下标是第二小提琴澄清:位置什么?这正是Apps匈牙利人正在做的事情;它首先告诉你存储在变量中的事物的然后进入细节 - 关于最接近的代码可以得到数学符号。

显然强类型可以解决Joel的文章中的安全与不安全的字符串示例,但是你不会为位置和速度向量定义单独的类型;两者都是三号的双重数组,你可能对一个人做的任何事都可能适用于另一个。此外,连接位置和速度(制作状态向量)或取其点积非常有意义,但可能不会添加它们。如何打字允许前两个并禁止第二个,这样的系统将如何扩展到您可能想要保护的每个可能的操作?除非您愿意在打字系统中对所有数学和物理进行编码。

最重要的是,许多工程都是在像Matlab这样的弱类型高级语言中完成的,或者是像Fortran 77或Ada那样的旧版本。

所以,如果你有一种奇特的语言和IDE,那么匈牙利应用程序对你没有帮助就会忘记它 - 很多人显然都有。但对于我来说,比使用弱动态或动态类型语言的新手程序员更糟糕的是,我可以使用匈牙利应用程序更快地编写更好的代码。

大多数现代的IDE都是非常冗余和无用的,它们可以很好地使类型显而易见。

另外 - 对我来说 - 看到intI,strUserName等是很烦人的事情:))

  

如果我觉得有用的信息被传授,为什么我不能把它放在那里?

然后谁在乎别人怎么想?如果您觉得它很有用,请使用符号。

我的经验,这很糟糕,因为:

1 - 如果您需要更改变量的类型(例如,如果您需要将32位整数扩展为64位整数),则会中断所有代码;

2 - 这是无用的信息,因为类型已经在声明中,或者你使用动态语言,其中实际类型首先不应该那么重要。

此外,使用一种接受泛型编程的语言(即在编写函数时未确定某些变量类型的函数)或动态类型系统(即在编译时甚至不确定类型)时,如何你命名你的变量?大多数现代语言都支持其中一种,即使是受限制的形式。

Joel Spolsky的错误代码看错了中,他解释了每个人的想法匈牙利表示法(他称之为系统匈牙利语)并不是它真正的目的(他称之为Apps匈牙利语)。向下滚动到 I’ m Hungary 标题即可查看此讨论。

基本上,匈牙利系统毫无价值。它只是告诉您编译器和/或IDE将告诉您的相同内容。

应用程序匈牙利语告诉您该变量应该是什么意思,并且实际上可以有用。

我一直认为在正确的位置前缀或两个前缀不会受到伤害。我想如果我能传授一些有用的东西,比如“嘿,这是一个界面,不要依赖于特定的行为”。就在那里,就像在IEnumerable中一样,我应该这样做。评论可能比一两个字符符号更容易混乱。

如果控件列表显示在IDE中按字母顺序排列的下拉列表中,那么在窗体上命名控件(btnOK,txtLastName等)是一个很有用的约定。

我倾向于将匈牙利表示法与ASP.NET服务器控件一起使用,否则我发现很难弄清楚窗体上的控件是什么。

获取此代码段:

<asp:Label ID="lblFirstName" runat="server" Text="First Name" />
<asp:TextBox ID="txtFirstName" runat="server" />
<asp:RequiredFieldValidator ID="rfvFirstName" runat="server" ... />

如果某人能够更好地掌握那套没有匈牙利语的控制名称,我会很想搬到它。

Joel的文章很棒,但它似乎省略了一个重点:

匈牙利人将特定的“想法”(种类+标识符名称)设为唯一, 或者在代码库中几乎是独特的 - 甚至是一个非常大的代码库。

这对于代码维护来说是巨大的。 这意味着你可以使用好的单行文本搜索 (grep,findstr,'在所有文件中找到')找到每个提及这个'想法'。

当我们知道如何读取代码的IDE时,为什么这很重要? 因为他们还不是很擅长。这在小代码库中很难看到, 但是很明显 - 在评论中可能会提到“想法”时 XML文件,Perl脚本,以及源代码控制之外的地方(文档,维基, 错误数据库)。

即使在这里你也必须要小心 - 例如C / C ++宏中的令牌粘贴 可以隐藏标识符的提及。这种情况可以使用 编码约定,无论如何它们往往只会影响到少数几个标识符 代码库。

P.S。关于使用类型系统与匈牙利语的关系 - 最好同时使用两者。 如果编译器不能为您捕获它,您只需要错误的代码就会出错。有很多情况下编译器捕获它是不可行的。但是在可行的地方 - 是的,请这样做!

在考虑可行性时,请考虑拆分类型的负面影响。例如在C#中,用非内置类型包装'int'会产生巨大的后果。所以在某些情况下这是有道理的,但在所有情况下都没有。

揭穿的好处,匈牙利表示法

  • 它提供了一种有区别的变量。

如果类型为所有区别的一个值从另一个,那么它只能转换的一种类型到另一个。如果你有同样的价值正被转化成类型之间,机会是你应该这样做在一个功能专门用于转换。 (我已经看到hungarianed维生素b6残羹剩饭使用的字符串在所有他们的方法的参数,只是因为他们无法找出如何deserialize JSON对象,或者正确地理解如何声明或使用空类型.)如果你有两个变量区分只能通过匈牙利的前缀,他们不是一个转变,从一个到另一个,那么你需要详细说明你打算用它们。

  • 它使代码的更多的可读性。

我们发现,匈牙利表示法使人们懒惰与他们的变量名称。他们有什么区别,并且他们感到没有必要详细阐述,其目的。这是什么你会发现通常在匈牙利声明的代码对现代:sSQL与groupSelectSql(或者通常没有sSQL在所有,因为他们应该是使用的对象是放在通过早期开发人员。),sValue与formCollectionValue(或者通常没有sValue,因为他们碰巧是在视,并应使用模型结合特征),款式与publishSource,等等。

这不可能是可读性。我看到更多的sTemp1,sTemp2...sTempN从任何特定hungarianed维生素b6剩下的比其他人都相结合。

  • 它可以防止的错误。

这将是由于2号,这是错误的。

用主人的话来说:

http://www.joelonsoftware.com/articles/Wrong.html

像往常一样有趣的阅读。

提取物:

“有人在某处读过西蒙尼的论文,在那里他使用了”&#8220; type,&#8221;并且他认为类似于类,类似于类型系统,就像编译器所做的类型检查一样。他没有。他非常仔细地解释了他所说的“&#8220; type,&#8221;但它没有帮助。损坏已经完成。“

“但对于匈牙利应用程序仍然有很大的价值,因为它增加了代码中的搭配,使代码更易于读取,编写,调试和维护,最重要的是,它使错误的代码看起来不对。“

确保您在阅读Joel On Software之前有一些时间。 :)

几个原因:

  • 任何现代IDE会给你的可变式通过简单地徘徊在你的鼠标变量。
  • 大多数类型的名字是长(觉得 HttpClientRequestProvider)是合理使用作为前缀。
  • 本类型信息不携带 信息,这只是解释的变量声明,而不是概述 目的 变量(认为 myInteger页大小).

我不认为每个人都狂热地反对它。在没有静态类型的语言中,它非常有用。当它用于提供不属于该类型的信息时,我肯定更喜欢它。就像在C中一样, char * szName 表示该变量将引用一个以null结尾的字符串 - 这不是隐含在char *中的 - 当然,typedef也会有所帮助。

Joel有一篇很棒的文章,关于使用匈牙利语判断一个变量是否是HTML编码:

http://www.joelonsoftware.com/articles/Wrong.html

无论如何,当我习惯传授我已经知道的信息时,我倾向于不喜欢匈牙利语。

当然,当99%的程序员都同意某事时,就会出现问题。他们在这里同意的原因是因为他们中的大多数人从未正确使用匈牙利符号。

有关详细论据,我建议您参考我就该主题撰写的博客文章。

http://codingthriller.blogspot.com/2007/11 /rediscovering-hungarian-notation.html

我几乎开始编写关于匈牙利符号发明的时间,并且我第一次被迫在一个我讨厌它的项目中使用它。

过了一会儿,我意识到当它完成得当它确实有所帮助,这些天我喜欢它。

但是就像所有事情一样好,必须学会和理解,并且做得恰当需要时间。

匈牙利语符号被滥用,尤其是微软,导致前缀长于变量名称,并显示它非常严格,特别是当您更改类型(臭名昭着的Lparam / wparam,Win16中不同类型/大小,在Win32中相同。

因此,由于这种滥用行为以及M $的使用,它被视为毫无用处。

在我的工作中,我们用Java编写代码,但是创始人来自MFC世界,所以使用类似的代码样式(对齐的大括号,我喜欢这个!,大写到方法名称,我已经习惯了,像m_这样的前缀到类成员(字段),s_到静态成员等。)。

他们说所有变量都应该有一个显示其类型的前缀(例如,BufferedReader被命名为brData)。这显示为一个坏主意,因为类型可以改变,但名称不会跟随,或者编码器在使用这些前缀时不一致(我甚至看到aBuffer,theProxy等等。)。

就我个人而言,我选择了一些我认为有用的前缀,最重要的是b为布尔变量加前缀,因为它们是我允许语法的唯一选项,如 if(bVar)(no使用某些值的autocast为true或false)。 当我用C编码时,我使用了一个用malloc分配的变量的前缀,作为提示,它应该在以后释放。等

所以,基本上,我不会拒绝这个符号作为一个整体,而是采取了适合我需要的东西 当然,在为某些项目(工作,开源)做贡献时,我只是使用了这些惯例!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top