Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I see most immutable POJOs written like this:

public class MyObject {
    private final String foo;
    private final int bar;

    public MyObject(String foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    }

    public String getFoo() {
        return foo;
    }

    public int getBar() {
        return bar;
    }
}

Yet I tend to write them like this:

public class MyObject {
    public final String foo;
    public final int bar;

    public MyObject(String foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    }
}

Note the references are final, so the Object is still immutable. It lets me write less code and allows shorter (by 5 chars: the get and ()) access.

The only disadvantage I can see is if you want to change the implementation of getFoo() down the road to do something crazy, you can't. But realistically, this never happens because the Object is immutable; you can verify during instantiation, create immutable defensive copies during instantiation (see Guava's ImmutableList for example), and get the foo or bar objects ready for the get call.

Are there any disadvantages I'm missing?

EDIT

I suppose another disadvantage I'm missing is serialization libraries using reflection over methods starting with get or is, but that's a pretty terrible practice...

share|improve this question

3 Answers 3

up vote 16 down vote accepted

Four disadvantages that I can think of:

  1. If you want to have a read-only and mutable form of the same entity, a common pattern is to have an immutable class Entity that exposes only accessors with protected member variables, then create a MutableEntity which extends it and adds setters. Your version prevents it.
  2. The use of getters and setters adheres to the JavaBeans convention. If you want to use your class as a bean in property-based technologies, like JSTL or EL, you need to expose public getters.
  3. If you ever want to change the implementation to derive the values or look them up in the database, you'd have to refactor client code. An accessor/mutator approach allows you to only change the implementation.
  4. Least astonishment - when I see public instance variables, I immediately look for who may be mutating it and worry that I am opening pandora's box because encapsulation is lost. http://en.wikipedia.org/wiki/Principle_of_least_astonishment

That said, your version is definitely more concise. If this were a specialized class that is only used within a specific package (maybe package scope is a good idea here), then I may consider this for one-offs. But I would not expose major API's like this.

share|improve this answer
    
Great answers; I have disagreements with some of them, but I'm not sure this site is the best forum for discussion. In short, 1) I can break others by using the mutable form where they assume it's immutable (perhaps I should add final to the class in my examples), 2) I agree, 3) I would argue it's no longer a POJO in that case, 4) I agree for now, but hopefully discussions like this can change what is least astonishing :). –  Cory Kendall Mar 18 '13 at 20:32
1  
5) You can't safely expose inherently mutable classes/types - like arrays. The safe way is to return a copy from a getter each time. –  Clockwork-Muse May 28 '13 at 16:19

One possible disadvantage I can see offhand is that you're tied to the internal representation of the data in the class. This probably isn't a huge deal, but if you use the setters, and you decide that foo and bar will be returned from some other class defined somewhere else, the classes consuming MyObject would not be required to change. You would only need to touch MyObject. However, if you use the naked values, then you would have to touch everywhere your MyObject i used.

share|improve this answer

In layman's words:

  • You violate encapsulation in order to save some lines of code. That defeats the purpose of OOD.
  • Client code will be hard coupled to the names of your class members. Coupling is bad. The whole purpose of OOD is prevent coupling.
  • You are also very sure your class will never need to be mutable. Things change. Change is the only thing that is constant.
share|improve this answer
3  
How is this a violation of encapsulation? Both versions are as exposed to the outside world as each-other (with read-only access). You're correct about the hard coupling and inflexibility of change, though, I won't argue that. –  KChaloux May 28 '13 at 15:29
1  
@KChaloux No. Version 1 is not as exposed. If you refactor it and change the name of foo to foo2, the outside world wouldn't notice. In version 1 you promise not to break the contract. In version 2 you promise not to refactor. –  user61852 May 28 '13 at 16:17
1  
@KChaloux You confuse "encapsulation violation" with "code failing to compile and having to waste time fixing it", one happens first. The second happens later. To make it clear: encapsulation is already violated in the present. The innards of your class are no longer encapsulated in the present time. But client code will break in the future if class changes in the future, because encapsulation was broken in the past. There are two different "breaks", encapsulation today, client code tomorrow, because of lack of encapsulation. –  user61852 May 28 '13 at 18:38
1  
I'm getting a warning that we're going into too-long-discussion territory, so I'll stop it here, but I don't agree. Perhaps this is because I'm spoiled by languages that offer proper properties, or languages like Scala that support a more functional paradigm, where it's common to expose immutable values, given the guarantee that they are in fact immutable. –  KChaloux May 28 '13 at 18:42
1  
Technically, when you use getters/etc. the client code will be hard coupled to method names instead. Look at how many libraries have to include old versions of methods with a "deprecated" tag/annotation because older code is still reliant on them (and some people may still use them because they find them easier to work with, but you aren't supposed to do that). –  JAB May 28 '13 at 20:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.