Raimund Krämer

Software Craftsman, Consultant, Coach

First of all, I don’t advocate for getters and setters at all. Don’t use them (especially setters) if you find an alternative. There usually is a better design. I won’t go into that here.

I want to focus on a bigger, very common problem: Many of the people who use getters and setters a lot – because they’ve always done it that way, or “by convention”, or simply because they assume that it’s necessary – use them in a way that defeats their purpose, much worse than the design implications of their usage itself. Have you seen code that looks like this?

/**
 * Getter for the field {@code phoneNumber}.
 */
public String getPhoneNumber() {
    return phoneNumber;
}

/**
 * Setter for the field {@code phoneNumber}.
 */
public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
}

Stating in the public contract that the methods give access to a specific field essentially makes the field public. The whole purpose of getters and setters (while still not without problems for other reasons) is that we don’t make an assumption as to where the value comes from without breaking the clients. Why would a client care whether the getter accesses the value in a field or somewhere else? That’s the one thing we actually want to abstract. Much better (although still redundant) documentation comments would be “Get the phone number” and “Set the phone number”. The implementation could get the phone number from a different object or from a hash map or somewhere else completely. Even though you might write (or generate) the getter and setter “for a field”, this is not the case when looking at it from the caller’s perspective. If you consistently write getters and setters that (“by convention”) always access a field of the same name, then you could as well just make the field public and thus at least reduce boilerplate in your code. Of course, don’t do that (!), but it would be a local maximum compared to “wrapping” fields with getters and setters that even state the name of their backing field as part of their public contract. A valid exception might be when using a framework that expects getters and setters to be named in accordance with the field’s name because of reflection or code generation, which is quite common in the Java world, but in cases where I’ve seen the anti-pattern that was often not the case (and those tools often don’t even require a corresponding backing field of a certain name); rather, I suspect that such frameworks may have taught these developers some bad habits, and that some IDEs might generate bad Javadoc by default which the developers then just accept as is.