97 Things
Published in

97 Things

Behavior Is ‘Easy’, State Is Hard

When I was first introduced to object-oriented programming, some of the very first concepts taught were the triple of polymorphism, inheritance, and encapsulation. And to be honest we spent quite some time trying to understand and code with them. But, at least for me, too much emphasis was given to the first two, and very little to the third and most important of all: encapsulation.

Encapsulation allows us to tame the growing state and complexity that is a constant in the software development field. The idea that we can internalize the state, hide it from other components, and offer only a carefully designed API surface for any state mutation is core to the design and coding of complex information systems.

But, at least in the Java world, we have failed to spread some of the best practices about the construction of well-encapsulated systems. JavaBean properties on anemic classes that simply expose internal state through getters and setters are common, and with Java Enterprise architectures we seem to have popularized the concept that most — if not all — business logic should be implemented in service classes. Within them we use getters to extract the information, process them to get a result, and then and put the result back into our objects with setters.

And when the bugs bite, we dig through log files, use debuggers, and try to figure out what’s happening with our code in production. It’s fairly ‘easy’ to spot bugs caused by behavior issues: Pieces of code doing something they’re not supposed to do. On the other hand, when our code seems to be doing the right thing and we still have bugs, it becomes much more complicated. From my experience, the hardest bugs to solve are the ones caused by inconsistent state. You’ve reached a state in your system that shouldn’t happen, but there it is — a NullPointerException for a property that was never supposed to be null, a negative value that was only be positive, and so on.

The odds on finding the steps that led to such inconsistent state right are low. Our classes have surfaces that are too mutable and too easily accessed: Any piece of code, anywhere in the system, can mutate our state without any kind of checks or balances.

We sanitize user-provided inputs through validation frameworks, but that ‘innocent’ setter is still there allowing any piece of code to call it. And I won’t even discuss the likelihood of someone using UPDATE statements directly on the database to change some columns in database-mapped entities.

How can we solve this problem? Immutability is one of the possible answers. If we can guarantee that our objects are immutable, and the state consistency is checked on object creation, we’ll never be able to have an inconsistent state in our system. But we have to take into account that most Java frameworks do not cope very well with immutability, so we should at least aim to minimize mutability. Having properly coded factory methods and builders can also help us to achieve this minimally mutable state.

Therefore, don’t generate your setters automatically. Take time to think about them. Do you really need that setter in your code? And if you decide that you do, perhaps because of some framework requirement, consider using an anti-corruption layer to protect and validate your internal state after those setter interactions.




Tap into the wisdom of experts to learn what every great practitioner should know, no matter what technology or techniques you use. With the 97 short and extremely useful tips, you’ll expand your skills by adopting new approaches while learning best practices.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Edson Yanaga

Edson Yanaga

Java Champion & Microsoft MVP. Empowering developers worldwide to deliver better software faster as Director of Developer Experience at Red Hat.

More from Medium

Creating a Deep vs Shallow Copy of an Object in Java

Finding the Articulation point

Object-Oriented Programming(OOPs)

10 Things I’ve Learnt In My First Year As A Java Developer

Global’s Technology & Digital Early Careers Programme