lombok-image

Lombok dobre i słabe strony

W tym wpisie postaram się przybliżyć Ci bibliotekę, która pomaga uporać się z meczącym pisaniem powtarzalnego kodu. Zebrałem najważniejsze informacje dotyczące biblioteki Lombok. Skupiłem się na jej wadach oraz tym, jak sobie z nimi radzić.

 

Co to jest Lombok?

Lombok to biblioteka, która poprzez generowanie kodu dodaje nam nowe funkcjonalności do języka Java. Żeby to było możliwe, musi ona wspomagać się wtyczkami do IDE (Integrated development environment). Potrzebne są także odpowiednie wtyczki dla narzędzi do budowania (np. maven, gradle).

Lombok jest procesorem adnotacji (annotation processor), co oznacza, że korzysta z mechanizmu Javy, który pozwala przed kompilacją wykonać pewne zadania. W tym wypadku jest to generowanie kodu.

Trzeba także dodać, że Lombok jest jedną z najbardziej popularnych bibliotek, więc warto się trochę z nim zapoznać. Jak podaje GitHub, Lomboka używa ponad 257 tyś projektów:

Lombok github stats

Do czego służy Lombok?

W skrócie: pozwala programiście zaoszczędzić trochę czasu. Poprzez generowanie kodu daje możliwość ograniczenia konieczności pisania powtarzalnego kodu (boilerplate code), takiego jak np. gettery, settery, konstruktory, czy metody takie jak hashCode(), czy equals(Object obj).

W kodzie po prostu dodajemy odpowiednią adnotację i nie musimy już pisać powtarzalnego kodu. Dzięki temu jest on mniej obszerny i czytelniejszy:

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
class Person {
  private String name;
  private int age;
}

 

Co oferuje Lombok?

Poza wymienionymi już wcześniej adnotacjami @Getter i @Setter, jest jeszcze całkiem spora kolekcja adnotacji oraz słów kluczowych takich jak var i val(słowo kluczowe var zostało wprowadzone do języka Java w wersji 10 i służy ono do deklaracji zmiennych lokalnych. W związku z tym jeśli używasz Javy 10 lub nowszej powinieneś używać słowa var wbudowanego w język).

val – służy do deklaracji finalnych zmiennych lokalnych
var – służy do deklaracji zmiennych lokalnych
@NonNull – sprawdza czy dany parametr jest nullem, jeśli tak, wyrzuca NullPointerException
@Cleanup – zamyka zasoby, działa tak samo jak try-with-resources, który został wprowadzony w Javie 7
@Getter/@Setter – generuje gettery i settery
@ToString – dodaje metodę toString()
@EqualsAndHashCode – generuje metody equals(Object obj) i hashCode()
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor – generują konstruktory
@Data – generuje wszystko to co adnotacje @ToString, @EqualsAndHashCode, @Getter, @Setter i @RequiredArgsConstructor
@Value – jest niemutowalną wersją adnotacji @Data
@Builder – dodaje buildera
@SneakyThrows – przechwytuje checked exception
@Synchronized – dodaje bloki synchronizowane wewnątrz metody
@Getter(lazy=true) – pozwala generować gettery, które cache’ują wartości
@Log – dodaje loggera

 

Zalety Lomboka:

  • Jedną z głównych zalet tego narzędzia jest zmniejszenie ilości kodu w projekcie (kodu, który widać), dzięki temu jest go trochę mniej do ogarnięcia i pisania. Chociaż współczesne IDE pozwalają na wygenerowanie najczęściej pisanych metod: getterów, setterów, hashCode(), equals(Object obj) itp., to jednak Lomboka używa się znacznie szybciej i wygodniej.
  • Przyspiesza pisanie kodu. Dodajemy adnotację i już mamy to co chcieliśmy. Usuwanie kodu też jest o wiele prostsze, usuwamy tylko jedną linijkę, zamiast całych metod.
  • Używają go duże projekty np. Spring Data.

 

Wady Lomboka:

  • Jeśli zaczniesz go używać, to późniejsze usunięcie go z projektu może przysporzyć dużo pracy. Co prawda, plugin do IDE ma wbudowaną opcję Delombok, ale użycie jej na całym projekcie może być mało estetyczne.
  • Niektóre adnotacje nie współpracują ze sobą np. jednoczesne użycie @Value i @NoArgsConstructor jest niemożliwe, dostajemy wtedy błąd kompilacji: „Variable 'x’ might not have been initialized”
  • Niektóre adnotacje Lombokowe, wykorzystują pewne haki i używanie ich jest nie do końca dobre np. @SneakyThrows
  • Korzystanie z różnych bibliotek takich jak Hibernate może powodować konieczność automatycznego dodawania niektórych adnotacji np. @NoArgsConstructor (Hibernate potrzebuje bezargumentowego konstruktora, żeby stworzyć encję, podobnie jest z Jacksonem, którego używa spring jako domyślnego mapera dla jsona).
  • Zbyt wiele adnotacji na pojedynczej klasie – jeśli poza Lombokiem używasz innych frameworków, a zwykle tak jest, to adnotacji robi się czasem naprawdę sporo.
  • Kod którego nie widać – developer nie widzi kodu, który wygenerował Lombok, może powodować to zakłopotanie i częste korzystanie z funkcji Delombok, zwłaszcza gdy coś przestaje działać i nie wiesz co jest tego przyczyną.
  • Niektóre adnotacje (@Builder, @EqualsAndHashCode) mogą sprawiać kłopoty w miejscach, gdzie mamy dziedziczenie, a zwłaszcza, gdy to dziedziczenie jest bardzo rozbudowane.
  • W połączeniu z innymi generatorami kodu może dawać nieprzewidziane efekty.

 

Jak używać Lomboka?

Warto na początek rozważyć stosowanie tylko kilku podstawowych adnotacji, z czasem można zacząć używać większej ilości. My w zespole zdecydowaliśmy, że będzie dla nas bezpieczniej jeśli nie będziemy od raz korzystali z wszystkich funkcji Lomboka.

Poza adnotacjami które wymieniłem, jest jeszcze kilka, które mają status expermiental i użycie niektórych z nich jest na tyle magiczne, że doszliśmy do wniosku, że lepiej z nich nie korzystać – zgodnie z zasadą KISS (Keep it simple stupid).

Jeśli nie wiesz, jak użyć danej adnotacji, albo w danych przypadku nie do końca jesteś przekonany, czy wygeneruje ona to, o co Ci chodzi, to po prostu jej nie używaj. Napisz kod własnoręcznie.

 

Podsumowanie

Jest zaledwie kilka, ale za to bardzo konkretnych zalet tego narzędzia i właśnie z ich powodu warto pobawić się Lombokiem i przekonać się na własnej skórze, czy korzyści przeważają wady.

Ja osobiście używam go od ponad roku w obecnym projekcie i w większości przypadków sprowadza się to do używania adnotacji @Getter, @Setter, @Builder, @EqualsAndHashCode oraz metod generujących konstruktory.

W tych podstawowych zastosowaniach sprawdza się świetnie. Poza wadami, które wypisałem wyżej, nie sprawia on większych problemów. Oczywiście zawsze pozostaje możliwość rezygnacji z Lomboka w miejscu, gdzie jest jakiś problem i napisania kodu własnoręcznie lub wygenerowania przez IDE.

 

Źródła:

https://projectlombok.org
https://www.javacodegeeks.com/2017/09/lombok-definitely-give-try.html
https://stackoverflow.com/questions/3852091/is-it-safe-to-use-project-lombok
https://www.reddit.com/r/java/comments/6ilt97/what_do_you_think_of_project_lombok/

 

Mateusz Dąbrowski

Cześć jestem Mateusz, zajmuję się programowaniem już ponad 12 lat z czego ponad 8 programuję w Javie. Zapraszam Cię do lektury mojego bloga. Możesz przeczytać więcej o mnie >>TUTAJ<<

12 thoughts to “Lombok dobre i słabe strony”

  1. Początkowe eksperymenty z Lombokiem dały bardzo pozytywne rezultaty w postaci krótszych klas i byłem bardzo zadowolony. Podzielam opinię o tym, że lepiej na początku pozostać przy prostszych adnotacjach.
    Jedyny problem z Lombokiem na jaki trafiłem to stackoverflow exception, który był wyrzucany po dodaniu adnotacji do definicji encji, które wykorzystywały jpa i dziedziczenie. Nie pamiętam szczegółów, ale okazało się, że kod jest generowane w nieskończoność, co zjada w pewnym momencie całe zasoby.. Ot, trzeba uważać.
    Ciekawy wpis.

    Pozdrawiam,
    vioolldeyja

  2. Brakuje mi tylko w minusach lomboka ze jego mechanizm działania jest oparty na jednym wielkim hacku i bazuje na nie dokonać oficjalnym api kompilatora którego raczej nie powinno się używać i które w kolejnych wersjach javy może zniknąć co może skutecznie uniemożliwić upgrade javy w naszym projekcie.
    Uważam ze jezeli tak bardzo przeszkadza nam ten zbędny kod w Javie to już lepiej zacząć korzystać z języka który oferuje nam takie ułatwienia jak Kotlin/Scala

    1. Dzięki za komentarz Marcin. Masz rację, ale bez tego haka nie było by Lomboka. Ja starałem się wypisać głównie wady związane z użytkowaniem tego narzędzia.

      Co do przyszłości Lomboka, to myślę, że nie ma się o co martwić. Jeśli wystarczająco duża ilość developerów będzie go używać, to będzie bezpieczny.

      Niech przykładem będzie klasa Unsafe, której używanie to też hak. A kiedy developerzy Javy chcieli ją usunąć, społeczność zaprotestowała i klasa ta nie została usunięta.

      Co do innych języków, w większości przypadków nie jest to opcja. Zwykle nie możesz tak po prostu zmienić języka w projekcie.

      1. Co do samych zalet używania Lomboka zgadzam się w pełni i całkiem fajny artykół, ale wydaje mi się że ludzie powinni wiedzieć w co się pakują zanim zaczną używać lomboka 😉

        A co do zmiany jezyka to wiem że często to jest problem, ale dorzucanie stopniowo do projektu Kotlina jest storunkowo proste (nikt nie mówi o rewolucji i przepisywaniu projektu), najwiekszym problemem jest przekonanie zespołu.

    2. Tak jak sugerował kolega wyżej… Lombok może być etapem pośrednim zanim przesiądziemy się na Kotlina ? tak było w moim wypadku. Nic tak dobrze nie eliminuje boilerplate jak Kotlin i tyle ?

  3. 1. Koniecznosc uzycia NoArgsConstructor dla encji hibernetowych – to problem samego hibernata , a nie lomboka samego w sobie. Ma byc konstruktor i kropka. To samo za
    2. Immutable class i NoArgsConstructor -> to specyfka javy i final, a nie problem lomboka

    Poza tym wszystko sie zgadza. Dodalbym jeszcze:
    3. koniecznosc wlaczenia „annotation processing” w Intelij albo „org.projectlombok:lombok:${lombokVer}” w gradle

    Pozdawiam

    1. Dzięki za komentarz Marek.
      Ad. 1 i 2 Zgadza się może nie napisałem tego wystarczająco jasno, ale o to właśnie chodzi.
      Ad. 3 Trafna uwaga

  4. Przy okazji warto zwrócić uwagę też uwagę na @ToString na encji, które może wykonać wywołanie pól opisanych adnotacją @LazyLoad.

  5. To może nie wada, ale ostatnio znalazłem błąd, który był małoczytelny w Lomboku
    import javax.ws.rs.QueryParam + BeanParam -z pomocą tych 2 adnotacji można stworzyć BeanParam który zmapuje wszystkie queryParamy. W ramach refactoru dodaliśmy tą adnotację do klasy która wcześniej miała adnotację @Builder z lomboka.
    Builder wykluczał bezargumentowy kontstruktor i błąd był bardzo nieczytelny. To nie wada Lomboka, ale trzeba pamiętać że Builder będzie się kłócił z wstrzykiwaniem QueryParam czy JPA, może by mogli czytelniejszy wyjątek dodać

  6. Ja tej biblioteki nie używałem, ten wpis był pierwszym miejscem gdy zapoznałem się z nią, ale już widzę kilka problemów, nie wiem czy dobrze zrozumiałem zasadę działania, ale jeśli tak to kod jest budowany w procesie kompilacji zgodnie z annotations. Czyli jak na klasie postawie adnotacje do setterów i getterów to wygeneruje mi je dla wszystkich zmiennych, ale mogę mieć przecież zmienne prywatne określające stan obiektu i o ile getter byłby przydatny o tyle setter już niekoniecznie. Poza tym w tym getterze lub setterze mogłyby być robione jeszcze jakieś dodatkowe operacje i już to jest niemożliwe. To samo z konstrukorami. Konstruktor konstruuje obiekt, nie tylko ustawia jego membery. W takich sytuacjach jest to nieprzydatne. Kolejna sprawa to czas kompilacji. Kolejna to dodawanie do projektu dodatkowej biblioteki, która zasadniczo nie wnosi nic poza tym oczyszczeniem kodu to ryzykowna zabawa, bo zyskuje się niewiele (jak dla mnie to nic), a ryzykuje błędami które może mieć ta biblioteka i na dodatek może potem być problem z nazwami adnotacji z innych bibliotek czy frameworków, właściwie nie wiem czy w adnotacjach w Javie można rozwiązać konflikty nazw, jeśli można no ten ten problem odpada, ale chyba nie można, w każdym razie nie wiem tego. Pewnie jakbym zapoznał się z tym bliżej i przemyślał temat to znalazłbym więcej wad. Nie wiem jak wygląda sprawa z debuggerem :). Dobra kończę, bo pewnie pierdziele głupoty o 2 nad ranem 🙂

    1. Dobra kończę, bo pewnie pierdziele głupoty o 2 nad ranem 🙂

      Trochę tak 😉 a trochę masz rację, ale problemy, które opisałeś, są w większości nieistotne albo do rozwiązania w łatwy sposób. Zachęcam do zapoznania się z dokumentacją. Większość ludzi używa Lomboka, zwłaszcza jak korzystają ze Springa i Spring Data (bo jest już dołączony w tej paczce). Skraca on czas pisania kodu i to jest bardzo istotna zaleta 😉

Komentarze są zamknięte.