Datum
July 11, 2022
Kategorie
Software Engineering
Lesedauer
3 Min.

Decluttering Code with Lombok – Best Practices and a Look to the Future

Lombok should be a familiar term to many developers in the Java world by now. It is no wonder: the ability to encapsulate various standard code snippets with annotations greatly enhances code readability. Redundant elements are eliminated, allowing you to focus on the essentials. To learn how it works, what features we can expect in the future, and my overall conclusion on the tool, join me on this brief tour.

Photo by Diana Polekhina on Unsplash

Setup and Initial Magic

To integrate Lombok into your project, simply add the dependency to your preferred build tool. For example, in Maven:

<dependencies>
   <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>1.18.24</version>
       <scope>provided</scope>
   </dependency>
</dependencies>

Once you’ve done that, you are ready to start cleaning up your code.

@Getter/@Setter

In plain Java, you would typically see the following code:

private final String property;

public void setProperty(String value) {
 this.property = value;
}

public String getProperty() {
 return property;
}

With Lombok, you can replace it with just these two lines:

@Getter
@Setter

private final String property;

And your methods are ready. In this case, the annotations apply specifically to this one attribute but they can also be used at the class level. While most developers hopefully do not write getters and setters manually and rely on their IDE to generate them, this approach makes the code more concise.

Constructors

Constructors are added at the class level and there are various options, summarized briefly:

  • @NoArgsConstructor: creates empty constructor – can be forced with (“force=true”), if final fields are included, they are initialised with zero
  • @AllArgsConstructor: creates constructor for all fields
  • @RequiredArgsConstructor: creates constructor for all final fields

Furthermore, using such an annotation does not exclude the addition of other, more specific constructors. You can use your custom constructors in conjunction with those generated by Lombok.

In addition, there are basic functions like @EqualsAndHashCode and @ToString – the names are self-explanatory. With @NotNull on a method parameter, you no longer need to deal with NullPointerExceptions.

Exciting Features in the Testing Phase

So that covers the basics. But Lombok’s functionality is regularly expanding. Potential new features initially appear in an experimental status. If they prove themselves during this period, they are promoted to stable and the extension becomes permanent. I would like to discuss a few of these experimental features and explain why you should keep them in mind. I am quite convinced by some and expect them to become permanent.

@SuperBuilder and @Jacksonized

The @Builder-annotation is already a core feature of Lombok and is particularly popular in the context of APIs. Instead of multi-step instantiation using setter methods, objects can be “built” with a single command and then used.

This functionality is extended with @SuperBuilder to incorporate the concept of inheritance. Super calls to the parent constructor are a thing of the past. Once the relevant classes – the parent and the child classes – are annotated with this feature, you can set all attributes from a builder call:

@SuperBuilder
public class Person {

 private final String firstName;
 private final String lastName;
}@SuperBuilder
public class Employee extends Person {

 private final String employeeId;
}Employee.builder().firstName("Donald")
                 .lastName("Trump")
                 .employeeId("1D1OT")
                 .build();

However, there was an issue with the Jackson library not handling this constructor alternative correctly. It could not infer that the builder should be used for serialization/deserialization without additional annotations. Although you could work around this with some extra annotations, it seemed counterproductive to have boilerplate code for a tool that is supposed to reduce it. This is where @Jacksonized comes into play: it combines these adjustments into a single annotation and ensures a smooth process. It also works for the regular @Builder without inheritance.

@SuperBuilder
@Jacksonized
public class Person {
...

I would not want to miss the combination of @SuperBuilder and @Jacksonized. The result is super clean and straightforward model classes with seamless JSON integration.

To use these features, you need at least Lombok v1.18.14.

Conclusion

I must admit, I’m a big fan of Lombok. The advantages are clear and address some of the long-standing issues that have plagued Java’s reputation. Everything becomes more compact, even more complex classes become easily understandable at a glance.

However, there are also opposing voices that prefer less magic happening behind the scenes. This is a valid point. Where a lot is taken away, you inevitably have less insight into what is actually happening. Bundled annotations (like @Data) can lead to excessive code generation that might not be necessary. Additionally, using too many annotations at once can quickly become overwhelming, which undermines their purpose. To prevent this, it is advisable to maintain a consistent order of annotations at the class level.

In summary, it’s a matter of personal preference and common sense. Use annotations sparingly, where they make sense and simplify your work, rather than overloading your code with them.