Lombok: a DDD-friendly Java tool

Gara Mohamed
11 min readMay 9, 2022

--

Evaluating Lombok from a DDD perspective

Photo by Mathis Jrdl on Unsplash

Introduction

DDD is a holistic approach to tackling complexity in the heart of software. It takes care of both the strategic and the tactical aspects of software solutions and IT organizations. This post is limited to the tactical scope: we try to evaluate a tool from a DDD viewpoint. The real goal of the analysis is not the tool itself but the DDD mindset.

Lombok is a java tool that is largely used. Its pros and cons were well discussed in many articles and Stack Overflow answers. In this post, we evaluate Lombok from a DDD perspective. The analysis is based mainly on my understanding of:

  • Eric’s book which I read two times (the first time was five years ago)
  • And some of his talks at DDD conferences (such as DDD Europe)

Let’s first start with a brief history of the java language and a description of the problem resolved by Lombok.

Java power and limitation

My journey with Java started eighteen years ago on a text-based IDE called JPadPro. It was a big step forward in developing GUI applications after my first screens with other platforms. It was easy to write small desktop applications with Swing. As a software engineering student, I enjoyed writing my first Java classes.

Since that time, the JDK has kept growing in popularity and maturity. The language, API, and the platform have evolved during the last twenty years and the ecosystem has become quite large and mature. All this stuff kept attracting me more and more.

But after all that time, some limitations of the Java native platform are not totally tackled by the JDK: the language is verbose when dealing with some repetitive tasks such as declaring constructor, properties, equals, hashCode, simple builders.

As a lazy programmer who hates redundant dummy tasks and likes to do more challenging ones, I suffered from this verbosity when working on real-world professional applications. Let’s illustrate the problem with a concrete simple example.

In the following listing we declare a class for defining a Person:

Listing 1

This is a class with three fields with default access visibility. We should now add the following idiomatic stuff:

  • constructor
  • properties
  • equals and hashCode methods
  • toString method
  • Builder class
Listing 2

This is a code for an immutable class. If we add the setters we can have almost 100 lines of code. We can extract the Builder class to a separate file to reduce the verbosity but the problem still exists.

Writing this verbose code has two major drawbacks in terms of developer experience:

  • This is an example with three properties. For a real-world entity with twenty or even more fields, the situation becomes worse.
  • It is hard to maintain this logic. If we add a property we must update all methods which is an error-prone task.

The code can be generated by the IDE. This is true when the class is created for the first time. But when we change attributes we should launch the generation action for each part of the code.

There is also another cost: we should read all this dummy code which is visual pollution and it’s hard to analyze by the human brain.

Let’s now look at Lombok and see how it tries to resolve the problem.

What is Lombok?

Lombok can be seen as an extension of the Java compiler. It uses the Annotation Processing Tool to “generate” code in the compilation phase. The main value of Lombok is to reduce the class declaration verbosity by removing the boilerplate code and using a declarative approach based on annotations. When we use Lombok in our example it becomes:

So, the idea is to make some aspects of Java programs more declarative. If all or the majority of the class member are exposed as object properties then Lombok can be a good tool to use.

Lombok offers many features that do not all have the same level of maturity. In this post we limit Lombok to his main annotations subset:

  • Value
  • Builder
  • With
  • EqualsAndHashcode

With this quick Lombok reminder/presentation, let’s jump now to the DDD side.

What is Domain Driven Design?

DDD is an approach that emerged to tackle the complexity in the heart of software applications. It defines principles, patterns, and practices from the high-level organizational, social and political aspects to the low-level lines of code.

DDD states that when the complexity is in the business logic, then we should isolate this logic in a domain model layer. This layer should be dedicated to expressing the model and be free from GUI, DB, and HTTP clients logic. The model isolation is an important principle and it deserved a full chapter in the DDD blue book.

DDD is based on the agile (as defined by the manifesto) and Lean Software Development mindsets. The DDD doesn’t try to reinvent the wheel it’s partially a brilliant collection of the good principles and practices that emerged in the industry.

What is the relation between Lombok and DDD?

DDD is a holistic approach that covers high-level strategic topics as well as low-level tactical topics. The main idea of the tactical part is to express the model in the software solution.

When talking about implementing the model, the blue book discussed four main subjects:

  • An architectural style that helps to isolate the domain model
  • A catalog of useful design patterns to express the model
  • The supple design
  • The tools that we use to build a software

Even if DDD is tool agnostic, it promotes some criteria for selecting tools. In many chapters, the blue book talked about programming languages (general-purpose, 4GL, DSL, etc…), frameworks, and databases. I think that one of the best paragraphs that explain the DDD mindset about tools is the following:

Architectural frameworks and other tools will continue to evolve. Newer frameworks will automate or prefabricate more and more of the technical aspects of an application. If this is done right, application developers will increasingly concentrate their time on modeling the core business problems, greatly improving productivity and quality. But as we move in this direction, we must guard against our enthusiasm for technical solutions; elaborate frameworks can also straitjacket application developers.

So, DDD is not against tools but it prefers ones that help us to focus mainly on business problems. Our model should be:

  • Isolated from the external world and also from technical aspects
  • Easy to define with a declarative style

Let’s take another excerpt from the book talking about tools but this time from the Value Object chapter:

Immutability of an attribute or an object can be declared in some languages and environments but not in others. Such features help communicate the design decision, but they are not essential. Many of the distinctions we are making in the model cannot be explicitly declared in the implementation with most current tools and programming languages. You can’t declare ENTITIES, for example, and then have an identity operation automatically enforced. But the lack of direct language support for a conceptual distinction does not mean that the distinction is not useful. It just means that more discipline is needed to maintain the rules that will be only implicit in the implementation. This can be reinforced with naming conventions, selective documentation, and lots of discussion.

This paragraph has a direct relationship with the tool selected in this article. Lombok allows to declaratively define an immutable object without the Java boilerplate code. Lombok also makes declaring entity identity more declarative.

This post is at the same level as the DDD book discussions of the various tools used to implement the domain model. I hope that the two previous blue book citations are enough as examples to illustrate the link between tools and DDD in general. But, before we go forward, I would like to point out that the Domain-Specific Languages section in chapter 10 exposes the pros and cons of DSLs which can be compared to our discussion of Lombok's pros and cons at the end of this article.

Let’s now discuss Lombok features from a DDD perspective. Our first evaluation of Lombok will be from the XP perspective.

eXtreme Programming

Simplicity is one of the values of eXtreme Programming. It’s usually applied to the design but should also be applied to the tools used to implement it. It’s clear that listing 2 introduces an accidental complexity in the codebase which has no relationship with the problem being resolved. So, the Lombok version helps to achieve the required simplicity and remove the accidental complexity.

The XP philosophy is to use the easy design solution and then refactor if the constraints change. This applies well to the use of tools and Lombok is a decision that can be easily reversed.

Lean software development

From a Lean point of view, writing boilerplate, redundant and dummy code is a waste that should be eliminated. The developer should fully put his energy on the domain problem and the listing 2 approach hijack the developer’s focus from the domain (or at least reduce his efficiency).

By its declarative strategy, Lombok helps us to:

  • focus more on the domain model
  • eliminate accidental complexity
  • eliminate waste

All these points enhance the developer’s experience. And the better the developer's experience the bigger his impact on the product.

One of the basic craft rule that I learned ten years ago is: Every thing that can be automated should be automated.

Rich domain model pattern

The DDD promoted the rich domain model pattern. Listing 2 code is not a scalable approach to use when adopting this pattern because domain entities will contain complex behavior and all the dummy code that we add interwind with the rich behavior and makes the navigation in the codebase painful.

So, Lombok helps to keep only the rich domain behavior in entities and value objects.

Usually getter/setter are considered as a DDD anti-pattern. But exposing domain entities state using properties can be a good solution if the rich domain model pattern is respected.

The mythical “only Java” heuristic

Using only Java to implement the domain layer is a heuristic that I saw in a few blog posts but It doesn’t exist in the reference DDD books (at least to my knowledge). And it’s a heuristic that conflicts with the DDD mindset. To see why let’s remind ourselves what the blue book said about the goal of isolating the domain model:

Concentrate all the code related to the domain model in one layer and isolate it from the user interface, application, and infrastructure code. The domain objects, free of the responsibility of displaying themselves, storing themselves, managing application tasks, and so forth, can be focused on expressing the domain model. This allows a model to evolve to be rich enough and clear enough to capture essential business knowledge and put it to work.

The goal of isolating the model is to be focused on expressing the domain model. Everything that is not directly related to this responsibility should be avoided. And any tool that simplifies the writing, reading, and navigating in the model is considered DDD-friendly at least from this perspective.

In the Generic Subdomains chapter, It was stated explicitly that DDD is not about reinventing the wheel even for the domain model:

Don’t feel compelled to implement all aspects of a published model, if you can identify a simplified subset that is self-consistent and satisfies your needs. But in cases where there is a well-traveled and well-documented — or better yet, formalized — model available, it makes no sense to reinvent the wheel. DDD is not about reinventing the wheel.

So, if we can reuse a well-established model to design our abstract domain model, then why we can’t do the same thing when implementing this model in our code. DDD is not a justification to use poor solutions or reinvent the wheel.

In my experience, using a third-party library in the domain layer is an interesting choice when implementing a cohesive mechanism. I’m writing a dedicated post about a real cohesive mechanism example. I will publish the article as soon as possible.

Let’s now look at two examples that I usually use when engaged in discussion about the Java Only rule:

  • In 2012, to represent date and time in a Java application, we had at least two choices: either we use the JDK native API or we use a third-party library such as Joda time. The Java date and time API before 2014 was a poor one. If we followed the Java-only heuristic we will use a bad API. A heuristic that promotes using bad API isn’t a good one. And the history of the Joda time library confirms this because the actual Joda time API is now part of the JDK.
  • The Java API doesn’t contain a concept to model a range. So, we can use a third-party library such as Guava with its Range type or we can choose to create one from scratch so the domain layer is independent of external libraries. We can do that if it’s justified but the justification can’t be: “this is the DDD” because the DDD is not about reinventing the wheel.

From a DDD point of view, using a third-party module in the domain layer is forbidden for two reasons:

  • The module contains infrastructural stuff that couples the model to external systems.
  • The selected module does not help to express the domain model very well.

So, if the third-party module respects the two constraints, from a DDD point of view, it can be used in the model. But, the third-party module adoption should be evaluated from other perspectives. For example, we can ask the question: why did we choose the Java platform to develop the application. Maybe, the module should respect the same choice criteria.

Lombok: the false problem

Lombok is using APT to hack the compiler. To add a feature, it should be implemented for the different versions of the compiler. Sure, this is not ideal but this is a problem for the maintainers of the project, not the users. From a user perspective what accounts is:

  • How easy to use
  • How active the project
  • The release roadmap

So, talking about the internal implementation to justify the use or not of Lombok is not a very wise argument. From a user perspective, Lombok suffers from another type of limitation.

Lombok: the real problem

The real problem of Lombok is usually the tooling. The first problem is that we need to install a plugin in our IDE. The second problem which is worse is that the plugin has a different release cycle than Lombok. These are the real practical disadvantages of Lombok.

There is another problem that is more controllable: Lombok is an additional tool to master. But, the team is autonomous to solve this problem. It doesn’t depend on a third-party entity to solve the learning problem.

Alternatives

The JVM languages such as Kotlin are a good alternative to resolve the Java language verbosity. Almost all Lombok's main features are tackled by Kotlin. From a DDD point of view, Kotlin is a good language for implementing Domain Model on the JVM.

The recent versions of Java are also a good alternative. Some interesting features, such as records, were added to the language. But, they are still limited compared to Lombok and Kotlin.

Conclusion

DDD is not about making perfect solutions. The first DDD rule for the domain model design is that: a good design is imperfect and we should stop being perfectionists.

DDD is mainly about understanding the business problem by communicating with domain experts to construct a shared understanding based on a domain model. The domain model should be implemented using patterns and tools. Any tool that makes the model expressive and pure is a DDD-friendly tool. But, DDD-friendliness is not the only criteria to use when selecting our toolbox. It’s the main one but it’s not the single one.

--

--