Java变量名

3

您能给出一些在变量名中包含类名的好理由吗?我们之前有这样的政策,我认为非常有用。但是现在有些团队成员想要撤销这个决定。

我的论点:

  • 你可以直接知道你在谈论什么:

    for (Student student: students) { ... }

很容易理解(相对于 Student sStudent anyone

  • 它有助于自我注释代码
  • 我们的IDE提供了直接支持
  • 您可以直接看到您使用的是苹果而不是梨子(或熊;-)

在细微差别重要的情况下减少混淆:

criteriaBuilder.equal(nameExpression, name);

我唯一能想到的反对意见是这会使代码变得更长(我认为在现代IDE环境下这不是问题)。
是否有公共供应商支持这样的建议?是否有其他人使用相同的规则?还有其他替代方案吗?

3
变量名应该清楚地表明它们所包含/表示的内容,类型通常不重要。例如,你会写 String string = "Eric" 吗? - Kaj
1
@DJClayworth,是的,他想说的是在变量名前面放置类型,例如:“Student studentJack = ....” - RMT
1
似乎这样做 Student studentJohn; 没有问题。我同意这会使得稍后在代码中区分变量更容易。 - Trevor Arjeski
@David:我同意,allStudentsByName 表示它是一个map结构。 - ymajoros
1
@ymajoros - 你不会找到证据证明一种方法比另一种更好。跟大部分的编码规范一样,你需要在组织内权衡考虑两方面并做出选择。在IDE功能较弱之前和重构出现之前,匈牙利命名法更为流行。我感觉随着产业和工具的成熟,这种方法已经被淘汰了。你仍然可以在某些地方看到这种命名法,但是自1995年以来,我只在一个项目中使用过它,那是因为我要扩展的现有代码库使用了这种方法。 - David Harkness
显示剩余21条评论
4个回答

7

听起来对我来说像是匈牙利命名法

原则上,这听起来是个不错的想法,但我不确定是否有充分的理由支持:

  • 自注释/文档化代码-应该可以在不将类型放入变量名称中的情况下实现;
  • IDE还应提供支持,以查看变量的类型,而无需将其放入变量名称中(例如Eclipse可以做到这一点)
  • 我不认为这真的是一个优势。

匈牙利命名法的一个问题是您没有提到,即如果重构代码,则必须同时更改所有变量名称。 在The Daily WTF上有很多示例,其中变量被命名为'strSOMETHING'或'intSOMETHING',即使类型定义为其他内容也是如此。

总的来说,在我看来,使用匈牙利命名法的理由非常薄弱,通常我不建议将其作为一项政策。

(如果这不完全是您所谈论的内容,我向您道歉!)


我甚至在某些变量(计数器)上也有同意见。然而,根据我的经验,我认为这应该是一项严格的对象命名规范。一个“学生”可能会一直保持这个身份。 - ymajoros
就Java而言,我认为没有必要在变量前加上类型前缀,因为大多数人可能使用能够提供类型信息的IDE。 - alexcoco
@alexcoco:但你必须查询。而且你并不总是从IDE(网络...)中阅读代码。相反,这个策略几乎没有成本就能使事情清晰明了(在NetBeans中键入类型只需按Ctrl-Space)。 - ymajoros
@ymajoros,我同意,并非每个人都会从集成开发环境中阅读代码。也许只是我的个人偏好不加前缀。我认为这也很重要。对我来说,这已足以使我停止加前缀。不过话说回来,当我编写代码时,通常只是为了自己的眼睛。 - alexcoco
1
一篇非常好的博客文章,讲述了匈牙利标记法的实际目的:http://www.joelonsoftware.com/articles/Wrong.html - Thomas
显示剩余5条评论

6
您在这个问题上的圣经是Steve McConnel的书,Code Complete,它是关于软件构建实践最全面的书籍。他有一整章关于变量命名以及为什么它很重要。
关键是将变量名称描述得非常详细,以便读者容易理解。如果达到了这个目的,那么就是好的实践。 Student student 策略看起来很简单易懂,但它有一个即时的缺点——它不包含有关变量的任何其他信息。您已经知道它是一个学生。如果您知道对象的其他任何信息,请将其添加到变量名称中——studentUnderReview、graduatingStudent等。只有在您绝对不知道变量用于什么时才应使用“student”,例如变量用于迭代所有学生。现在在一个长方法中,通过查看名称知道类型很有用,但如果变量的作用域很短,则它是否有用是微不足道的。有一些研究(见McConnel)表明,对于作用域非常短的变量,例如for循环索引,使用短名称更好。
一旦你有两个变量,这个系统就会崩溃。如果默认情况下将一个变量称为“student”,那么诱惑就是将两个变量称为“student1”和“student2”,这确实是不好的做法(详见McConnel)。你需要使用描述对象的名称 - goodStudent和badStudent; studentBeingSaved和studentBeingRead。

我肯定会看这本书。如果我有两个学生变量,我通常会按照您建议的方式命名它们。我的问题是关于这个主题的一个好参考资料,所以您的答案确实很有趣。 - ymajoros
《代码大全》中只稍微提到的一个重要主题是在变量名中使用单位。我认为将单位放入变量名中是必须的,例如使用timeoutMilliseconds而不仅仅是timeout,并且将内容类型(不是变量类型的一部分)作为commentsHtml而不仅仅是comments。 - Eduardo
这是一个很好的观点,但如果你使用一致的单位集合,那么在名称中放置单位就是不必要的。在注释中说明即可。 - DJClayworth
@DJClayworth问题在于你可能最开始将超时时间设置为秒,然后你将其更改为毫秒以获得更高的分辨率,这就会变成一团糟。如果你重命名变量,你要确保旧单位的变量没有被引用。 - Eduardo
这就是为什么我说“如果您使用一致的单位集合”。如果您不使用一致的单位集合,那么是的,您可能需要重命名一些变量。 - DJClayworth

2

应该使用描述性变量名的策略。单个字母的变量名不好,但仅基于类名的变量名也不好。你的主要观点确实是为了使用具有描述性的变量名。

至于其他方面:

  • 它有助于自我注释代码 - 不,它会从变量声明中复制信息
  • 我们的 IDE 直接支持这一点 - 只有在其他替代方案没有任何好处时才会是一个论点
  • 您可以直接看到是否正在使用苹果而不是梨子(或熊;-)) - 这是类型系统的工作

当然,如果您的类名是描述性的,则有时候拥有相同名称的变量将有意义 - 当变量描述一个没有任何独特特征的类的实例时。就像你的例子一样:

for (Student student: students) { ... }

如果你正在循环遍历所有学生,那么这样做是可以的。但是如果你有一个非泛型的Student实例,变量名应该描述这个学生在程序的哪个部分扮演了什么特定的角色(例如candidategraduate)。


我同意某些部分,直到候选人/毕业生的例子。对我来说,candidateStudent是一个更合适的选择。 - ymajoros
我同意Michael的观点。“Student candidateStudent”并没有比“Student candidate”更多的信息。 - DJClayworth
@DJClayworth它确实提供了“候选人”不提供的视觉类型信息。在我们庞大的代码库中,这非常重要。您不能总是检查类型。 - ymajoros
@ymajoros:如果变量在定义它们的地方很远的地方使用,那么你就有一个设计问题,与代码大小无关,类型信息也不是这个问题的最大部分。任何值得使用的Java IDE都会在你将光标悬停在变量上时显示其类型。有一个非常广泛的共识,即“可视化类型信息”(重复声明的类型)不是一件好事(请参见整个匈牙利符号争论)。 - Michael Borgwardt
在编程中,即使定义不难读懂,但如果涉及到非平凡算法,将一个学生变量命名为“graduate”会让读者难以记忆。相比之下,明确地命名为“graduateStudent”则能让一切变得清晰明了。 - ymajoros

1

通常情况下,你的变量名应该能够帮助开发者快速理解它们所代表的含义。

如果关系定义了“任何东西到学生”的关联,例如Student student是可以接受的,而对于类似Professor的情况,Student[] students(或更好地说,一些包含多个学生的集合)是可以接受的。

String string通常不是一个好主意,因为它不会告诉我们关于该变量的使用方式。更好的命名方式可以是String nameString description或类似的命名。在某些情况下,当你仅需要处理一个字符串时(如通用字符串工具类),你可以将变量命名为string,但如果你有两个或更多的字符串,就应该使用更好的名称(例如,根据类/方法的上下文,使用sourcetarget等)。

在我看来,添加前缀/后缀可能是个不错的主意,如果它们能够提供关于变量的额外信息,而基本名称无法提供。例如,在Web环境中,你可能会处理用户输入的字符串以及经过转义的字符串(例如,为了防止代码注入),因此你可以使用前缀/后缀来区分用户输入版本和转义版本。


我同意在大多数情况下,String string 不是一个好主意(可能适用于字符串实用方法)。但是当我的变量名包含某些东西的字符串表示时,我总是以 Str 结尾(在面向对象编程中,这应该与它所代表的东西非常不同)。 - ymajoros
@ymajoros 如果你有一个不是字符串的东西的字符串表示,你是可以这样做的,但是如果你有一个普通的字符串对象,你不会把它称为 nameStr,对吧? - Thomas
如果显而易见,我就不会这样做。如果需要的话,我会这样做:String publicationDateStr(格式化日期)与Date publicationDate - ymajoros

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