Getter and setters, also known as accessors and mutators; and predicates are very useful to attain abstractions and encapsulation in object-oriented programming. In schools, when you initially learn about these, you start to use them everywhere you can. You start a class, add some private class attributes at some point and then add getters, setters, and predicates for each attribute. This is not okay and you should look into the context and make a judgment.
To overcome verbosity, I will use the term GSP to refer to getter, setter, and predicate in the rest of the article. Similarly, GSPs will refer to the plurals of these terms.
There are 4 possible cases of having or not having GSPs.
- Not having GSPs at all, allowing the direct use of all class properties.
- Having GSPs all the time. Exposing every private property via GSPs.
- Not having GSPs at all, allowing the direct use of some class properties that are required to be exposed.
- Having GSPs at appropriate times and not exposing every private property.
In the above list, we will not discuss 1 and 2 much, because the options are simply stupid to follow. It is like to find an easy way out of software design, and you can’t. Our focus will be to discuss the pros and cons of 3 and 4.
Even though the benefits of having getters, setters, and predicates are overwhelming, but it doesn’t mean that you should have them for every property in the class. Always lookout for the context. GSPs expose information about a class. The less a user class knows about a used class, the lower the coupling would be between them. There is a strong reason in making a property private and that is not letting other classes see them, and in words of Uncle Bob Martin:
There is a reason that we keep our variables private. We don’t want anyone else to depend on them.Clean Code by Robert C. Martin
Find below the benefits of having getters, setters, and predicates. And remember, these are benefits of having them only when they are appropriate.
- Immutability: First and the biggest advantage of getters/setters is immutability. An extra layer of abstraction helps you in deciding the state of your object.
- Refactoring: They allow you to follow the Uniform Access Principle. Are you simply returning class properties or doing some calculations to generate the return value? No one needs to know. The less one module knows about the other (especially its internal implementation), the more loosely-coupled they are. I put this as an added advantage to refactoring because you can refactor without hesitation. You can change a simple returning field to calculation and vice versa with confidence.
- Third-Party Access: They are very useful if you are writing a library that will be used by third-party applications. They will help in making sure the communication happens as expected.
- Validation: This is connected to the above two benefits, you can have validation in the getter, setters right now, or later on.
- Consistency: You will access a field in a consistent way.
- Agility: You don’t know what is coming next, at least sometimes. GSPs allow you to be prepared to keep the changes to the smallest scope. For example, type change in your class field.
- Polymorphism: A child class can decide differently on how to set or get a class property.
Find below some of the disadvantages of having getters, setters, and predicates. These disadvantages are for the cases when they are appropriate. Because “having GSP all the time” is a superset of “having GSP appropriate times”, it denotes that these disadvantages also apply to have GSP all the time among several others that I will not go into (because again it is just stupid).
- First of all, you should know that having getters and setters for every class field is not the way to go. It breaks encapsulation and is simply a bad design. Don’t do it. That is one step away from making all data members public.
- Extra abstraction layer will consume some extra execution time. Although very low and acceptable in most cases, it is there.