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

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

Do people use the Hungarian Naming Conventions in the real world?

它是否值得学习这个约定,或者它是对可读性和可维护性的一种损害?


考虑到大多数使用匈牙利符号的人都遵循被误解的版本,我认为这是非常没有意义的。

如果您想使用它的原始定义,它可能更有意义,但除此之外,它主要是句法上的糖分。

如果你阅读维基百科关于这个主题的文章,你会发现两个相互冲突的符号,系统匈牙利符号和应用匈牙利符号。

最初的,好的,定义是应用匈牙利符号,但大多数人使用系统匈牙利符号。

作为这两种方法的一个例子,考虑在变量前加l表示长度,a表示面积,v表示体积。

有了这样的符号,下面的表达式就有意义了:

1
int vBox = aBottom * lVerticalSide;

但这并不是:

1
int aBottom = lSide1;

如果要混合前缀,它们将被视为公式的一部分,对于一个框来说,volume=a re a*length是可以的,但是将length值复制到一个area变量中应该会引发一些红旗。

不幸的是,另一种表示法不太有用,人们在变量名前面加上值的类型,如下所示:

1
2
3
int iLength;
int iVolume;
int iArea;

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

最初的前缀是用来发现方程中的问题的,但是由于不必查找变量声明,它以某种方式使代码变得更容易阅读。在今天的智能编辑器中,您只需将鼠标悬停在任何变量上即可找到完整的类型,而不仅仅是它的缩写,这种类型的匈牙利符号已经失去了很多意义。

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

编辑只是为了添加一个简短的通知,虽然我不使用匈牙利符号,但我确实使用了前缀,它是下划线。我在类的所有私有字段前面加上前缀,否则像拼写属性一样拼写它们的名称,用第一个字母大写的标题大小写。


匈牙利命名约定在正确使用时很有用,不幸的是,它经常被误用。

阅读JoelSpolsky的文章,让错误的代码看起来错误,以获得适当的视角和理由。

本质上,基于类型的匈牙利表示法,其中变量的前缀是关于其类型的信息(例如,对象是否是字符串、句柄、int等),这基本上是无用的,通常只会增加开销,但好处很小。遗憾的是,这是大多数人都熟悉的匈牙利符号。然而,匈牙利表示法的目的是增加变量所包含的"类型"数据的信息。这允许您从其他类型的数据中分离出各种类型的数据,这些数据不应该被混合在一起,除非可能通过某种转换过程。例如,基于像素的坐标与其他单位的坐标,或不安全的用户输入与来自安全源的数据,等等。

以这种方式来看,如果您发现自己正在快速浏览代码以查找变量的信息,那么您可能需要调整命名方案以包含该信息,这就是匈牙利惯例的本质。

注意,匈牙利表示法的一个替代方法是使用更多的类来显示变量使用的意图,而不是在任何地方都依赖基元类型。例如,您可以为不安全的用户输入使用简单的字符串包装类,而不是为不安全的用户输入使用变量前缀,为安全数据使用单独的包装类。在强类型语言中,这有一个优点,即编译器强制执行分区(即使在强类型较少的语言中,通常也可以添加自己的tripwire代码),但会增加不小的开销。


当涉及到UI元素时,我仍然使用匈牙利符号,其中几个UI元素与特定的对象/值相关,例如,

标签对象的lblFirstName,文本框的txtFirstName。我绝对不能把它们都称为"名字",即使这是两个对象的关注点/责任。

其他人如何命名UI元素?


这是毫无意义的(和分散注意力),但在我的公司中使用的比较多,至少对于像int、strings、booleans和double这样的类型是这样的。

sValueiCountdAmountfAmountbFlag之类的东西到处都是。

从前,有一个很好的理由举行这一公约。现在,它是一种癌症。


我认为匈牙利符号是一个有趣的脚注沿着"路径"到更可读的代码,如果做得好,最好不要这样做。

尽管如此,我还是宁愿放弃它,而不是这样:

1
int vBox = aBottom * lVerticalSide;

写这个:

1
int boxVolume = bottomArea * verticalHeight;

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

此外,如果编写的变量名比所编写的变量名长得多,那么无论如何都应该考虑重构为对象或函数。


很抱歉跟进一个问题,但是用"i"前缀的接口是否符合匈牙利符号?如果是这样的话,那么是的,很多人在现实世界中使用它。如果没有,忽略这个。


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

  • L表示本地
  • A代表辩论
  • M代表成员
  • G代表全球

用现代技术重构旧代码,搜索和替换一个符号,因为你改变了它的类型是冗长的,编译器会捕捉到类型的变化,但往往不会捕捉到不正确的使用范围,明智的命名约定有助于这里。


我认为匈牙利符号是一种规避我们短期记忆能力的方法。根据心理学家的说法,我们可以存储大约7个正负2块信息。通过包含前缀添加的额外信息可以帮助我们提供关于标识符含义的更多详细信息,即使没有其他上下文。换句话说,我们可以猜测变量的用途,而不必看它是如何使用或声明的。这可以通过应用诸如封装和单一责任原则等OO技术来避免。

我不知道这是否是经验性的研究。我假设当我们试图理解具有9个以上实例变量的类或具有9个以上局部变量的方法时,工作量会显著增加。


当我看到匈牙利语的讨论时,我很高兴看到人们努力思考如何使代码更清晰,以及如何使错误更明显。这正是我们应该做的!

但别忘了,除了命名之外,您还有一些强大的工具可供使用。

提取方法如果方法的时间太长,以至于变量声明已从屏幕顶部滚动出来,请考虑将方法变小。(如果方法太多,请考虑新类。)

强类型如果您发现要将存储在整型变量中的邮政编码分配给鞋码整型变量,请考虑为邮政编码创建一个类,为鞋码创建一个类。然后,您的bug将在编译时被捕获,而不需要人工仔细检查。当我这样做的时候,我通常会发现一堆特定于邮政编码和鞋码的逻辑,这些逻辑我已经围绕着我的代码展开了,然后我就可以进入我的新课程了。突然间,我所有的代码变得更清晰、更简单,并且不受某些类型的错误的影响。真的。

总而言之:是的,请仔细考虑如何在代码中使用名称来清晰地表达您的想法,同时还要注意您可以调用的其他强大的OO工具。


我不使用非常严格的匈牙利表示法,但我发现自己使用它时,会省去一些常见的自定义对象来帮助识别它们,而且我倾向于在GUI控件对象前面加上它们的控件类型。例如,labelfirstname、textffirstname和buttonsubmit。


我对按钮、文本框和标签等UI元素使用匈牙利语命名。主要优点是在Visual Studio IntelliSense弹出窗口中进行分组。如果我想访问我的标签,我只需开始输入lbl…。而且Visual Studio会建议我所有的标签,nicley组合在一起。

但是,在做了越来越多的Silverlight和WPF工作之后,利用数据绑定,我甚至不再命名所有控件,因为我不必从代码背后引用它们(因为实际上不再有任何代码隐藏;)


The original prefix was meant to be
used to spot problems in equations,
but has somehow devolved into making
the code slightly easier to read since
you don't have to go look for the
variable declaration. With todays
smart editors where you can simply
hover over any variable to find the
full type, and not just an
abbreviation for it, this type of
hungarian notation has lost a lot of
its meaning.

我打破了这个习惯,但是在没有强变量类型的javascript中,使用类型的前缀是很有用的。


当使用动态类型语言时,我偶尔使用应用程序匈牙利语。对于静态类型语言,我没有。请参阅另一个线程中的解释。


匈牙利符号在类型安全语言中是无意义的。例如,在旧的微软代码中,您会看到一个常见的前缀是"lpsz",意思是"指向以零结尾的字符串的长指针"。自1700年初以来,我们还没有使用有短指针和长指针的分段架构,C++中的正常字符串表示始终是零终止的,编译器是类型安全的,所以不允许我们将非字符串操作应用到字符串中。因此,这些信息对程序员来说都不是真正有用的——只是更多的输入而已。

但是,我使用了一个类似的想法:前缀可以澄清变量的用法。主要有:

  • M=成员
  • C=常量
  • S=静态
  • V=挥发性
  • P=指针(和PP=指针指针等)
  • i=索引或迭代器

这些变量可以组合在一起,因此作为指针的静态成员变量将是"mspname"。

这些在哪里有用?

  • 如果用法很重要,最好经常提醒程序员变量是(例如)易失性变量或指针
  • 在使用p前缀之前,指针取消引用一直在执行我的头操作。现在,很容易知道什么时候有对象(橙色)、指向对象的指针(porange)或指向对象的指针(pporange)。要取消对一个对象的引用,只需在它前面为它的名称中的每个p加上一个星号。案子解决了,不再有虫子了!
  • 在构造函数中,我通常发现参数名与成员变量名(例如,大小)相同。我更喜欢使用"msize=size";而不是"size=thesize"或"this.size=size"。它也更安全:当我打算说"msize=1"(设置成员)时,我不会意外地使用"size=1"(设置参数)。
  • 在循环中,迭代器变量都是有意义的名称。大多数程序员使用"i"或"index",当他们想要一个内部循环时,就必须编出新的无意义的名称("j","index2")。我使用一个带有i前缀的有意义的名称(ihospital、iward、ipient),所以我总是知道迭代器在迭代什么。
  • 在循环中,您可以使用相同的基名称和不同的前缀来混合几个相关变量:橙色橙色=porange[i orange];这也意味着您不会造成数组索引错误(papple[i]看起来正常,但将其写为papple[iorange]并且错误立即明显)。
  • 许多程序员会在不知道的情况下使用我的系统:通过添加一个长长的后缀,如"index"或"ptr"——没有任何好的理由使用比单个字符imho更长的格式,所以我使用"i"和"p"。更少的打字,更一致,更容易阅读。

这是一个简单的系统,它为代码添加有意义和有用的信息,并消除了许多简单但常见的编程错误的可能性。


问题是混合标准。

正确的是确保每个人都做同样的事情。

1
int Box = iBottom * nVerticleSide

作为一个PHP程序员,如果它的类型非常松散,我并不想使用它。但是,我偶尔会根据系统的大小和变量的范围将某个对象标识为数组或对象。


原始格式(右匈牙利符号:),其中前缀表示变量存储的值的类型(即长度、数量)可以,但并非所有类型的应用程序都需要。

在大多数现代编程语言中,前缀表示类型(string,int)的流行形式(错误的匈牙利表示法)是无用的。

尤其是像斯特拉这样毫无意义的名字。我不明白我们大家用的是无意义的名字,前缀很长,什么也不给。


我对组件(如editfirstname、lblstatus等)使用基于类型的(systems hn),因为它使自动完成功能更好。

我有时会将app hn用于类型信息无效的变量。ie fpx表示一个定点变量(int类型,但不能与int混合和匹配),rawinput表示尚未验证的用户字符串等。


这取决于你的语言和环境。通常我不会使用它,除非您所处的开发环境使得很难找到变量的类型。

还有两种不同类型的匈牙利符号。见乔尔的文章。我找不到(他的名字不太容易找到),有人链接到我的意思吗?

编辑:韦奇在他的帖子里有我的意思。


在过去的6个月里,我一直在IBM工作,但我在任何地方都没有看到它(感谢上帝,因为我讨厌它),我看到的要么是Camelcase,要么是C_风格。

1
2
thisMethodIsPrettyCool()
this_method_is_pretty_cool()


推荐阅读