Maven vs Gradle - XI 2021 edition

0

Tak się składa że na https://jvm-bloggers.com/ (który polecam tym co nie znają) wylądował wpis: https://nullpointerexception.pl/dlaczego-nie-lubie-mavena-vlog-03/ w którym autor (być może obecny tutaj) dowodzi Gradle > Maven.

Miałem napisać wpis na bloga, ale powiem szczerze nie chce mi się więc wrzucę post, wcale nie gorszy tematycznie.

Po pierwsze ja jestem fanem Mavena, przynajmniej na moich pet projektach. Maven nie jest doskonały, dwie podstawowe wady to:

  1. szybkość działania (czuć lag nawet na hi endowym komputerze)
  2. brak automatycznego przebudowywania zależności

Pozwólcie że rozwinę punkt 2. Otóż jeżeli mamy projek:

app
 +- moduleA
 +- moduleB

Taki że moduleB zależy od moduleA, następnie dokonamy zmian w moduleA i uruchomimy ./mvnw exec:java -pl moduleB to niestety moudleA nie zostanie przebudowany. Ogólnie jeżeli nie wykonamy na moduleA install to Maven nie będzie nawet w stanie znaleźć zależności na moduleA. Jest to dość spora przeszkoda którą muszą pokonać początkujacy Maveniarze. Najczęstsza rada jaką słyszę to po prostu odpalanie ./mvnw install na całym projekcie (+- clean), co przy szybkości działania Mavana powoduje wiele biadolenia i narzekania.

Na koniec jeszcze jedna wada, nazwijmy ją punktem 2.5: site's. Jeżeli ktoś próbował generować zagregowane raporty Maven'em to jest to prawdziwa masakra. Mam jeszcze flashbacki po tym przeżyciu (jeżeli ktoś nie wie o co chodzi to tak w telegraficznym skrócie Maven może pozbierać raporty z code coverage, analizatorów kodu, propozycje updateów zależności, javadoc'i i wygenerować z nich statyczną stronę którą można potem na CI wypchnąć na jakiś serwer, także żeby każdy mógł zobaczyć to nasze nędzne pokrycie :D).

OK tyle ze złych rzeczy, teraz te dobre. Jaki jest XML każdy widzi, podpowiedzi w InteliJ są zadowalające (np. fajne są podpowiedzi na żywo przy deklarowaniu zależności typu junit), ba IJ potrafi nawet wyświetlać pomoc do tagów:
screenshot-20211130171135.png

Proces budowy bazujący na konwencjach jest banalny po tym jak już się go zrozumie. Ogólnie budowanie składa się z kilkunastu następujących po sobie faz: https://medium.com/@yetanothersoftwareengineer/maven-lifecycle-phases-plugins-and-goals-25d8e33fa22 (pełny rysunek może być przytłaczający, początkujący wykorzystują tylko kilka z tych faz). Wtyczki dodają tak zwane gole do poszczególnych faz, oznacza to tyle że gol wtyczki wykona się na określonym etapie budowania. Generalnie daje się to juniorom wyjaśnić w 15 min, co bardziej opornym duszom w 30 min pod tablicą.

Pisanie własnych wtyczek nie jest trudne, wtyczki piszę się w Javie, można do nich dopisywać testy (ważne!) oraz stosować inne dobre praktyki znane z codziennej pracy.

Tworzenie wielomodułowych projektów również nie jest trudne, choć wymaga pewnej świadomości (punkt 2).

Pominę tutaj aspekty wspólne dla Gradle i Mavena typu bazowanie na konwencjach (układ kodu src/main src/test itp).


Popatrzmy teraz na Gradle (pominę tutaj płatne funkcjonalności takie jak Gradle Enterprise):

  • Groovy jako język definiowania buildu. Nie każdy zna Grooviego, tak naprawdę to bardzo niewiele osób zna dobrze ten język, większość piszę po prostu Javę w Groovy i liczy że będzie działać. Groovy jako język jest zagrożony wymarciem (wersja 4.0 ma wspierać JDK 17, więc wymarcie raczej w kategoriach spadającej liczby użytkowników).
  • Powyższe argumenty skłoniły firmę matkę do zmiany języka na Kotlin (https://docs.gradle.org/current/userguide/kotlin_dsl.html), większość osób z dolinki używa już Gradle + Kotlin. Niestety oznacza to że początkujący zostali na lodzie bo bardzo dużo materiałów na SO i forach internetowych jest w Groovie'im. W IJ jest co prawda automatyczne tłumaczenie w locie ale z działaniem tego automatu bywa różnie. Jednym słowem początkujący piszący w Kotlin DSL muszą przygotować się na przedzieranie się przez dokumentację i tłumaczenie jednego DSLa na drugi.

A teraz przejdzmy do naprawdę poważnych wad Gradle:

  • Możliwość pisania ad-hoc skryptów w Groovie, najczęściej oznacza pisanie nie testowalnego kodu pod płaszczykiem "to tylko build, po co testować". Po kilku latach takiego podejścia mamy istną stajnię Augiasza, którą posprzątać można tylko poprzez przepisanie build'a na nowo. Również modyfikacje build skryptu stają się ryzykowne.
  • Praktycznie brak podpowiedzi w IDE, kryptyczne błędy w runtime'ie, potrzeba googlania prawie wszystkiego np. a jak w tym Grooviem zadeklarować tablicę?
  • Morze tasków, task taskiem pogania, taski mają między sobą zależności, na dużym projekcie można od tego osiwieć. Do tego mamy tak naprawdę 2 przejścia - jedno gdzie generowana jest konfiguracja, i drugie które na podstawie konfiguracji faktycznie buduje już aplikacje. Nie jest to dla mnie intuicyjne.

Oczywiście Mavena używam na własnych projektach, gdzie wszystko robię sam więc i znam ten system budowania o wiele lepiej. Gradle używałem w pracy na Monorepo, gdzie była dość skomplikowana konfiguracja. I niestety powiem że nie rozumiałem co tam się faktycznie dzieje.

Także ja stoję murem za Maven'em i sypię głowę popiołem bo nie znam Gradle tak dobrze jak bym chciał.
Na koniec bonus, jeden z bardziej skomplikowanych buildów które wyrzeźbiłem: https://github.com/marcin-chwedczuk/javafx-validation/blob/master/pom.xml Zbliżony złożonością do tego do można spotkać w firmach (+- liczba modułów i zależności, na prawdziwej aplikacji będzie o wiele większa).

Czekam na wasze opinię...

5

Maven masterrace.
Gradle ma niekompatybilne API co wersje co potrafi doprowadzić człowieka do szału, bo trzeba dobierać wersje gradle np. pod konkretną wersje frameworka bo inaczej plugin do budowania się wysypie. Zresztą w ogóle gradle to jest taki trochę anty-python, bo python ma dewize "there should be only way to do it", gdzie w gradle masz 17 sposobów na osiągnięcie tego samego efektu, ale 13 z nich przestanie działać w kolejnej wersji :D Dodatkowo gradle ma jakieś zupełnie zrypane i nieintucyjne cachowanie artefaktów. W mavenie wiadomo że jak robisz install to leci do m2/repository i jak chcesz to mozesz skasować artefakt i przebudować, albo skasować i maven pobierze z remote. W gradle to jakiś hardkor, bo jest kilka miejsc gdzie artefakt może się zasiedzieć i powodzenia życzę jeśli chcecie zmusić go zeby pobrał coś jeszcze raz z remote (np. zrobiliście release tej samej wersji jara do repozytorium artefaktów i chcecie zeby pobrało poprawioną wersję).

1

A może bazel, który ostatnio zyskuje na popularności (np, Google używa go w nowych projektach):
https://bazel.build/

4

Z dwóch , (złów, zeł)?
wolę gradle, bo:
a) mniej pitolenia w buildzie i nie muszę patrzeć na xml
b) przez punkt a) gradle jest IMO dużo wygodniejszy jak mamy dużo modułów (nowy moduł nawet nie musi mieć żadnego pliku z buildem)
c) bo można uratować build nawet jak autorzy pluginów coś porypią (ręcznie doskryptowując braki)
d) bo działa super szybko - build.cache i inne takie naprawde rządzą
Maven działa znośnie jak masz standardowe i dobrze przetestowane moduły. Ale miałem już kilka razy przypadek (w web), że plugin coś rypał i niewiele się dało zrobić, poza ściągnięciem źródeł, poprawieniem plugina i wpierniczaniem do lokalnego artifactory (dużo pierniczenia).

wady gradle:
a) nowa wersja to zawsze ruletka, przeważnie jakiś plugin przestaje działać
b) składnia groovy jest porypana
c) składnia .kts jest miejscami porypana (nie wygląda elegancko)

Problemów ze stale artefaktani nie miałem już dawno. Dwa lata temu bywały.

1 użytkowników online, w tym zalogowanych: 0, gości: 1