人们在现实世界中使用匈牙利命名规则吗?

34

学习约定是否值得,还是会对可读性和可维护性造成不利影响?

20个回答

59

考虑到大多数使用匈牙利命名法的人都遵循了其被误解的版本,我认为这样做相当无意义。

如果您想使用它的原始定义,那么可能更有意义,但除此之外,它大多数是语法糖。

如果您阅读了相关的维基百科文章,您会发现两种相互冲突的表示法:系统匈牙利命名法和应用程序匈牙利命名法。

原始的、好的定义是应用程序匈牙利命名法,但大多数人使用系统匈牙利命名法。

以变量前缀l表示长度,a表示面积,v表示体积为例。

使用这种命名法,以下表达式是有意义的:

int vBox = aBottom * lVerticalSide;

但是这个不行:

int aBottom = lSide1;

如果您混淆了前缀,它们应被视为等式的一部分,且 volume = area * length 对于一个长方体来说是可以的,但将长度值复制到面积变量中应该引起一些警惕。

不幸的是,另一种表示法不太有用,其中人们使用值类型作为变量名称的前缀,就像这样:

int iLength;
int iVolume;
int iArea;

有些人使用n代表数字,i代表整数,f代表浮点数,s代表字符串等。

原始的前缀旨在用于检测方程中的问题,但不知何故已经演变为使代码稍微易读一些,因为您不必去查找变量声明。随着今天智能编辑器的出现,您可以简单地将鼠标悬停在任何变量上以找到完整类型,而不仅仅是它的缩写,这种匈牙利标记法已经失去了很多意义。

但是,你应该自己决定。我只能说我两者都不用。


编辑 补充一下,虽然我不用匈牙利标记法,但我使用前缀,它是下划线。我将类的所有私有字段都加上下划线作为前缀,并按照属性的命名方式拼写它们的名称,即标题大小写,首字母大写。


我建议阅读http://blogs.msdn.com/larryosterman/archive/2004/06/22/162629.aspx。 - Anzurio
1
在今天的智能编辑器中,您可以将鼠标悬停在任何变量上以查找完整类型,而不仅仅是它的缩写,因此这种匈牙利命名法已经失去了很多意义。但如果考虑像pastebin.com、stackoverflow、任何带有代码标签的论坛甚至是基于Web的存储库浏览器呢?在这种情况下,我发现这些前缀与在糟糕的编辑器中一样有用。实际上,这是我仍然使用它的主要原因。 - mibollma
2
我仍然认为在变量前加上i表示整数是毫无意义的,变量的名称应该比单个i更具表现力。 - Lasse V. Karlsen
4
“I don't use neither” 的意思是你两个都用。 - Ally
typedef volume_t int; typedef area_t int; typedef length_t int; - vasilescur

22
匈牙利命名法在正确使用时非常有用,但不幸的是,它往往被滥用得更多。
阅读Joel Spolsky的文章Making Wrong Code Look Wrong,以获得适当的视角和理由。
基本上,基于类型的匈牙利记法,即在变量前缀中加入关于其类型的信息(例如,对象是否为字符串、句柄、int等),大多数情况下都是无用的,通常只会增加开销而几乎没有好处。不幸的是,这是大多数人熟悉的匈牙利记法。然而,匈牙利记法的初衷是为了添加关于变量所包含数据“种类”的信息。这使您可以将一种数据与其他不应混合在一起的数据进行分区,除非通过某些转换过程,可能允许它们混合在一起。例如,基于像素的坐标与其他单位的坐标,或者不安全的用户输入与来自安全源的数据等。
从这个角度看,如果您发现自己需要查找变量信息,则可能需要调整命名方案以包含该信息,这就是匈牙利约定的实质。
请注意,匈牙利记法的替代方法是使用更多的类来显示变量用途的意图,而不是在所有地方依赖原始类型。例如,与其为不安全的用户输入添加变量前缀,您可以为不安全的用户输入使用简单的字符串包装器类,并为安全数据使用单独的包装器类。在强类型语言中,这具有编译器执行分区的优点(即使在较弱类型的语言中,您通常也可以添加自己的tripwire代码),但会增加相当大的开销。

14

在涉及UI元素的情况下,我仍然使用匈牙利命名法,其中几个UI元素与特定对象/值相关联,例如:

lblFirstName用于标签对象,txtFirstName用于文本框。 即使这两个对象都需要关注/负责“FirstName”,我绝对不能将它们都命名为“FirstName”。

其他人是如何处理命名UI元素的?


5
我使用 firstNameLabel 和 firstNameTextBox。 - Mark Cidade

11

我认为匈牙利命名法是通向更可读代码的“路径”上有趣的脚注。如果使用得当,它比不使用要好。

虽然如此,我更倾向于放弃它,而不是这样:

int vBox = aBottom * lVerticalSide;

写下这个:

int boxVolume = bottomArea * verticalHeight;

现在是2008年,我们不再使用80个字符的固定宽度屏幕了!

此外,如果您正在编写比这还要长的变量名,那么您应该考虑重构为对象或函数。


8

这种命名方式对于像整数、字符串、布尔和双精度浮点等类型至少在我们公司中被广泛使用,但它是毫无意义的(并且会分散注意力)。

类似于 sValue, iCount, dAmountfAmount, 以及 bFlag 这样的东西随处可见。

曾经有一个很好的理由来采用这种约定。现在,它却成为了一种病态。


1
发生了什么?我如何开始成为癌症? - justjoe

6
我认为匈牙利命名法是绕过短期记忆容量的一种方法。据心理学家称,我们可以存储大约7个加减2个信息块。包括前缀添加的额外信息可以通过提供有关标识符含义的更多详细信息来帮助我们,即使没有其他上下文也能猜测变量的用途,而不必看到它的使用或声明方式。这可以通过应用面向对象的技术,例如封装单一责任原则来避免。
我不知道是否已经进行了实证研究。我假设当我们尝试理解具有超过九个实例变量的类或具有超过9个局部变量的方法时,所需的工作量会显著增加。

5
抱歉再问一下,使用"I"作为接口的前缀是否属于匈牙利命名法?如果是这样的话,那么很多人在实际工作中都在使用它。如果不是,请忽略此问题。

4

现在,范围比类型更重要,例如:

  • l表示本地变量
  • a表示参数
  • m表示成员变量
  • g表示全局变量
  • 等等

使用现代重构旧代码的技术,如果您更改了变量的类型,则替换符号是繁琐的。编译器会捕捉到类型更改,但通常无法捕捉到范围的不正确使用,合理的命名约定可以帮助解决这个问题。


4
当我看到匈牙利式命名讨论时,我很高兴看到人们努力思考如何使他们的代码更清晰,并使错误更加明显。这正是我们应该做的!但不要忘记,除了命名之外,您还有一些强大的工具可供使用。
抽取方法:如果您的方法变得太长,以至于变量声明已经滚动到屏幕顶部,请考虑将您的方法缩小。(如果您有太多的方法,请考虑一个新类。)
强类型:如果您发现正在将存储在整数变量中的邮政编码分配给鞋码整数变量,请考虑为邮政编码和鞋码分别创建一个类。然后您的bug将在编译时捕获,而不需要由人进行仔细检查。当我这样做时,我通常会发现我已经在我的代码中散布了一堆特定于邮政编码和鞋码的逻辑,然后我可以将它们移动到我的新类中。突然间,我的所有代码变得更加清晰、简单,并且受到某些类别的错误的保护。哇。
总之:是的,认真考虑如何在代码中使用名称来清晰地表达您的想法,但也要寻找其他强大的面向对象工具。

2

我并不严格遵循匈牙利命名法,但对于一些常见的自定义对象,我会适度使用它来帮助识别它们,并且我倾向于在GUI控件对象前加上它们所属的控件类型。例如,labelFirstName(标签名字)、textFirstName(文本框名字)和buttonSubmit(提交按钮)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接