Keep It Simple. Encapsulation.

Alexander Krupsky
Geek Culture
Published in
5 min readJun 1, 2021

--

When you face Object Oriented Programming (OOP) for the first time, you meet its three pillars: Encapsulation, Inheritance and Polymorphism. These principles are so simple and clear that experienced developers bully their young colleagues if the latter one ask to explain them. I think that they do it in vain. I have seen a lot of code that does not follow these principles or principles were used in an absolutely wrong way. And you know what? This code was written by mature developers.

I’m not going to explain all these principles in this story. Moreover, I don’t want to deep dive into them. My intention is to highlight common mistakes when you try to apply Encapsulation in your code.

Photo by Singkham from Pexels. Plant in a light bulb.
Photo by Singkham from Pexels

What is Encapsulation in Brief.

Thanks to Wikipedia, we know that:

In object-oriented programming (OOP), encapsulation refers to the bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object’s components.[1] Encapsulation is used to hide the values or state of a structured data object inside a class, preventing direct access to them by clients in a way that could expose hidden implementation details or violate state invariance maintained by the methods.

In simple words, Encapsulation is all about protecting your code from the incorrect usage.

The class below is a good example of Encapsulation. It has a hidden field to hold the current state of the car (color) and method to set it up. In such a way, we can be sure that no one can change this color unpredictably and state of our model cannot be corrupted.

Basic Encapsulation Example

Looks pretty simple. What can go wrong? Let's look at it on the example of the mentioned class.

Issue #1. Properties Avoiding.

I like how this issue is described by Jon Skeet on Stack Overflow:

Reason for disliking properties is because they look like fields — so developers who don’t understand the difference will treat them as if they’re fields

Indeed, if we look at the snippet below, we can see that there is a property that can be set from anywhere and we cannot protect it from the incorrect usage.

Property Declaration Example

There are a lot of examples how this code can be rewritten in a better way. You can find something like this:

State Protection Example

From the encapsulation point of view, it is a prefect code. You have private state that can be altered through your methods only. You have full control over the process. You can do anything before or after state is set (for example, validate input parameter or change other fields). You can be sure that no one can break your logic. It is solid. It is awesome.

But! The properties can do the same. Let’s see the next snippet, it represents the old-fashion style used to define properties (I haven’t seen it for ages).

Old-fashion Style for Properties Definition

If these two approaches are the same, why do we need to use properties? Let’s be honest. How often do you need to make any logic inside an object when you retrieve or change its state? Usually we have enough fingers on our hands to count these cases.

Properties are useful, because their definition takes one line of code while methods definition takes up to nine. Properties allow us to reduce class size and to improve code readability. Also, it significantly facilitates efforts if we are going to use some code to map objects.

Issue #2. We need methods to protect state everywhere.

To describe this issue, I’ve selected three major objects that exist at any project:

  1. Data Transfer Object (DTO).
  2. Domain Object.
  3. Entity.

DTO.

It is usually used to transfer some data from one layer to another. For example, DTO is used when a Single Page Application (SPA) consumes a public API to display required data.

In such a way, the lifecycle of this kind of objects is simple. They are created from an object, transferred from point A to point B, converted to another object, destroyed.

Please avoid methods to protect state in this kind of objects. As it is described in the previous paragraph, all logic that we apply to them is conversion. It is much simpler to use ordinary properties for that.

Domain Objects.

It is an entity/object related to a specific Domain Model. They should definitely protect their state, therefore be free to apply any protection approach here.

Entity.

It is a representation of data stored in a database. I refer these objects to DTOs, because I have not seen any database scheme that completely suits Domain Model. In common case, they differ due to some performance improvements and you need to convert entity to Domain Object and vice versa. Therefore these objects should be as simple as it is possible. Classes with plain properties will be sufficient in 95% of cases.

This approach allows you to save a lot of efforts to properly configure data access layer and to convert the entities.

Issue #3. Validation Inside the Setters.

From time to time I find some code similar to the code below.

Validation Example

Just imagine. You have a red car and once you decided to paint the car green. You go to shop, buy green paints, masking tape, painting suit, a paint gun, and whatever else you need. You bring this stuff in a garage, put the suit on, fill the paint gun with paintings, go to the car and suddenly you figure out that you cannot repaint the car. When you try to apply paints, the car tells you that this action is prohibited!

Why it happens? What business rule is responsible for that? What to do if we have different restrictions based on a painter or company rules that he/she employed? What to do if a new validation appears? Is it a good idea to modify car class in these cases? Will we break open-closed principal? There are a lot of questions.

We can avoid most of them if we move the validation to higher level. For example, to the class responsible for painting.

Higher Level Validation Example

I’ve tried to keep this code primitive, but I believe that it answers all the questions above.

Conclusion

Encapsulation is a powerful principal. It brings a lot of benefits to your project. But you need to implement it carefully. Wrong implementation can significantly increase efforts required to deliver the solution and support it. My point here: do not blindly follow approaches that are described on the Internet (even mine). You need to understand what will be better for you and your project. If you don’t know, just discuss it with your teammates. Perhaps, they already defined some guidelines.

Thank you for reading. I hope you enjoyed this story. Sincerely yours, Alex.

--

--