Lombok, czyli annotation driven development – zyski i zagrożenia
Author
Rafał Pieńkowski
blog_date_icon
20 sierpnia

Pisząc kod w javie i tworząc nowe klasy, często potrzebujemy napisać metody, które są praktycznie prawie takie same dla różnych klas. Na przykład, mając:

<!--more-->
public class User {
private String username;
private String email;
}

Czyli zwykłą małą klasę trzymającą dane o użytkowniku, zapewne będziemy potrzebować utworzyć:

  • konstruktory (domyślny i z parametrami)
  • gettery i settery
  • equals i hashcode
  • toString

Zatem, nasza mała klasa rozrasta się z kilku linii do aż 60 (na rzecz czytelności artykułu, pominę wygenerowany przez IDE kod). Pomimo rozrostu, nie dodaliśmy żadnej logiki biznesowej. Nic to nie wniosło. Taki kod nazywamy boilerplate code – czyli kod, który nic nam nie wnosi, ale jest potrzebny do napisania, żeby aplikacja działała.

Lombok

Z pomocą przychodzi nam biblioteka lombok, która generuje owy boilerplate code na podstawie użytych adnotacji. Żeby zacząć korzystać z lomboka, dodajemy jego zależność:

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

Jeśli nie korzystamy ze Spring Boota, potrzebne nam będzie również dodanie wersji. Ekwiwalent 60 linijkowej klasy możemy zapisać teraz z pomocą kilku samowyjaśniających się adnotacji:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class User {
private String username;
private String email;
}

Jak widać, zaoszczędziliśmy wiele linijek kodu. Poszliśmy w stronę programowania deklaratywnego – mówimy, co chcemy mieć zrobione (używając adnotacji), a nie jak to ma być zrobione.

Przybyło jednak adnotacji – możemy użyć nawet „pewnego zbioru” adnotacji, jak np na poniższym przykładzie:

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private String username;
private String email;
}

@Data zawiera w sobie @Getter, @Setter, @RequiredArgsConstructor, @ToString oraz @EqualsAndHashCode.

Również przydatną rzeczą jest @Builder – dzięki temu, będziemy mieć dostarczony builder pattern przy tworzeniu obiektów danej klasy.

Lombok – wady

No dobrze, nie mamy boilerplate kodu – czy są zatem jakieś wady?

Pierwszą, o której się pomyśli, to brak możliwości debugowania – nie postawisz breakpointa na adnotacji i nie zobaczysz parametrów metody. Okej – można wykonac proces tzw. delombok, i postawić breakpointa w wygenerowanym kodzie, ale wtedy cała zabawa zaczyna tracić sens. Mając zbiór adnotacji (potocznie, pejoratywnie, można to nazwać annotation driven development) łatwo pogubić się w tym gąszczu – np mając tak oznaczoną klasę:

@Data
@Value
public class User {
private final String username;
private final String email;
}

Nie od razu widzimy, które metody są wygenerowane, a które nie. Dopiero później możemy się przekonać, że @Value zawiera w sobie @AllArgsConstructor, @Data zawiera w sobie @RequiredArgsConstructor, natomiast w tym wszystkim brakuje nam... @NoArgsConstructor, czyli konstruktora domyślnego. Jaki może być tego skutek? Niektóre biblioteki do serializacji / deserializacji, jak np Jackson, wymagają konstruktora domyślnego – w przeciwnym wypadku, na konstruktor z parametrami należy nanieść stosowną adnotację. Niestety, wyjdzie to dopiero w runtimie...

Podsumowanie

Jak widać, stosowanie lomboka pozwala znacząco zredukować boilerplate code i tym samym przyspieszyć proces wytwarzania oprogramowania oraz zwiększyć czytelność kodu. Jednak nie zapominajmy o rozsądku, żeby pewnego dnia nie znaleźć się w gąszczu samych adnotacji, ponieważ w przypadku jakiegoś błędu, namierzenie jego przyczyny jest dużo trudniejsze.

Przeczytaj także