Lombok lets you do wrong things very easily. And that is a huge problem. Using it cripples your thinking about code and its architecture.
The title of this post is very sharply phrased I know. And I would like to point out two things before I start.
- Anything I say about Lombok is not aimed at Lombok as a project but rather on foundation ideas and the consequences of using it.
- Using Lombok or not is a no recipe for a good code and product. You can create an astonishingly good code while using Lombok and of course a very bad one without it.
The point I would like to make is that using Lombok is robbing you and your code of the benefits of well-designed code. It does it by telling you that some parts of code suck and they will always suck and there is no other way so we created a library to hide those parts out of your sight.
Here is a complete feature list but I would like to stop at only some of them which are the worst in my opinion.
Constructors are one of the most important aspects of a class in OOP. It is a place that defines how your class fits with other classes. As in a quote “As many languages you know, as many times you are a human being” in OOP it is “As many constructors class have, as many times it can be reused”. A propper class has multiple constructors in order to be usable in as many contexts as possible. If your constructors just copy your fields list your problem is not “I have to write a boilerplate constructor that just copies a parameter list”. The real problem here is having a class that is not reusable and that is something that Lombok won’t help you with.
Builder pattern, as useful as it seems, is in most cases antipattern. Having a class with many fields is a code smell that should raise a red flag in order to make the class more composable. Of course, there are rare cases in which builders are acceptable, but they are rare, and one-time code generation in your favorite IDE is enough. Large field lists are a composition problem. Do not cover the problem under the Lombok blanket, solve the composition problem!
My favorite argument about Lombok is about getters and setters.
I am often confronted with the argument that getters are boilerplate code and Lombok really helps. If you have getters and setters then sure it is. I don’t face this problem so I don’t need to generate them at all. I don’t have getters and setters in my code. They are not needed in almost all cases. They are very hurtful to the code architecture.
In some rare cases of pure data transporter classes simple
public final filed will do much better. “But I will lose the encapsulation!!”. No, you won’t, you can’t lose something that was not there in the first place. Getters and setters actually break encapsulation in most cases.
Improve your design so you dont need getters and you wont feel any need generating them.
Having nulls in your code (not counting inputs) is a bad idea to begin with. Do not return nulls anywhere and you won’t need to check for it. Return lists, null objects, throw exceptions, do anything except returning null unless there is absolutely no other way. If you don’t have nulls you don’t have to generate null checks.
Recently a colleague of mine discovered a big difference in a build time when using a
val feature. Using it is accountable for a 63 % increase in the compilation time of our project. In our case, it is just 2 minutes. But 2 minutes times number of devs times compilations per day times working days in a year and you are at on man-year of work lost.
There are some harmless or even great features of Lombok of course.
@SneakyThrows might be one of them. But those little beneficial features never pay off the technical debt introduced by ignoring the code architecture with other features.
Log feature that seems harmless might not be. It sends a signal to a dev that having a statically generated logger (not injected through the constructor) is normal and a good thing. We are used to it in the Java world but I would not take it for granted. See my post about injecting a log.
Lombok takes away the reasoning about the code architecture and normalizes things that should be questioned and reasoned about.
Reject the temptation of an easy solution. Take the hard path - improving the code architecture Taking the hard path may be slow from the begging but pays off greatly in a long run.