Bloated JavaBeans™, Part II – or Don’t Add “Getters” to Your API


I have recently blogged about an idea how JavaBeans™ could be extended to reduce the bloat created by this widely-accepted convention in the Java world.

That article was reblogged on DZone and got quite controversial feedback here (like most ideas that try to get some fresh ideas into the Java world):
http://java.dzone.com/articles/javabeans™-should-be-extended.

I want to revisit one of the thoughts I had in that article, which was given a bit less attention, namely:

Getter and Setter naming

Why do I have to use those bloated “get”/”is” and “set” prefixes every time I want to manipulate object properties? Besides, the case of the first letter of the property changes, too. If you want to perform a case-sensitive search on all usage of a property, you will have to write quite a regular expression to do so

I’m specifically having trouble understanding why we should use getters all over the place. Getters / setters are a convention to provide abstraction over property access. I.e., you’d typically write silly things like this, all the time:

public class MyBean {
    private int myProperty;

    public int getMyProperty() {
        return myProperty;
    }

    public void setMyProperty(int myProperty) {
        this.myProperty = myProperty;
    }
}

OK. Let’s accept that this appears to be our everyday life as a Java developer, writing all this bloat, instead of using standard keywords or annotations. I’m talking about standards, not proprietary things like Project Lombok. With facts of life accepted, let’s have a look at java.io.File for more details. To me, this is a good example where JavaBean-o-mania™ went quite wrong. Why? Check out this source code extract:

public class File {

    // This is the only relevant internal property. It would be "final"
    // if it wasn't set by serialisation magic in readObject()
    private String path;

    // Here are some arbitrary actions that you can perform on this file.
    // Usually, verbs are used as method names for actions. Good:
    public boolean delete();
    public void deleteOnExit();
    public boolean mkdir();
    public boolean renameTo(File dest);

    // Now the fun starts!
    // Here is the obvious "getter" as understood by JavaBeans™
    public String getPath();

    // Here are some additional "getters" that perform some transformation
    // on the underlying property, before returning it
    public String getName();
    public String getParent();
    public File getParentFile();
    public String getPath();

    // But some of these "transformation-getters" use "to", rather than
    // "get". Why "toPath()" but not "toParentFile()"? How to distinguish
    // "toPath()" and "getPath()"?
    public Path toPath();
    public URI toURI();

    // Here are some "getters" that aren't really getters, but retrieve
    // their information from the underlying file
    public long getFreeSpace();
    public long getTotalSpace();
    public long getUsableSpace();

    // But some of the methods qualifying as "not-really-getters" do not
    // feature the "get" action keyword, duh...
    public long lastModified();
    public long length();

    // Now, here's something. "Setters" that don't set properties, but
    // modify the underlying file. A.k.a. "not-really-setters"
    public boolean setLastModified(long time);
    public boolean setReadable(boolean readable);
    public boolean setWritable(boolean writable);

    // Note, of course, that it gets more confusing when you look at what
    // seem to be the "not-really-getters" for the above
    public long lastModified();
    public boolean canRead();
    public boolean canWrite();
}

Confused? Yes. But we have all ended up doing things this way, one time or another. jOOQ is no different, although, future versions will fix this.

How to improve things

Not all libraries and APIs are flawed in this way. Java has come a long way and has been written by many people with different views on the subject. Besides, Java is extremely backwards-compatible, so I don’t think that the JDK, if written from scratch, would still suffer from “JavaBean-o-mania™” as much. So here are a couple of rules that could be followed in new APIs, to get things a bit cleaned up:

  1. First off, decide whether your API will mainly be used in a Spring-heavy or JSP/JSF-heavy environment or any other environment that uses JavaBeans™-based expression languages, where you actually WANT to follow the standard convention. In that case, however, STRICTLY follow the convention and don’t name any information-retrieval method like this: “File.length()”. If you’re follwoing this paradigm, ALL of your methods should start with a verb, never with a noun / adjective
  2. The above applies to few libraries, hence you should probably NEVER use “get” if you want to access an object which is not a property. Just use the property name (noun, adjective). This will look much leaner at the call-site, specifically if your library is used in languages like Scala. In that way, “File.length()” was a good choice, just as “Enum.values()”, rather than “File.getLength()” or “Enum.getValues()”.
  3. You should probably ALSO NOT use “get” / “set” if you want to access properties. Java can easily separate the namespace for property / method names. Just use the property name itself in the getter / setter, like this:
    public class MyBean {
        private int myProperty;
    
        public int myProperty() {
            return myProperty;
        }
    
        public void myProperty(int myProperty) {
            this.myProperty = myProperty;
        }
    }
    

    Think about the first rule again, though. If you want to configure your bean with Spring, you may have no choice. But if you don’t need Spring, the above will have these advantages:

    • Your getters, setters, and properties have exactly the same name (and case of the initial letter). Text-searching across the codebase is much easier
    • The getter looks just like the property itself in languages like Scala, where these are equivalent expressions thanks to language syntax sugar: “myBean.myProperty()” and “myBean.myProperty”
    • Getter and setter are right next to each other in lexicographic ordering (e.g. in your IDE’s Outline view). This makes sense as the property itself is more interesting than the non-action of “getting” and “setting”
    • You never have to worry about whether to choose “get” or “is”. Besides, there are a couple of properties, where “get” / “is” are inappropriate anyway, e.g. whenever “has” is involved -> “getHasChildren()” or “isHasChildren()”? Meh, name it “hasChildren()” !! “setHasChildren(true)” ? No, “hasChildren(true)” !!
    • You can follow simple naming rules: Use verbs in imperative form to perform actions. Use nouns, adjectives or verbs in third person form to access objects / properties. This rule already proves that the standard convention is flawed. “get” is an imperative form, whereas “is” is a third person form.
  4. Consider returning “this” in the setter. Some people just like method-chaining:
        public MyBean myProperty(int myProperty) {
            this.myProperty = myProperty;
            return this;
        }
    
        // The above allows for things like
        myBean.myProperty(1).myOtherProperty(2).andThen(3);
    

    Alternatively, return the previous value, e.g:

        public int myProperty(int myProperty) {
            try {
                return this.myProperty;
            }
            finally {
                this.myProperty = myProperty;
            }
        }
    

    Make up your mind and choose one of the above, keeping things consistent across your API. In most cases, method chaining is less useful than an actual result value.

    Anyway, having “void” as return type is a waste of API scope. Specifically, consider Java 8’s lambda syntax for methods with / without return value (taken from Brian Goetz’s state of the lambda presentations):

    // Aaaah, Callables without curly braces nor semi-colons
    blocks.filter(b -> b.getColor() == BLUE);
    
    // Yuck! Blocks with curly braces and an extra semi-colon!
    blocks.forEach(b -> { b.setColor(RED); });
    
    // In other words, following the above rules, you probably
    // prefer to write:
    blocks.filter(b -> b.color() == BLUE)
          .forEach(b -> b.color(RED));
    

    Thinking about this now might be a decisive advantage of your API over your competition once Java 8 goes live (for those of us who maintain a public API).

  5. Finally, DO use “get” and “set” where you really want to emphasise the semantic of the ACTIONS called “getting” and “setting”. This includes getting and setting objects on types like:
    • Lists
    • Maps
    • References
    • ThreadLocals
    • Futures
    • etc…

    In all of these cases, “getting” and “setting” are actions, not property access. This is why you should use a verb like “get”, “set”, “put” and many others.

Summary

Be creative when designing an API. Don’t strictly follow the boring rules imposed by JavaBeans™ and Spring upon an entire industry. More recent JDK APIs and also well-known APIs by Google / Apache make little use of “get” and “set” when accessing objects / properties. Java is a static, type-safe language. Expression languages and configuration by injection are an exception in our every day work. Hence we should optimise our API for those use cases that we deal with the most. Better, if Spring adapt their ways of thinking to nice, lean, beautiful and fun APIs rather than forcing the Java world to bloat their APIs with boring stuff like getters and setters!

Tags: , , , , , , , , ,

20 responses to “Bloated JavaBeans™, Part II – or Don’t Add “Getters” to Your API”

  1. ericjs says :

    Just a couple of minor points:

    I’m pretty sure File existed before the notion of JavaBeans, and while methods added later may have been influenced by JavaBeans, I think the tendency to use the word “get” in function names preceded it, if less consistantly.

    I don’t think the way in which verbs are typically used for method names, like get and set, is in the infinitive form. I’m pretty sure they are in the imperative form. The caller is telling the object what to do: “get me this property!” Is / has type methods are an exception where the metaphor is more like making a exploratory true/false statement about the thing in question, e.g. isReady = “the object is ready”; hasChildren() “the object has children” so that you may use that statement in some comparison or boolean expression “if ( the-object-is-ready OR the-object-has-children)…”. The verb used in such statements is third person present tense. (At least I believe this is all true in English. I don’t know if people naming things in other languages adhere to the same conventions.)

    I more or less agree with your dislike of the JavaBean convention and setter bloat, and your API advice. I’d much rather have the notion of interface “properties” and some flexible way of tying implementations to them. I do think that horse has long escaped from the stable though. I wonder if one minor amelioration might still be possible in changing the JavaBean standard to allow setters to return the value passed to the setter, which would at least allow those who cared to use this convention.

    I would add that in making the choice of whether you have motivation to make a given class to JavaBean, if you don’t, you can always write a JavaBean conformant adapter class to wrap it.

    But I really don’t get your distinction between setting and getting actions and property accesses. Can you explain more / give an example?

    • lukaseder says :

      Thanks for the feedback, Eric. Agreed, imperative is probably better than infinitive. I’ll fix that in the post. If “is” / “has” has a different metaphor, then they’re not “getters” because the obtained value is not a property. E.g. “hasChildren()” is probably a shortcut for “children().size() > 0″. So a sensible design shouldn’t allow thinking about like “getHasChildren()” or “setHasChildren()”. “isReady()” on the other hand might just as well be called “ready()”. “isReady()” on its own is fine if you want some additional fluency at the call-site, e.g. if (resource.isReady()). But if this is the “getter” for the “isReady” property, the “setter” should be “resource.isReady(true)”

      Anyway, I think that we shouldn’t always care that much about horses having escaped from the stable. The JPA / CriteriaQuery horse has escaped, too and it is “accepted” and “adopted”. Yet, it’s boring and wrong in many aspects. I know, we have grown used to Java being hyper-backwards-compatible. But with all the competition today, at some point, Java will have to move forward. Just as Mac OS X has forced Microsoft in a long struggle to finally dare something really new with Windows 8.

      The distinction between property access and “getting” / “setting” actions is the same as what you described with the imperative form. In my opinion, the semantics of property access is not strong enough to justify using such verbs, most importantly for the “getter”(see also the post’s title). Typically, the containers listed in point 5 have a stronger access semantics than beans – at least to me. I’m not sure if that’s clearer, now :-)

      • ericjs says :

        Sorry, I still don’t get the distinction you are making. Semantically “int getX()” is equivalent to X where X is an int property. It’s just more awkward in trying to read the java like natural language in the context of an expression other than simple assignment. Maybe I don’t understand what you mean by “Property”. What I mean by Property in this context is some state (mutable or not) carried by an object which may or may not be a direct value of the object.

      • ericjs says :

        Actually, let me revise my definition slightly. Using the word “state” may be asking for trouble. Let’s say a Property answers some question about the object…a Property which is not read-only (has a setter) also allows you to change the answer to that question.

  2. ericjs says :

    Sorry, one brainfart in my last post…I should have said “to allow setters to return this”. And I was assuming that the JavaBeans standard mandates a void return type, but maybe that’s not true…

    • lukaseder says :

      Hmm, I was sure I had read somewhere, that “void” is mandatory according to the JavaBeans standards. However, reading through the specs, I can only see that there are naming conventions that are “not mandatory”. Those conventions include

      8.3 Design Patterns for Properties
      8.3.1 Simple properties
      By default, we use design patterns to locate properties by looking for methods of the form:
      public get();
      public void set( a);

      But there is no mention of the setter having to return void

  3. Mladen Adamovic says :

    After 5 years of being bored with getters and setters in Java I decided to start creating them unless obviously necessary and started naming variables as public. Even I developed ORM tool which assumes that you will not create getters and setters, but rather use public variables. Works as a charm, wonderful.

  4. agentgt says :

    Getters I don’t mind so much (that is typing the additional “get”) but regular Setters are painful. I’ll say one thing… at least Java is very standard and consistent (albeit lame) on what constitutes a property.

    Compare this to Python where there are a dozens of practices out their (name, method, @decorator, true property… etc).

    One thing I like about the standard prefix “set” for Setters is I know that it is a property I’m setting although it is annoying that the standard return is void. Its important that I know that I’m setting a property as my expectations are this should only change the state of the object and other behavior should not happen (I hate when setting something kicks of a whole bunch of behavior). Likewise the same from “get” I expect the behavior to *not* do anything dynamic and just return the property. Properties that don’t have “get” or “set” in front of them are free to do dynamic stuff. That is “get” and “set” in most Java programmers mind is equivalent to direct member setting (which is how it looks like in C# ala Bertrand Meyer’s unified access).

    Because I prefer immutable objects what I really wish Java had that Scala, Groovy and others have is named parameter object construction. That is I wish I could define immutable data structs that are easy to instantiate using the names of the fields.

    Although the fluent builder pattern is frequently used for DSL its probably most used because constructing a giant immutable object is a PITA in Java.

    There are a couple of Eclipse code generators projects (bpe), code instrumenters (lombok), and code translators (xtend) that make this somewhat easier but its still annoying and I think will worsen when Java 8 lambda support comes out.

    • lukaseder says :

      I agree with your feelings about setting properties and communicating the fact that no other actions are triggered. I guess that after all, “get” and “set” – while adding lots of bloat – are just easier rules to follow than semantically meaningful English tenses and verb forms…

  5. Frisian says :

    For a start, it’s java.io.File, not java.util.File ;-)

    java.io.File is probably the worst conceivable example to come up with:
    – It covers both files and directories, thus violating the Single-Responsibility-Principle, thus having too large an API anyway.
    – toPath() was only added in Java 7. getPath() returning String was already there, so a different prefix was necessary in order to preserve backwards compatibility.

    That said, I don’t think of getters and setters as a problem:
    – Immutable objects don’t have setters by definition, which leaves only getters.
    – Unlike JavaBeans, Fluent Interfaces aren’t really meant for being used with reflection, because they are supposed to make hand-written code more succinct. Hence, writing name(“Name”) instead of setName(“Name”) shouldn’t cause too much problems.
    – If there are too many getters, chances are, that the class has too many properties and should therefore be broken up into smaller ones. java.nio.file.Path is a good example: A lot of getters could be removed from java.io.File because of toPath(), which offers the same information in a Path object.
    – Having one convention is better than having none or two for that matter.

    • lukaseder says :

      (thanks for the hint about java.util.File… who’d that slip in…? ;-) )

      I think that it is still a good example, because it shows how easy it is for any API designer to get the naming schemes around these things wrong. But we could find other examples

      e.g. java.math.BigInteger.setBit(int). This method returns a *new* BigInteger with *some* properties of the old one. How is that supposed to be a setter?

      e.g. java.util.Deque.getFirst() as opposed to peek() and peekFirst(). Why use “get” in this context when “get” is supposed to be an indicator for property access? (Maybe to retrofit Deque onto LinkedList, which was added in Java 1.2? eek)

      People get this wrong very often, because the idea of having properties by convention is wrong. Java is very explicit in all other things except for JavaBeans, where a lot of implicitness defines rules applied by huge stacks of reflective APIs such as Spring / JSF / JSP, etc.

      My post is trying to hint at the possibility to abandon this convention all together to put some pressure on those stacks / on the JCP, to finally get this mess right. There is no point of misusing methods with arcane naming conventions as getters / setters, when in fact you want to manipulate properties.

      I like your point about fluent interfaces, which are a rather new trend (give or take 5 years since Martin Fowler introduced another useless, bloating prefix “with”). Maybe fluent interfaces should be the first ones to abandon getters and setters…

    • agentgt says :

      I agree with you accept that using getters/setters for serialization purposes and property reflection is no longer needed now that Java has annotations.

      In fact one of the rarely used standard Java Bean annotations that few know about or use is @ConstructorProperties (http://docs.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html). Xtend, Scala and Lombok also have @Property annotations.

      Thus I feel Lukas does have a point that getters/setters are holding back the language or at least create a bitter taste for those that are new to the language.

      • lukaseder says :

        Unfortunately, as often, Java only went half the way and only added @ConstructorProperties, instead of something more formal and complete like the @Property annotation from other platforms that you’ve mentioned.

    • ericjs says :

      I feel like a couple of things are getting muddled in parts of this conversation. There’s JavaBeans and then there’s the convention of setters and getters. JavaBeans uses that convention, and the presence of JavaBeans has probably done some to encourage its proliferation, but the convention exists above and beyond (and appeared before) JavaBeans. java.io.File is not a JavaBean.

      One of the earliest motivations and most common uses of JavaBeans is simply to have a simplified interface to something that packages things up to look like a “struct”. For example, you often see them created as a way to package some information from a more complex API for use in a web templating language. (There is of course more to JavaBeans, stuff around reflection and listeners, etc, but it is the simple “struct” aspect that is most germane to the getter and setter convention.)

      The motivation behind getters and setters is a slightly more abstract version of that motivation, which is what I have been calling a Property (with slight uncertainty whether you mean the same thing by the word) which some other languages use for their more elegant formalized feature for the same purpose. That purpose is to expose a value semantic for reading and / or writing without directly exposing its representation (e.g. get and set may work in terms of an int, but the object may have no such int…it may be stored in some other form, inside a data structure, delegated to some other system, whatever). Essentially, letting the API user think in terms of the object having attributes.

      I would also note that not every method that happens to start with get or set is motivated by the Property notion, those happen to just be really obvious words to use in function names. I would guess this to be true of many methods in File which pre-exist JavaBeans and the commoness of the setter / getter convention.

      I would guess this is what you are getting at in your advice #5 but I don’t think you’ve quite nailed the distinction. The problem with ‘ACTIONS called “getting” and “setting”’ is that actual setting and getting “actions” are really about implementation. I would instead talk about methods that return a value or pass a value that should not be thought about simply as attributes of the object. That distinction can get a little fuzzy and may sometimes be debatable, and is the kind of thing that people often are not clear on when they first design an API. I think the question to be asked there is should the user know about some “doing” that goes on along with the getting or setting? Is that “doing” part of the semantics of the API itself? In File, we could probably argue about getFreeSpace() or even getCanonicalPath().

      If I’m not barking up a different tree there, in terms of where you are trying to go with #5, then there is another problem. If some doing is really part of the API semantics, then “get” and “set” don’t do a very good job of communicating it

      • lukaseder says :

        You’re putting things more clearly into words than I did. I like your notion of a “struct” semantics when it comes to a bean with its properties. And it is precisely this “struct” semantics that makes me feel like using method name conventions involving “get” and “set” prefixes is the wrong tool to implement that semantics. As you stated, other languages have introduced more elegant formalised features for this purpose. I wish Java would finally do that and let us get rid of these “getters” and “setters”, which never clearly communicate whether they’re doing

        • Property access (like myBean.getMyProperty())
        • Arbitrary data access (like file.getFreeSpace())
        • What I fuzzily called ACTIONS (like ThreadLocal.get())

        In other words, my post is trying to say the same as your conclusion:

        If some doing is really part of the API semantics, then “get” and “set” don’t do a very good job of communicating it

        I’m saying that “get” and “set” don’t do a very good job of communicating anything at all, except in some exceptional cases like listed in #5 (e.g. it does make sense to write list.set(index, value)).

      • ericjs says :

        We hadn’t really pinned pinned down what the semantics of get and set are exactly. In thinking about it, I’ve come to a couple of realizations.

        First of all the semantics of set and get, are simply assignment and reference. set__ is assignment, and equivalent of the = in the language syntax. get__ is reference (I do not say “retrieval”, that is implementation)…a way of using a thing in an expression. get__and set__ are used when the language itself does not have syntax for referencing and assigning the thing being set or get. Property access setters and getters are not needed in a language with property syntax.

        But in the examples you gave of set being used in ThreadLocal or List, the same thing is going on, just not with properties. Set and get here are used for assignment and reference of things the language does not have native syntax for. If threadlocal was a modifier you could put on a variable instead of being implemented as a class, you wouldn’t need get or set, you would simply reference or assign to the variable. If Java had built in syntax for lists, as some languages do (or as it does for arrays), you would not need get or set methods there either.

        So set__ and get__ for properties are part of a larger, more general convention. Which leads me to think your idea of instead using methods without the set and get for the same purpose is a bad idea.

        • lukaseder says :

          Thanks Eric, these are some interesting thoughts. You properly relate what I “felt” in #5 with what some people (including me) understand by property access.

  6. Mladen Adamovic says :

    Ericfs: “First of all the semantics of set and get, are simply assignment and reference. set__ is assignment, and equivalent of the = in the language syntax. get__ is reference…”

    Great said. I’m thinking… If get_ returns mutable object, there is no advantage over property access. If set_ doesn’t create new object, there is no advantage over property assignment.

    Strings are immutable objects, so for certain Java types there might be adventages, however those advantages are so negilable that in my High Performance ORM you wrote something like this:

    ProsConsEntity newEntity = new ProsConsEntity();
    newEntity.title = title;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 1,964 other followers

%d bloggers like this: