Java方法命名约定:太多getter

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

我注意到在函数式/声明式编程和PL / SQL中使用了不同的命名约定。 方法名称只是说明方法返回的内容。 他们将使用account.amount()Time.isoFormattedDateString(Date date)代替account.getAmount()Time.isoFormattedDateString(Date date) 。 这对我来说非常有意义,因为函数的名称描述了对方法进行评估的结果(假设没有任何副作用)。 “get”前缀似乎是多余的。

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

  1. 通知一些事件的对象,通常作为parameter passing事件。
  2. 询问关于某个对象的问题,通常使用方法名称形成自然语言语句,将对象作为parameter passing并返回一个布尔值。
  3. 取东西,可能传递一些查找键或一些对象作为参数转换,并始终返回所需的对象/值。

我的问题是关于第三类。 除了“获得”这种方法是否有命名约定? 在select方法名称/前缀时使用什么标准?

这里是一个例子:

我有两个方法getDates()getSpecialDates()getDates()只是返回一个私有variables的值(对date集合的引用)。 据我所知,这是一个标准的吸气剂。 getSpecialDates()是不同的; 它调用getDates() ,从另一个类中获取一个filter,应用filter并返回getDates()一个子集。

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

为什么要在应该以“get”为前缀的方法和不应该使用的方法之间进行区分,以及为什么要为“get”findreplace字呢?

我个人不会在任何可能的情况下使用 getter和setter(意思是:我不使用任何需要它的框架,比如Struts)。

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

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

类应该是不可变的,除非有一个很好的理由使它们变为可变的。如果一个类不能变成不变的,尽可能地限制它的可变性。

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

JavaBean模式有严重的缺点。

我完全赞同这个观点,因为JavaBeans最初的目标是一个非常狭窄的问题领域:在IDE中操纵graphics组件。 使用为解决另一个问题而devise的解决scheme是不好的做法。

它来自JavaBeans命名约定 。

有很多get *方法的部分原因是Java不支持“.net / COM”属性,而Java bean等使用函数getX和setX来复制名为X的属性的function。 Java利用这个来允许设置和检索属性。

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

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

Java不支持统一的访问原则 ,所以你必须编写getter和setter方法来访问属性。

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

要求Java开发人员使用通用的get / set约定的原因之一是很多框架都依赖于bean创build和设置字段。 例如,如果您为Spring beanconfiguration了一些属性(如<property name="foo" value="bar" /> setFoo() ,并且类中没有名为setFoo()方法,则会在创buildbean时出错。

正如很多人已经说过的,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布尔属性。

当我们生活在一个有价值的IDE将为你的私有variables产生getter和setter并且让你把它们折叠起来的时候,“get”是什么意思呢?

你真正的问题应该是关于devise:为什么你的对象有这么多的属性? 如果你的物体除了吸气剂和吸附剂之外什么都没有,你是否患有“贫血域模型”?

C# {get, set}表示法稍微好一些,因为它削减了代码行,但是仍然有那个麻烦的“get”来键入每个variables。

正如其他人所提到的,这是Java Bean。 但是,如果您正在使用Java,请只命名一个方法getXXX(),如果它只返回一个值而不做别的事情。 就像你暗示的那样,如果它正在做别的事情,就把它命名为computeXXX()。

我有时会用50行代码findgetXXX()方法 – 如果是这样的话,你就错了。

前提1:一种方法应该只做一件事。 前提2:吸气方法 – 使用get前缀或不使用 – 应该没有副作用。 鉴于这两个前提,我提出:一个方法的作用是取得某些东西,而且这样做相对简单和廉价,不需要在其名称中使用动词。

吸气剂的存在的意义不在于做什么,而是要评估一些事情。 我们对这个方法感兴趣。 由于它没有副作用,所以在方法中进行的任何计算都不是什么有意义的。 我们只关心该方法返回的内容 。 方法名应该以名词的forms反映出来。 仅由名词组成的方法名称应始终为“getters”。

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

一个名称只包含一个名词并具有返回值的方法可以被假定为没有副作用并且相对便宜。 名称中包含动词并且没有返回值的方法存在副作用。 一个名字包含一个动词并且有一个返回值的方法可以被认为是比较昂贵的,并且可能有副作用。

看来大家写“得到”的原因只是源于JavaBeans模式的教条式传统。 当您实际计划使用需要它的工具/框架时,请保留get前缀!

诸如getSpecialDates()computeSpecialDates()findSpecialDates()selectSpecialDates()elicitSpecialDates()类的方法名称是命令,因为在其名称中使用了动词(动作)。 每次你打电话时,命令都是有副作用的。 而方法名称如date()dates()specialDates() [名词]是方法返回一个有用的值,没有副作用。 除非调用一个副作用改变状态的命令,否则每次调用该方法都会返回相同的值。

就个人而言,我沉迷于get 。 这只是人类的语言。 当你想要什么时,你想得到一些东西。 get前缀没有任何问题。 关于命名约定,我可以考虑数据库查询的Select前缀 – 例如SelectUsers

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

我会稍微不同意这个结论。 我不会说这失去了它的意义,我会说,因为广泛使用get前缀的方法会做你期望他们做的事情。

对于以下示例:

 Time.isoFormattedDateString(Date date) 

这是否设置基于input参数的格式types,所有后续的调用将使用这种格式?

我知道有人会得出这样一个结论,因为这是一个静态的方法,但是如果在一个实例上调用这个方法,你会如何确定? 也许吧,但get的使用消除了所有的含糊之处:

 getIsoFormattedDateString(Date date) 

在我看来,财产是一个更优雅的解决scheme,而不是完全放弃。

历史片段:如果您查看一些最早的Java 1.0 API(在JavaBeans之前),您将看到它们没有“get”前缀。 例如,java.awt.Container#minimumSize()已弃用,取而代之的是#getMinimumSize()。

我认为这是“给你的variables和函数有意义的名字”的一个子集。

许多人已经注意到,“get”在Java Bean中具有特定的含义。 因此,我认为它应该被限制于被用来检索一个内部variables的值,可能带有副作用。 如果“获取”涉及次要计算,比如执行数据types转换或从embedded类中提取值或重新解释其他值,如“public int getRightMargin(){return width-margin.left;}”,则认为是可以接受的。 任何副作用都应该限制在获得价值的真正“副作用”上,比如设置一个标志,表明它已被检索。

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

如果我们在命名函数时使用了一致的术语,比如我们都同意“read”意味着主要活动是从数据库中检索某些东西,而“calc”意味着要进行计算等等,那将是一件好事。 但这可能是不现实的:也许有太多细微差别的情况。

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

例如在java.util.Mapsize()可以被称为getSize()keySet() 不会被称为getKeySet()

我使用获取和设置只能得到或设置属性,而不是其他的方法。

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

那么,尽pipeJavaBeans规范要求你声明getter和setter,但是除非绝对必要,否则我通常不会声明它们(就像许多MVC框架一样)。 我在Java职业生涯中做了很多工作,我倾向于将variables声明为public(是的,这听起来有点不OOPy)。 但我喜欢它,因为它看起来简洁,“我知道我在做什么”。 它唯一的好处是减less了行数。

“get”前缀仍然是很重要的,因为:

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

  • 得到显示variables的状态不会改变

  • 在这个expression式中,你很容易区分方法account()和variablesaccount

    newAccount = currentAccount + account() —这个account()做什么的?


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

  • 要么把你的class级分成小class或者小class
  • 只是更好地隐藏你的代码,因为你不必透露你的class级实习生,甚至应该尽可能地隐藏你的代码!