Java方法命名约定:太多的getter

时间:2010-07-09 08:52:01

标签: java naming-conventions getter many-to-many

为什么Java方法名称如此广泛地使用“get”前缀?至少在我的Java程序中,有很多方法的名称以“get”开头。 get方法的百分比非常高。由于通货膨胀,我开始觉得“获得”这个词正在失去意义。这是我代码中的噪音。

我注意到在功能/声明性编程和PL / SQL中使用了不同的命名约定。方法名称只是说明方法返回的内容。他们将使用account.getAmount()Time.getIsoFormattedDateString(Date date)而不是account.amount()Time.isoFormattedDateString(Date date)。这对我来说非常有意义,因为函数的名称描述了评估方法的结果(假设没有副作用,反正不应该这样)。 “获取”前缀似乎是多余的。

我刚刚开始阅读“清洁代码”一书。它说方法应该只做一件事,那件事通常应该是以下之一:

  1. 通知事件的某些对象,通常将事件作为参数传递。
  2. 询问有关某个对象的问题,通常使用方法名称形成自然语言语句,将对象作为参数传递并返回布尔值。
  3. 获取内容,可能会传递一些查找键或某些要转换为参数的对象,并始终返回所需的对象/值。
  4. 我的问题是关于第三类。对于这种方法,是否存在除“get”之外的命名约定?选择方法名称/前缀时使用什么标准?

    以下是一个例子:

    我的课程有两种方法getDates()getSpecialDates()getDates()只返回私有变量的值(对日期集合的引用)。据我所知,这是一个标准的吸气剂。 getSpecialDates()不同;它调用getDates(),从另一个类中提取过滤器,应用过滤器并返回实际上是getDates()的子集。

    方法getSpecialDates()可以命名为computeSpecialDates()findSpecialDates()selectSpecialDates()elicitSpecialDates()或其他。或者我可以简单地命名为specialDates()。然后,为了保持一致性,我可以将getDates()重命名为dates()

    为什么要分开应该以“get”为前缀的方法和不应该使用的方法之间的分离,以及为什么要为“get”找到替换词呢?

20 个答案:

答案 0 :(得分:27)

我个人尽可能不使用 getter和setter(意思是:我不使用任何需要它的框架,例如Struts)。

我更喜欢在可能的情况下编写不可变对象(公共最终字段),否则我只使用公共字段:更少的锅炉板代码,更高的生产力,更少的副作用。 get / set的原始理由是封装(尽可能使你的对象变得害羞),但事实上,我并不经常需要它。

Effective Java 中,Joshua Bloch提出了这个引人注目的建议:

  

除非,类应该是不可变的   这是一个很好的理由   他们可变......如果一个班级不能   不可改变,限制其可变性   尽可能多。

在同一本书中,他也说(但我不想在这里复制整本书):

  

JavaBeans模式很严重   缺点。

我完全赞同这一点,因为JavaBeans最初是针对一个非常狭窄的问题领域:在IDE中操纵图形组件。使用一种解决另一个问题的解决方案是一种不好的做法。

答案 1 :(得分:16)

答案 2 :(得分:9)

有这么多get *方法的部分原因是Java不支持“属性”,即la .net / COM,Java bean等使用函数getX和setX来复制名为X的属性的功能。一些Java的IDE利用这一点来允许设置和检索属性。

答案 3 :(得分:6)

getter和setter方法通常用Java编写的原因之一是因为使用了JavaBeans约定。

然而,标准Java API本身并不一致。例如,类String具有length()方法,接口Collection定义size()方法,而不是getLength()getSize()

Java不支持uniform access principle,因此您必须编写getter和setter方法来访问属性。

答案 4 :(得分:5)

一个原因是它是Java Bean Spec的重要组成部分。

答案 5 :(得分:5)

getSpecialDates()computeSpecialDates()findSpecialDates()selectSpecialDates()elicitSpecialDates()等方法名称对我来说都是命令,因为使用了动词(动作)他们的名字。每次调用它们时,命令都会产生副作用。而date()dates()specialDates() [nouns]等方法名称是返回有用值而没有副作用的方法。多次调用该方法每次都返回相同的值,除非调用一个副作用是改变状态的命令。

答案 6 :(得分:4)

要求Java开发人员使用常见的get / set约定的原因之一是许多框架依赖于它来创建bean和设置字段。例如,如果您为Spring bean配置了一些属性,如<property name="foo" value="bar" />,并且类中没有名为setFoo()的方法,那么您将在bean创建时出错。

答案 7 :(得分:3)

正如许多人已经说过的那样,get ..()和set()...是Java Beans Convention的一部分。这对于与Java Spec的其他部分进行互操作是必要的。例如,在JSP中,您可以通过指定不带get前缀的属性名称来访问Java中的成员。

鉴于豆: -

public class Foo {
  public int getX() { return 1; }
}

我们可以执行以下JSP来获取X: -

<jsp:useBean id="aFoo" class="Foo" />
<c:out value="${aFoo.X}" />
  

对于这种方法,是否存在“get”以外的命名约定?

是的,您可以使用is代替get来获取布尔属性。

答案 8 :(得分:3)

前提1:方法应该只做一件事。前提2:一个getter方法 - 它是否使用get前缀 - 应该没有副作用。鉴于我提出的这两个前提:一种方法,其作用是获取某些东西,并且以相对简单的廉价方式这样做,不需要在其名称中使用动词。

吸气剂的存在理由并不是做某事,而是为了评估某事。我们对所做的方法不感兴趣。由于它没有副作用,因此该方法中的任何计算都不会引起任何兴趣。我们只对返回的方法感兴趣。方法名称应以名词的形式反映出来。仅由名词组成的方法名称应始终为“getters”。

前缀“get”中的信息可以从缺少动词推断出来。这比使用get前缀更简单,更直观。

一个名称仅由名词组成且具有返回值的方法可以假设没有副作用并且相对便宜。名称包含动词且没有返回值的方法存在副作用。名称包含动词并具有返回值的方法可以假设相对昂贵并且可能有副作用。

似乎每个人都在写“获得”的原因仅仅是源自JavaBeans模式的教条传统。当你真正计划使用需要它的工具/框架时,保留get前缀!

答案 9 :(得分:3)

正如其他人所提到的,它适用于Java Bean。但是,如果您使用的是Java,请仅命名方法getXXX(),如果它只返回一个值而不执行任何其他操作。就像你暗示的那样,如果它正在做其他事情,可以将它命名为不同的东西,例如computeXXX()。

我有时会发现50行代码的getXXX()方法 - 如果是这种情况,那你就错了。

答案 10 :(得分:3)

当我们生活在一个适合拥有的任何IDE将为您的私有变量生成getter和setter并且如果您不想阅读它们时可以将它们折叠起来的日子和时代,那么“获得”会有什么影响?

你真正的问题应该是关于设计:为什么你的对象有这么多属性?如果你的物品只有吸气剂和制定者,你是否患有“贫血的领域模型”?

C#{get, set}符号稍微好一些,因为它减少了代码行,但你仍然需要为每个变量输入那些麻烦的“get”。

答案 11 :(得分:2)

就个人而言,我沉迷于get。它只是人类的语言。如果你想要什么,你想要getget前缀没有任何问题。关于命名约定,我可以考虑数据库查询的Select前缀 - 例如SelectUsers

答案 12 :(得分:2)

  

我开始觉得这个词了   “得到”正在失去意义,因为   通货膨胀。这是我代码中的噪音。

我会略微不同意这个结论。我不会说它失去了它的含义,我会说,因为它被广泛使用,带有get前缀的方法几乎可以完成你期望它们做的事情。

对于以下示例:

Time.isoFormattedDateString(Date date)

这是否根据输入参数设置格式类型,以便所有后续调用都使用此格式?

我知道有人会得出这样的结论,因为它是一个静态方法,但是如果在一个实例上调用这个方法,你会确定吗?可能,但get的使用消除了所有歧义:

getIsoFormattedDateString(Date date)

在我看来,属性是一种比完全放弃更优雅的解决方案。

答案 13 :(得分:1)

历史片段:如果你看一些最早的Java 1.0 API(JavaBeans之前的版本),你会发现它们没有'get'前缀。例如,java.awt.Container#minimumSize()被#getMinimumSize()替换为弃用。

答案 14 :(得分:1)

我认为这是“给你的变量和函数有意义的名字”理想的一部分。

“get”在Java Bean中具有特定含义,正如许多人所指出的那样。因此,我认为它应该仅限于用于检索内部变量的值,可能带有副作用。我认为“获取”涉及次要计算是可以接受的,例如进行数据类型转换或从嵌入类中提取值或重新解释其他值,例如“public int getRightMargin(){return width-margin.left;}”。任何副作用都应限于获得该值的真正“副作用”的东西,比如设置一个表示它已被检索的标志。

但如果有严重的计算,我认为它不应该被称为“获取”。也许是“计算”或其他什么。

如果我们在命名函数中使用一致的术语会很好,例如我们都同意“读取”意味着主要活动是从数据库中检索某些东西而“calc”意味着要进行计算或某些。但这可能是不现实的:也许有太多的案例存在微妙的差异。

答案 15 :(得分:1)

一种选择是为返回原始值或不可变值的方法保留get前缀,但删除返回可用于修改原始收件人的引用的方法的前缀。

e.g。在java.util.Map中,size()可以被称为getSize(),但keySet()称为getKeySet()

答案 16 :(得分:0)

“get”前缀的重要性在于:

  • 方法应该声明一个动作,因此它的名称必须包含一个动词

  • 获取表明变量状态不会改变

  • 您可以轻松地将方法account()与此表达式中的变量account区分开来:

    newAccount = currentAccount + account() ---这account()做了什么?


您在代码中看到太多getter的原因应该让您担心!

  • 您可以将班级分成较小的班级或
  • 只是更好地隐藏你的代码,因为你不必透露你的班级实习生,甚至应尽量隐藏它们!

答案 17 :(得分:0)

Java Bean对其命名约定非常敏感,比如 假设您声明一个变量名称Name,并将相应的setter声明为setName()。但它会产生错误,因为setName必须对应于'name'而不是Name。 另一个例子是boolean isReadey;使用getter isReady()。再次出错,因为它寻找布尔准备好了。 因此,在代码之前,您必须熟悉此命名约定。 但我个人更喜欢这种惯例,因为它使程序员的工作变得简单,并且在花费很短的时间后似乎有点合乎逻辑。

答案 18 :(得分:0)

好吧,虽然JavaBeans规范要求你声明getter和setter,但我通常不会声明它们,除非它是绝对必要的(如许多MVC框架的情况)。我在Java职业生涯中做了很多工作,我倾向于将变量声明为公共变量(是的,它听起来有点不OOPy)。但我喜欢它,因为它看起来简洁,“我知道我在做什么。它的唯一优势是减少了行数。

答案 19 :(得分:0)

我只使用get和set来设置只获取或设置属性的方法而不是其他方法。