Getters & Setters and its goodness and evilness

If you are a DZone reader, you will have read many posts about getters and setters and its evilness. Getters and setters are the response to an old Object Oriented principle which says that object’s implementation must not be exposed. On the other hand, there is also another old principle called Uniform Access Principle which says that client code should not be affected by a decision to implement an attribute as a method or field. Unfortunately, Java doesn’t follow this last principle.

Don’t Expose the Implementation

Currently, the most used IDE’s can generate the getters and setters for fields. Sometimes this doesn’t help, and developers automatically generate unnecessary getters and/or setters. This next example could be seen as a situation where generating getters and setters automatically is a bad practice:

package com.wordpress.j2eethoughts.ooPrinciples; public class Odometer{ private BigDecimal total; private BigDecimal partial; public Odometer (){ total = BigDecimal.ZERO; partial = BigDecimal.ZERO; } public BigDecimal getTotal(){ return total; } public void setTotal(BigDecimal total){ this.total = total; } public BigDecimal getPartial(){ return partial; } public void setPartial(BigDecimal partial){ this.partial = partial; } }

Now let’s explain because this is a bad practice. Maybe at a first glance, you may think that this implementations satisfies the principle of not expose the internal implementation of the object. Unfortunately, this is not true, everything is exposed. There isn’t much difference between this implementation with getters and setters and the hypothetical implementation with public fields. In addition, you can do illegal things with this implementation, as decrement the number of Kilometres of the Odometer. The unique advantage between this implementation and one with public fields is that you could attach some functionality in any function, like logging, checking permissions…

A more correct implementation for this class would be:

package com.wordpress.j2eethoughts.ooPrinciples; public class Odometer{ private BigDecimal total; private BigDecimal partial; public Odometer (){ total = BigDecimal.ZERO; partial = BigDecimal.ZERO; } public BigDecimal getTotal(){ return total; } public BigDecimal getPartial(){ return partial; } public void resetPartial(){ partial = BigDecimal.ZERO; } public void increment(BigDecimal inc){ partial.add(inc.abs()); total.add(inc.abs()); } }

This class implementation ensures that nothing wrong is done with the Odometer, Kilometres can only increase and you can’t rig the Odometer decreasing the total amount of Kilometres made.

Uniform Access Principle

As we have explained before, Java doesn’t satisfy the Uniform Access Principle, for this reason we will explain it using Scala. The client code must not be affected if the developer decides to implement an attribute as a method or as a field. For illustrating this example we will use a Circle class. There will be two different implementations for the attributes perimeter and area.

package com.wordpress.j2eethoughts.uap import Math.Pi class CircleVal (radius : Int){ val perimeter = 2 * Pi * radius val area = Pi * radius * radius } class CircleDef (radius : Int){ def perimeter = 2 * Pi * radius def area = Pi * radius * radius }

The client uses these classes exactly the same way in both implementations. The client doesn’t care if the developer had decided to implement these attributes as methods or as fields.

package com.wordpress.j2eethoughts.uap object Main { def main(args : Array[String]) : Unit = { val c1 = new CircleVal(4) println(c1.perimeter) println(c1.area) val c2 = new CircleDef(4) println(c2.perimeter) println(c2.area) } }

This post is not supposed to decide about the evilness or goodness of getters and setters, its only intention is to think about its use. So, we would be very glad if after reading this post, you think twice before ask your IDE to automatically generate the getters and setters.

9 Responses

  1. would like to mention that this is the core of object-oriented : encapsulation (which tells data and code that works on that data belong to them same class; doing this raises cohension of a class, a good thing)

    also, you provided a nice alternative for not using setters.

    a nice alternative for not using getters is the principle “tell, don’t ask”. instead of using getters to get all the stuff you need and then generate something using that data, the “thing” to do is tell the object that has the data to generate that something itself

    to think of it, it’s the same principle for what you suggested as alternative for setters.

    here are more details :
    http://pragprog.com/articles/tell-dont-ask

    or just search the internet about the principle :)

    this principle fits very well with the idea of encapulation

    ps:
    1. these ideas might make your head hurt at first, but that’s how oo is.

    it doesn’t fit real life perfect as you don’t say car.steerLeft() as if the car is steering by itself. instead think messagging. method calls are messages to objects

    2. so far, i haven’t figured out how hibernate justifies it’s intensive use of setters/getters. perhaps someone might enlighten me

  2. You say Java doesn’t follow the Uniform Access Principle, but the Java code I write definitely does. What you meant to write is that Java IDEs don’t follow that principle!

    • Hello Dave,
      Maybe I haven’t explained it correctly.
      What I meant to say is that in Java there is no way to call a method as a field. The syntax is different, so when you’re asking for an attribute you know if you are calling a method or a field. Of course that you could do things correctly, I am not saying that. I’m saying that many people use the “Generate Getters/Setters” option in Eclipse without analyse if it’s necessary or not.

      This post’s intention is not to attack the getters and setters, only tries to make people think about them and its indiscriminate use. Some times you don’t need the setter and/or the getter.

  3. Hi,

    Do you have a solution if you happen to be using OpenJPA over your Odometer class and need to have a public setter?

    Mike

    • HI Michael,

      I don’t know if I understood you but I’ll try to answer.
      I’ve never used OpenJPA, but in Hibernate if you annotate the field instead of the method you don’t need a public setter.

      If this is not what you were looking for, please let me know!

  4. […] This post was mentioned on Twitter by IBBoard and Disphunktion, Alltop Java. Alltop Java said: Getters & Setters and its goodness and evilness http://bit.ly/axfTr7 […]

  5. Don’t forget that BigDecimal is immutable else we need to think fluent and fonctional.

    • I used BigDecimal just for the precision. Using floats you can always get surprised (float’s precision is not the best in the world). Despite that, you are right, maybe for this example a float, or even an int, could be valid.

Leave a reply to Josep Prat Cancel reply