Don’t use Setters and Minimize Getters
In the modern IDE’s, getters and setters are created automatically or in
some cases including a specific library creates them automagically, injecting
these accessor methods. This so-called feature of the IDE is cool but evil! We
also have libraries that do this in code, like Lombok. Programmers don’t write
these methods and the IDE enables us to do these incorrect things quickly.
Let me take a step back for a moment. I know a lot of you are surprised
by the topic name and let us get into the details of it. In an object-oriented
world, an object represents a real-world entity. You always interact with the
object through its behavioural methods. What these getters/setters do is that
they expose the internals of the object and provide you with a mechanism to
modify an object's internal state.
Let us take an example. Suppose you have an employee object with the
following data
Employee Object
|
|
Name:
|
Sherlock
Holmes
|
Age
|
130
|
Address
|
221-B
Baker Street, SW1A2NE
|
Here, assume you have setters. Any process that has access to the
Employee object can modify this object. Say, it can change the name or age
etc., basically introduces what we in today’s parlance call “Side-effects”. This
change violates the fundamental principle of object-oriented practice –
Encapsulation. Why does this happen?
programmers think an object as a data structure which holds the data rather
than think it as a real-world object with its defined behaviour.
Side-effects are the enemy of any developer as it causes hard to debug
bugs, hard to write test cases etc.,
If you are creating the object either through a constructor (or an
overloaded constructor) or through a public method which invokes a private
constructor, it avoids any “Mutation” of state and hence restricts side
effects. Also, it avoids what is called “failure atomicity”, which means either
you get the object, or you don’t. you don’t get an inconsistent object
Now let’s discuss getters.
Getters (also known as accessor methods) expose an object's internal
state. This thinking leads us to expose the internals of the object, say the
age or an address outside without the context of whose age it is. This breaks
(again!) the encapsulation principle. We can always argue that getters are
methods that take the private variable and show it outside (mostly, with very
few changes), but why should a private variable (its an object state at the end
of the day) be exposed outside? Can't the consumers access the required state
through behavioural methods? I’m not saying don’t use getters ever, just review
every getter method and appropriately share the value you would want to the
outside world, rather than the internal state of that object. This in simple
terms, means that don’t directly expose the value of the private variable
to the outside world. Think of how this can be exposed as an object’s
attribute/behaviour. The key here is “don’t ask for information to do something.
Instead, as the object that has the information to do it for you”. CRC cards
enforce this type of “object thinking”.
Let’s illustrate this with an
example.
Asking for “get me the age” from an employee object, where age is a private attribute is a getter, whereas “get me if the employee is of a valid
age for employment” is a behaviour of the object.
This is the first of many posts on the series of “Object Thinking”. Stay
tuned.
Comments