您是否在变量名称前加上变量类型的缩写?(匈牙利表示法)


37

在我目前的工作中,没有编码准则。每个人几乎都按照他想要的方式进行编码。很好,因为公司很小。

但是,最近有一个新手提议始终使用匈牙利表示法。到目前为止,我们中的一些人使用了某种匈牙利符号,而我们中的某些人则没有。您知道,这是一家工程公司,因此只要算法是合理的,编码样式就并不重要。

我个人认为这些小写缩写是多余的。一个经过深思熟虑的名字通常会传达相同的信息。(此外,大多数的我们的代码必须运行一些怪人的DSP,在那里同样的一个概念boolfloat不存在反正)。

那么,您如何看待匈牙利符号?你用吗?为什么?



7
您正在使用哪种编程语言?
拉里·科尔曼

3
实际上,它不是很好-您应该有一个编码标准(正式的或其他形式),我认为它永远不会很好...但是其他人可能会不同意。
Murph

@Larry:我们主要使用C和C ++,到处都有少量的Assembler和Lua。
bastibe 2011年

11
@Paperflyer,编码标准/规则不适用于客户,它们适用于开发团队。除非您相信同一位开发人员将永远任职(不切实际),否则我坚信您应该建立并遵循编码标准。它带来了更易于维护的系统,使新员工更快地提高了速度并提高了一致性。话虽如此,我同意匈牙利的表示法已被证明是多余的,并且更多地是过去的遗迹。考虑周全的名称更为重要,尤其是在如今使用功能更强大的IDE的情况下。
Mark Freedman

Answers:


77

当大多数人说“匈牙利符号”时,他们实际上是在谈论“ 系统匈牙利语 ”。

系统匈牙利语完全没有用,应避免。无需在名称中对变量的类型进行编码。但是,Systems Hungarian实际上是对原始的 “真实的”匈牙利语:Apps匈牙利语的误解。

在Apps Hungarian中,您不对变量名称中的“类型”进行编码,而是对变量的“种类”进行编码。因此不是nWidth,而是pxWidthemWidth(分别用于“以像素为单位的宽度”或“以ems为单位的宽度”)。不是,strName而是sNameusName(分别用于“安全名称”或“不安全名称”-在接受用户输入时有用:不安全字符串)。

就个人而言,我通常都不会打扰任何人。除非我做的事情是明确地转换值的“种类”(例如,过去我使用过“ px”和“ em”前缀,因为它使错误pxArea = emWidth * emHeight很明显)。

另请参见Joel的文章“ 使错误的代码看起来错误”


2
查看西蒙尼关于该主题的著作:他是匈牙利的原始颁布者,他的版本是有用的。msdn.microsoft.com/zh-CN/library/aa260976(v=vs.60).aspx
Michael Kohne

1
如果确实需要,可以采用某种方式将单位包含在自定义类型中(对于安全/不安全的字符串也是如此)。但是,我看到这样做会遇到性能问题(例如,您不希望将浮点数包装在类中)。在F#中,它引入了度量单位功能,该功能主要是为了实现此目的而在double中添加额外的类型信息。
Scott Whitlock

1
在处理用户输入的代码,我发现它有用前缀的用户数据与rawrawUsername
zzzzBov

1
@Scott的另一个选择是强类型typedef
jk。

1
@JBR:您实际上读过答案吗?在“应用匈牙利”时,s不是string什么的,但对于“安全”(或我也听说“安全弦”)。

31

代词你动词应该副词永不动词使用形容词匈牙利语注记,介词它使动词成为集体名词一切副词所以比较血腥形容词很难定语给动词朗读。


6
让我微笑...学究,但“至”是介词,而不是定语。“阅读”是不定式。
DrAl 2011年

@dral当然,那是在幽默寄存器,而不是语法怪胎的:d
smirkingman

1
太棒了,让我发笑。:)
Corv1nus 2011年

26

首先:

您知道,这是一家工程公司,因此只要算法是合理的,编码样式就并不重要。

编码风格很重要,与公司无关。是的,算法必须合理,但是每个人都必须维护代码,而不仅仅是原始开发人员。拥有包含样式元素的编码标准可以达到这一目的。我并不是说所有代码的样式都应该相同-这会适得其反,但是应该有一定程度的一致性。

现在转到匈牙利符号:

尽管有其用途,但对于支持IntelliSense类型行为的现代IDE,不必在其名称中包含变量的类型。您可以通过其他方式使用此信息。更糟糕的是,如果将来必须更改变量的类型,它会使代码更难阅读。


21

不要使用它。它是多余的,使代码更难阅读。


8
比“冗余”更糟糕。对于某些复杂的情况,很难正确解决。具体来说,您在应用中定义的每个类都需要一个缩写。在定义了20个左右的类之后,您将失去一个字母的缩写。现在怎么办?一个字母和两个字母的混合物?对数据结构元素的复杂引用呢?指向列表到整数到字符串的映射映射数组的指针?缩写将如何帮助您?
S.Lott

13

关于(系统)匈牙利表示法的很多争论都取决于工作领域。我曾经非常坚定地支持“绝不行!”,但是在一家从事嵌入式开发的公司工作了几年之后,我看到了它在某些应用程序中的一些优势,而且它在我身上的确有发展。

系统匈牙利语

据我所知,Systems Hungarian在嵌入式领域中经常使用。在PC应用程序中,编译器将处理许多与(例如)字符串,整数和浮点值之间的差异相关的问题。在深度嵌入式平台上,您通常会担心8位无符号整数,16位有符号整数等之间的差异。编译器(甚至强制执行MISRA规则的lint)并不总是会采用这些差异。在这种情况下,具有可变的名称,如u8ReadIndexs16ADCValue可以是有益的。

Apps匈牙利文

Apps Hungarian在PC / Web应用程序方面具有明显的优势,例如,在“不安全”字符串和“安全”字符串(即用户输入的字符串和已从内部资源中转义或读取的字符串)之间提供视觉区别)。编译器不知道这种区别。

重点是什么?

使用(系统或应用程序)匈牙利语仅是为了使错误的代码看起来不正确

如果您将不安全的字符串直接复制到安全的字符串中而又没有进行转义,那么如果您使用Apps Hungarian,它将看起来是错误的。

如果将有符号整数乘以无符号整数,则编译器将(通常无提示地)将有符号整数提升为(可能是巨大的)无符号整数,这可能会导致错误:Systems Hungarian看起来很错误。

在这两种情况下,(Apps / Systems)匈牙利表示法都倾向于使正式代码审查更快,因为很少涉及到变量的类型。

总体

总的来说,我认为最重要的是您有一个编码标准。是否使用Systems Hungarian,是否使用Apps Hungarian取决于个人或组的偏好,这与缩进类型的选择等非常相似。但是,以相同的偏好工作的整个开发团队具有明显的优势。


您应该弄清楚您在说什么语言。由于您从事嵌入式开发,因此我假设您正在使用C?匈牙利语确实在C语言中有意义,但在更现代的语言中却没有意义。
JacquesB 2015年

9

匈牙利表示法的目的是将信息编码到标识符中,否则无法在类型系统中进行编码。我个人的看法是,如果此信息足够重要以进行编码,那么它就足够重要以在类型系统中进行编码,可以对其进行正确检查。如果信息不重要,那么为什么要用它来弄乱源代码呢?

或者,更简单地说:类型信息属于类型系统。(注意:它不必是静态类型系统。只要它能够捕获类型错误,我就不在乎何时捕获它们。)

其他几个答案提到度量单位是匈牙利表示法的可接受用法。(令我惊讶的是,到目前为止还没有人提及美国国家航空航天局火星气候轨道器,因为在有关匈牙利表示法的讨论中,这似乎一直存在。)

这是F#中的一个简单示例:

[<Measure>] type m
[<Measure>] type ft

let someLength      = 48.15<m>
let someOtherLength = 16.2342<ft>

someLength + someOtherLength
// someLength + someOtherLength
// -------------^^^^^^^^^^^^^^^
// error FS0001: The unit of measure 'ft' does not match the unit of measure 'm'.

瞧,马,没有匈牙利人!

如果我这里使用匈牙利表示法而不是类型,那对我没有帮助:

let mSomeLength       = 48.15
let ftSomeOtherLength = 16.2342

mSomeLength + ftSomeOtherLength
// > val it : float = 64.3842

编译器让它直接通过。我现在依靠人工来发现本质上是类型错误的内容。这不是类型检查器的目的吗?

更好的是,使用Frink编程语言

someLength      = 48.15m
someOtherLength = 16.2342ft

someLength + someOtherLength
// 53.09818416 m (length)

// Wanna know the answer in a good old fashioned American unit?
someLength + someOtherLength -> yd
// 58.06888031496062992

// Are you an astrophysicist?
someLength + someOtherLength -> parsec
// 1.7207949554318336148e-15

// ... or a fundmentalist Christian who refuses to use units invented 
// less than 2000 years ago?
someLength + someOtherLength -> biblicalcubits
// 95.893563822870765006

因此,总而言之:我不喜欢匈牙利符号。您永远不要使用它。

话虽如此,我认为使用匈牙利表示法是一个好主意。等一下

是! 在这种情况下,您提到了:

此外,我们的大多数代码都必须在某些怪异的DSP上运行,在这些怪异的DSP上根本不存在诸如bool或float的概念

但是,这恰恰是唯一明智的使用案例匈牙利命名法!


PS:我全力推荐看Frink。它的手册包含一些有史以来最棒的放屁笑话。这也是一种很酷的语言:-)


如果可以的话,我会投票50次。
拉里·科尔曼

1
很有趣的说法!我可能会在当前项目中尝试一下。typedef meter float...
bastibe 2011年

6

在面向对象的语言中这没有意义-一切都是一种在尝试使用它时显而易见的类型。


6

唯一需要警告系统匈牙利语的地方是使用C之类的弱类型语言。由于C没有显式对象(它具有结构,但是所有功能都在该结构外部),因此对于C而言这双重重要。在诸如C ++,Java和C#之类的更强类型中,它无济于事,实际上会使情况变得更糟。代码更改了,更改类型比更改使用变量名的所有位置要容易得多。这也是不必要的繁忙工作,容易被忽略。

如果有度量单位,可能会有助于将其编码为一个名称-但最终可能还会产生额外的噪音。例如,我们将为代码中使用的不同事物声明标准的度量单位。例如,我们是否使用渐变或度,米或英尺,帧或毫秒?为代码设定标准后,只要我们以一种计量单位阅读,我们总是会立即转换为代码的标准计量单位。

我的建议:从您当前的痛点开始,并为该部分代码选择一个合理的标准。过度指定编码标准会适得其反。拥有变量和字段名称来说明它们所代表的内容有很多价值,而且大多数时候您可以从概念中安全地推断出类型。


1
实际上,好的IDE(或插件)通常具有相当强大的重构功能,可以轻松更改变量名。
bastibe 2011年

4
可以理解,但是版本控制中用于名称更改的额外杂音也无济于事。仅仅说增加的价值并不能证明维护的开销。
Berin Loritsch 2011年

将取决于语言以及某些语言对直接类型UoM或直接类型typedef
jk的

6

哎呀!

不要使用匈牙利符号或任何其他符号。作为程序员,我们不应在变量名中使用“符号”。

我们应该做的就是好好命名我们的变量

  • 避免使用过于笼统的名称。z当它是代表已命名对象的类变量(例如电话帐单)时,请勿命名。称之为phoneBillPhoneBill
  • 避免使用过于具体的名称。如果没有其他信息就可以清除某些东西,则不要包括在内。如果它只是用于遍历字符串字符的字符串索引变量,而您仅在函数MyFunc中使用过一次,那么MyFuncTempStringCharacterIndex到底为什么要调用它?那是一个可悲的笑话。调用它,Pos或者即使i您喜欢也可以。在上下文中,下一位程序员将轻松理解其含义。

  • 在确定名称的通用性或特定性时,请考虑其所在的域以及其他可能含义的上下文。在狭义的情况下,有两种容易混淆的相似类型的项目以相同的方式使用,那么可以提出一个前缀或后缀来表示这种差异是很好的。保持尽可能短。

正如其他回答者所说的,正是这种狭义的案例开始了“ Apps Hungarian”的使用,以区分相对于窗口rwTabPosition和相对于文档的度量rdTabPosition。但是,在执行与文档相关的所有操作的应用程序中,请勿添加任何多余的内容!实际上,为什么不使用约尔格·米塔格(JörgW Mittag)的想法来制作一种实际的新类型呢?这样一来,您就不可能将事情搞混了。

在几乎所有区域中,添加具有最小含义密度的内容都会降低总体意义并简化理解。这是本富兰克林(Ben Franklin)一个例子。再举一个例子:用英语可以用词性来修饰我们的单词。是更多信息,不是吗?如果初学者对英语感到困惑,这可能对他们真的有帮助,对吧?阅读此书,并告诉我您认为这对长期理解和有效地传达信息有多大帮助:

vrbDo advnot vrbuse nou匈牙利语注解cnjor adjany adjother注解。作为Nou编程人员,prov vrb应该为proour可调名词使用“ nounotation” prp来动词。

通过添加信息,我完全无法阅读。

所以忘了符号。忘记您总是添加的特殊前缀。我认为,这里唯一真正的准则应该是:

变量名应尽可能,尽可能有意义,并且始终保持明确


这几乎就是我们的标准。唯一的区别是,在命名事物时,我们更喜欢使用Pascal Case,以便使大小写一致。
DForck42,2011年

5

标识符的目的比其类型更重要。如果在程序中使用描述性名称作为标识符,则无需使用匈牙利表示法。isConnected总是比更具可读性和易于理解boolConnected


2
我绝对同意!他们称之为“ App Hungarian”,而不是“ System Hungarian”。
bastibe 2011年

@bastibe:不,这就是他们所说的描述性名称。Apps Hungarian依靠缩写。
JacquesB 2015年

2

当我还是C ++程序员时,我们曾经使用匈牙利语,这很棒。您无需搜索声明就可以看到变量的类型(例如BSTR,CString,LPCTSTR或char *)。在那时,您可以通过以下方式搜索声明:

  1. Ctrl-Home
  2. Ctrl-F
  3. 变量名
  4. 输入

所以这很重要。但是在2000年左右的某个地方发生了一些事情:

  • 编辑者变得足够聪明,可以将变量类型显示为工具提示
  • 编辑者有一个“声明声明”快捷方式,以及一种快速浏览的方式
  • C ++的使用较少,大多数其他语言的变量类型也较少。例如,在C#中,您可以肯定lastName是一个System.String,因为只有一个字符串类。

我是最后一个放弃匈牙利语的人之一,现在当我阅读旧的源代码时,它实际上使我很烦。


2

我只是讨厌匈牙利符号,我更喜欢使用下划线来分隔变量名。

最重要的是,当您将类型作为第一个字母放在变量名的开头时,如下所示:float fvelocity; vect vDirection; 字符串** ppszWord;

自动补全将它们全部分类,您很难找到想要的东西,人们倾向于使用他们认为更好的东西,这不再是一种记号。

我只想写ThingsLikeThat,当我需要对变量进行非常描述性的时候,因为它节省了空间,而且有大写字母的事实使它更具可读性。

我通常要做的是为我的方法和类命名,首字母大写,变量名小写,变量名下划线(我发现最后一个有用)。

认真地说,我希望人们关心这些规则:在相关的空格处使用逗号,算术和花括号:

void f(int a, char b);
int a = b + 4 / (3 + 4);

每行最多80个字符,或最多90个字符,请对函数或long使用多行参数if

if
(
    checkthat(a, b) == checkthis(b, d) &&
    checkthat(d, b) == checkthis(v, d)
)

1

同意大多数,这是一种旧样式。

使用现代IDE,将鼠标悬停在变量上即可显示类型。


2
我发现这个问题(IDE可以帮助您)是一个糟糕的论点-在进行编码时,是的,您将受益匪浅。但是在许多情况下(提交,审阅,差异/归咎等),您可能没有可用的支持。
Murph

你错了!;)公平的说,我仍然不会使用匈牙利语!
ozz 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.