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:
- szybkość działania (czuć lag nawet na hi endowym komputerze)
- 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:
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ę...