Java方法名过长的标准是什么?

180
在过去的几周中,我看到有些人为一个方法或类使用非常长(50个字符)的名称,通常是在前提下认为这样可以提高可读性。我的看法是,像这样的长名称表明我们正在尝试在一个方法或类中做太多的事情,如果我们需要使用这样的长名称,那么这是一个指标。不过我想知道你们对此有什么看法。
例子:
getNumberOfSkinCareEligibleItemsWithinTransaction

20
是的,这是一种“代码异味”(code smell)... http://c2.com/cgi/wiki?LongMethodSmell - Dan Rosenstark
25
当字符数超过666个时,就意味着出现了问题。 - Thomas Eding
9
在你的例子中,“长方法”的相反词是“短方法”,被认为是一件好事。所以很明显它不是指方法名称,而是指代码行数(或类似的东西)。例如,f()是一个非常短的函数,但这肯定不是一个好习惯...你应该告诉一些编程数学家们 :) - sfussenegger
3
@sfussenegger,这是真的。但我打赌方法名长度和方法长度之间存在相关性。f()可能不是一个很好的函数,但$()在Javascript方法世界中就像一个摇滚明星。 - Dan Rosenstark
7
@yar,你提供的链接是指方法长度(即代码行数),而不是方法名称的长度。 - Thorbjørn Ravn Andersen
显示剩余14条评论
21个回答

440

在Java或其他语言中,如果存在一个同样能够表达方法行为的更短的名称时,使用较短的名称。


71
数学上优雅。 - Ricket
327
例如,boolean doesShorterNameExistThatEquallyConvaysTheBehaviorOfTheMethod(String s) 应该重构为 boolean isTooLong(String s) - Mark Bolusmjak
7
我不完全同意,因为你不仅想传达行为,还要保持项目和语言的惯例。所以在Python中,您可能会说eligible_items_cnt,但在Java中,通常会说getEligibleItemsCount - flybywire
18
任何让你写过长名称的约定都具有可疑的好处。 - MAK
22
@MAK @S.Lott,getLength()length() 有什么不同?我喜欢在键入“get”或“set”后查看自动完成 - 因此,在这种情况下,我更喜欢规范性而不是简约性。 - sfussenegger
显示剩余10条评论

212

一些减少方法名称长度的技巧:

  1. 如果整个程序、类或模块都是关于“护肤品”的话,你可以省略“护肤品”这个词。例如,如果你的类名为SkinCareUtils,则可以改为getNumberOfEligibleItemsWithinTransaction

  2. 你可以将within 更改为 in,从而得到 getNumberOfEligibleItemsInTransaction

  3. 你可以将 Transaction 更改为 Tx,这样就可以得到 getNumberOfEligibleItemsInTx

  4. 或者,如果该方法接受类型为Transaction 的参数,则可以直接省略“在Tx中”这部分: getNumberOfEligibleItems

  5. 你可以将numberOf 改为 count:getEligibleItemsCount

现在名称更加简单易懂了,并且长度缩短了60%。


11
此外,第5点将会把getEligibleItems()getEligibleItemsCount()放在按字母顺序排序的列表中相邻的位置(例如自动补全或Java文档)。 - sfussenegger
4
通常而言,较短的名称符合俳句规则。 - sal
59
我讨厌像“Tx”,“Cnt”,“grph”等缩写…… (顺便说一下,“Tx”是“Transmission”或“Transmitter”的简写)。 - Meinersbur
15
我同意你的观点,直到你决定使用“Tx”。 - Ponkadoodle
2
@Bill:根据getEligibleItems的命名,我希望该方法返回一个项目对象的集合,而不仅仅是计数。 - Tobias Lott
显示剩余7条评论

195

为了换换口味,给出一个客观的回答:65536个字符。

A.java:1: 字符串“xxxxxxxxxxxxxxxxxxxx…”的UTF8表示对于常量池而言太长了

;-)


4
是的,当JVM无法处理时,它太长了 :) - Anurag
40
+1 对于“THE”字面回答。 - sal
39
从技术上讲,Java语言规范对标识符长度没有上限限制。这是取决于你的JVM实现的限制。干杯! - uckelman
13
Sun的编译器显然不符合规范。http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8中写道:“标识符是一个无限长度的序列……” - Michael Myers
6
正如错误消息所指出的,JVM规范确实有一个上限。utf8的常量池表示法被限制为2^16字节在此指定。类名和方法名必须作为utf8存储在常量池中。 - thejoshwolfe
1
啊,是工程师的回答。从技术上讲是正确的,但有点无用。 - Mateen Ulhaq

45

我同意大家的看法:方法名不应太长。但我想要补充一个例外:

JUnit测试方法的名称可以很长,应该类似于句子。

为什么呢?

  • 因为它们在其他代码中不会被调用。
  • 因为它们用作测试名称。
  • 因为它们可以被编排成描述需求的句子。(例如,使用 AgileDox)

例如:

    @Test
    public void testDialogClosesDownWhenTheRedButtonIsPressedTwice() {
        ...
    }

有关这个想法的更多信息,请参见“行为驱动设计”。


5
+1 我同意这个观点,这也是我正在做的事情。尽管JUnit 4方法不再需要以“test”开头,但这也打开了使用“should”的可能性,例如dialogShouldCloseWhenTheRedButtonIsPressedTwice()。或者你可以将测试类命名为DialogShould,然后将方法命名为closeWhenTheRedButtonIsPressedTwice(),以便一起阅读:DialogShould.closeWhenTheRedButtonIsPressedTwice() - stivlo
3
虽然我同意,但我也建议,句子过长可能表明测试做得过多了! - Brian Agnew
1
或者,如果方法名太长,可以使用注释@DisplayName。例如:@DisplayName("当红色按钮被按两次时,对话框关闭") - Navigatron

17

"...WithinTransaction"这个上下文应该很明显。这就是面向对象的全部意义。

该方法是类的一部分。如果该类不表示“事务”--且如果它不能让你免于一直说“WithinTransaction”,那么你有问题了。


2
可能还可以接受某种事务参数。 - willcodejavaforfood
3
从上面得分最高的答案可以看出,选择简单实用而非OO建议。+1 - Dan Rosenstark
@yar 人民永远不会错。 - CurtainDog

14

Java文化鼓励使用长名称,或许是因为IDE有良好的自动完成功能。

这个网站表示JRE中最长的类名是InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState,长度为92字符。

至于最长的方法名称,我找到了这个supportsDataDefinitionAndDataManipulationTransactions,长度为52个字符。


24
看起来那个班级的命名是由被雇佣为在“冗余部门”中为事物命名的命名人员所完成的,他们在“冗余部门”的工作是为事物命名。 - Michael Madsen
1
@MichaelMadsen:这真的是多余的吗,还是在描述一个嵌套在另一个框架内的框架? - endolith
PEP-8 想和那个类名谈一谈。 - Mateen Ulhaq
这太有趣了。 - Miguel Coder

13

不必使用长词汇,能用简短的就好。

我认为你提出的“方法名长度与方法长度成正比例”这个观点并不一定正确。

以你举的例子为例:“getNumberOfSkinCareEligibleItemsWithinTransaction”。对我来说,它只做了一件事情:计算交易中属于某个特定类别的物品数量。当然,如果没有看到该方法的实际代码,我无法评判,但我认为这是一个好方法。

另一方面,我见过很多方法名称非常短,简洁,但却做了很多工作,例如“processSale”或者广受欢迎的“doStuff”等等。

我认为很难给出一个关于方法名长度的硬性规定,但目标应该是:足够长,以传达函数的功能,足够简短,易于阅读。在这个例子中,“getSkinCareCount”可能已经足够了。问题在于你需要区分什么。如果你有一个函数计算交易中符合美容保养条件的物品数量,另一个函数计算其他地方符合美容保养条件的物品数量,那么“withinTransactions”会增加价值。但如果在交易之外讨论这些物品没有任何意义,那么在名称中加入这些多余的信息就没有意义。

第二,我认为假设任何管理得当的长度的名称都能在除了最琐碎的情况下准确地告诉你函数的作用是极其不现实的。一个现实的目标是制定一个名称,给读者一个提示,并且稍后可以记住它。例如,如果我正在尝试找到计算我们需要消耗多少反物质才能达到超光速的代码,如果我查看函数名称并看到“calibrateTransporter”、“firePhasers”和“calcAntimatterBurn”,那么很明显前两个不是我要找的,但第三个可能是。如果我检查并发现那确实是我要找的那个,那么在明天回来继续解决这个问题时,很容易记住它。这已经足够好了。

长名称相似的情况比短名称更加令人困惑。如果我有两个函数分别叫做 "calcSalesmanPay" 和 "calcGeekPay",我可以快速猜出它们各自的含义。但如果它们被称为 "calculateMonthlyCheckAmountForSalesmanForExportToAccountingSystemAndReconciliation" 和 "calculateMonthlyCheckAmountForProgrammersForExportToAccountingSystemAndReconciliation",我就需要仔细研究名称以确定它们的含义。在这种情况下,名称中的额外信息可能会适得其反,将半秒钟的思考时间变成 30 秒钟。


这个糟糕的答案已经受到了+1的评价。 - Dan Rosenstark

12

我倾向于使用“俳句规则”来命名:

 Seven syllable class names 
 five for variables
 seven for method and other names

以下是关于最大名称的经验法则。只有在它能提高可读性时,我才会违反这些规则。像recalculateMortgageInterest(currentRate, quoteSet...)这样的命名比recalculateMortgageInterestRate或recalculateMortgageInterestRateFromSet更好,因为它嵌入了文档(如javadoc或.NET等)中明确包含利率和报价集的信息。

注意:这不是一个真正的俳句,因为它是7-5-7而不是5-7-5。但我仍然喜欢称其为俳句。


13
类别得到七分,变量少于五个,其余得七分。 - James
8
“variables at most five” 的翻译是“最多五个变量”。(少于五个不准确) - Jason S
较短的名称可能会导致代码可读性降低。 - Deniss M.

11

按照你想要的方式设计你的界面,使实现与之相匹配。

例如,我可能会这样写:

getTransaction().getItems(SKIN_CARE).getEligible().size()

或使用Java 8流式处理:

getTransaction().getItems().stream()
    .filter(item -> item.getType() == SKIN_CARE)
    .filter(item -> item.isEligible())
    .count();

6
我的规则如下:如果一个名称太长以至于必须单独出现在一行中,那么它就太长了。(实际上,这意味着我的命名很少超过20个字符。)
这是基于研究表明可见代码垂直行数与编码速度/效率正相关的事实。如果类/方法名称开始严重影响它们,那么它们就太长了。
在声明方法/类时添加注释,如果您想要详细描述其用途,请让IDE带您到相应位置。

我喜欢这样的规则。只要你记住它们是你/你的团队随意制定的,就没问题了。另一方面,我不能点赞这个因为“研究显示”实际上需要一个链接到那个研究,或者有关它的一些东西... - Dan Rosenstark

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