I’m a huge believer in consistency, and hence conventions.
However, I’m currently developing a framework in Java where these conventions (specifically the get
/set
prefix convention) seem to get in the way of readability. For example, some classes will have id
and name
properties and using o.getId()
instead of o.id()
seems utterly pointless for a number of reasons:
- The classes are immutable so there will (generally) be no corresponding setter,
- there is no chance of confusion,
- the
get
in this case conveys no additional semantics, and - I use this
get
-less naming schema quite consistently throughout the library.
I am getting some reassurance from the Java Collection
classes (and other classes from the Java Platform library) which also violate JavaBean conventions (e.g. they use size
instead of getSize
etc.).
To get this concern out of the way: the component will never be used as a JavaBean since they cannot be meaningfully used that way.
On the other hand, I am not a seasoned Java user and I don’t know what other Java developers expect of a library. Can I follow the example of the Java Platform classes in this or is it considered bad style? Is the violation of the get
/set
convention in Java library classes deemed a mistake in retrospect? Or is it completely normal to ignore the JavaBean conventions when not applicable?
(The Sun code conventions for Java don’t mention this at all.)
Consider this: Lots of frameworks can be told to reference a property in object's field such as "name". Under the hood the framework understands to first turn "name" into "setName", figure out from its singular parameter what is the return type and then form either "getName" or "isName".
If you don't provide such well-documented, sensible accessor/mutator mechanism, your framework/library just won't work with the majority of other libraries/frameworks out there.
If you follow the appropriate naming conventions, then 3rd-party tools can easily integrate with and use your library. They will expect
getX()
,isX()
etc. and try to find these through reflection.Although you say that these won't be exposed as JavaBeans currently, I would still follow the conventions. Who knows what you may want to do further down the line ? Or perhaps at a later stage you'll want to extract an interface to this object and create a proxy that can be accessed via other tools ?
The get-less schema is used in a language like scala (and other languages), with the Uniform Access Principle:
Since Java is not meant to offer UAP for "properties", it is best to refer to those properties with the get/set conventions.
UAP means:
Foo.bar
andFoo.bar()
are the same and refer to reading property, or to a read method for the property.Foo.bar = 5
andFoo.bar(5)
are the same and refer to setting the property, or to a write method for the property.In Java, you cannot achieve UAP because
Foo.bar
andFoo.bar()
are in two different namespaces.That means to access the read method, you will have to call
Foo.bar()
, which is no different than calling any other method.So this get-set convention can help to differentiate that call from the others (not related to properties), since "All services (here "just reading/setting a value, or computing it") offered by a module cannot be available through a uniform notation".
It is not mandatory, but is a way to recognize a service related to get/set or compute a property value, from the other services.
If UAP were available in Java, that convention would not be needed at all.
Note: the
size()
instead ofgetSize()
is probably a legacy bad naming preserved for the sake of Java's mantra is 'Backwardly compatible: always'.Josh Bloch actually sides with you in this matter in Effective Java, where he advocates the
get
-less variant for things which aren't meant to be used as beans, for readability's sake. Of course, not everyone agrees with Bloch, but it shows there are cases for and against dumping theget
. (I think it's easier to read, and so if YAGNI, ditch theget
.)Concerning the
size()
method from the collections framework; it seems unlikely it's just a "bad" legacy name when you look at, say, the more recentEnum
class which hasname()
andordinal()
. (Which probably can be explained by Bloch being one ofEnum
's two attributed authors. ☺)I actually hate this convention. I would be very happen if it was replaced by a real java tool that would provide the accessor/modifier methods.
But I do follow this convention in all my code. We don't program alone, and even if the whole team agrees on a special convention right now, you can be assured that future newcomers, or a future team that will maintain your project, will have a hard time at the beginning... I believe the inconvenience for get/set is not as big as the inconvenience from being non-standard.
I would like to raise another concern : often, java software uses too many accessors and modifiers (get/set). We should apply much more the "Tell, don't ask" advice. For example, replace the getters on B by a "real" method:
by
Many good properties are obtained by this refactor:
The violation of the get/set convention in the Java library classes is most certainly a mistake. I'd actually recommend that you follow the convention, to avoid the complexity of knowing why/when the convention isn't followed.