ByteIntroduction

Getting started with LOMBOK

Skills:

Java

Objective

Get a quick overview of how Lombok reduces boiler-plate code

Background/Recap

We tend to write a lot of similar code in our projects for various purposes. We’d need to add constructors for our classes, getter & setter methods for our fields & other utility methods like for printing out an object directly using some variation of print.

image alt text


These are perfectly essential use-cases. But, due to the repetitive nature of the tasks, we can reduce the time we take on these if we follow some conventions.

Primary goals

  1. Understand how to reduce boiler-plate code using Lombok

Objective

Get a quick overview of how Lombok reduces boiler-plate code

Background/Recap

We tend to write a lot of similar code in our projects for various purposes. We’d need to add constructors for our classes, getter & setter methods for our fields & other utility methods like for printing out an object directly using some variation of print.

image alt text


These are perfectly essential use-cases. But, due to the repetitive nature of the tasks, we can reduce the time we take on these if we follow some conventions.

Primary goals

  1. Understand how to reduce boiler-plate code using Lombok

Download & run source code

You can download the source code from here using one of the following commands:


git clone https://gitlab.crio.do/crio_bytes/lombok.git

git clone git@gitlab.crio.do:crio_bytes/lombok.git

Verify by running Main.java, you’ll see Running Completed outputted in the terminal

Is boiler-plate code really an issue?

I have a Trade class with some variables declared. I’m trying to create a new instance of Trade class like this


Trade trade = new Trade("AAPL", 50, LocalDate.now());

While running the Main class, the compiler is giving me some "Constructor is not defined" error. Can you help me make that go away?

(Verify by uncommenting the code in Main class as instructed)


public class Trade {

  

  private String symbol;

  private int quantity;

  private LocalDate purchaseDate;


}

Thanks. Now, I’m able to create new Trade objects. But, there’s a new issue now. I’m having trouble retrieving & updating the values of the variable for objects of this class. Google told me I have to define getter & setter methods for private variables as they are "private" for the class defining it.


It would be great if you could do that for me. I’d like to have the ability to access & modify all these private variables.


Nice! I’m going crazy modifying Trade’s "private" variables. I’m hearing someone saying, “Privacy intrusion detected”.

Are you able to run the commented code in the Main class to run without errors? Did you name the getter/setter methods something like getSymbol() in the first place?

You can also try to override the toString() method to be able to directly print a Trade object like this using System.out.println()


Trade [purchaseDate=2020-06-12, quantity=1000000, symbol=GOOGL]

With all these done, how many lines of code does the Trade class have? Can you scroll up to see how many lines we started with? How do you think the number of lines will increase with the number of variables?

Let’s say you are planning to create a REST API for a food delivery app. I’ve provided some of the classes you'll need inside src/main/java/com/example/lombok/dto. Take a quick glance at those. How much time will you need to add the constructor/setter/getter/toStrings methods? How many lines of code?

(Quick note if you are highly adventurous: don’t get started with adding those methods. Save it for the next milestone!)

Curious cats

  • Can you try using the empty constructor to create a new Trade object? It should give an error, right?

How does Lombok fight Boiler-plate?

Lombok provides annotations (yeah, the things we put on top of classes/fields) for auto-generating boiler-plate code. This is achieved by injecting in the required things directly to the .class files.


We’ll go popping out code in the order we added it (Okay, okay. You added it :) ) from Trade class. Remove/comment out related code once you add the annotations.

  1. Use @ToString to auto-generate toString() implementation

  2. Use @Getter/@Setter to auto-generate getters & setters on either the class itself or on all of the fields you need a getter/setter

  3. Use @AllArgsConstructor to generate a constructor with all the parameters


Ok, quick question - how many lines of code does your Trade class have now? If you were to add these to the classes in the dto folder as well, how does it compare with what you were doing earlier?


Very cool, right? Can we do even better?


If you said, "What!", let’s understand how Lombok was able to reduce boiler-plate code. For @ToString it sticked to a particular format printing out all the variables like this:


Trade [purchaseDate=2020-06-12, quantity=1000000, symbol=GOOGL]

With @Getter/@Setter at the class level, Lombok chose to create public getters/setters for all non-static fields with standard naming convention like getSymbol(). As for @AllArgsConstructor, it creates a constructor with all the arguments in the order they were declared.


By sticking to certain specific cases (or restrictions), Lombok made it possible to reduce boiler-plate code. Coming back to our earlier challenge if this can be further reduced, it’s again a Yes!


@Data do all these. Can you try adding the annotation? I’ve provided another class TradeData if you like to keep your earlier code. What happens when you create a TradeData instance in the Main class? All well?


Sorry, I tricked you. No, no! @Data does the work for us. There’s a slight difference


@Data = @ToString + @Getter/@Setter + @RequiredArgsConstructor

Check out how @RequiredArgsConstructor works here.


We’ll need to annotate "required" arguments to be included in the constructor. You’ll have to find the annotation to be used.

Curious Cats

  • Remove any Lombok annotations. Can you use the empty arguments constructor (new Trade()) now? Add @AllArgsConstructor and check again. Why do you think that happens?

  • Can you give a scenario when @RequiredArgsConstructor functions like @NoArgsConstructor for a class with non-zero fields?

Takeaways

  • How to reduce boiler-plate code using Lombok annotations?