W dniu dzisiejszym same nowości – nowy Micronaut, nowy Kotlin, a także nowy sposób formatowania JavaDocs. Zapraszamy do lektury!
1. Micronaut 3.0 Wydany 🔬
Jako że poprzednią edycję “zawłaszczyło” nam podsumowanie roku, nie mieliśmy okazji poinformować Was o ważnej premierze w świecie javowych frameworków. Micronaut (i może trochę śp. Dropwizard) parę lat temu zapoczątkował nowy rzut javowych frameworków, chcący rzucić rękawice dotychczas niepokonanemu Springowi. Był to moment, gdy po latach starań Java EE zgubiła gdzieś chwilowo zyskany impet (głównie przez fatalne wsparcie dla Microserwisów) i w zasadzie zaczynała coraz bardziej zjadać własny ogon. Wtedy to twórca Grailsów (frameworków Rails-like przeznaczonego dla Ruby-like języka Groovy) zdecydował się pokazać światu swoje dziecko, stanowiące alternatywę dla Spring Boota. Głównym wyróżnikiem Micronauta była rezygnacja z refleksji na rzecz procesorów anotacji i generowaniu niezbędnego kodu na poziomie kompilacji. Rozwiązanie to było wyraźnie inspirowane rozwiązaniami wykorzystywanymi w programowaniu mobilnym i stanowiło powiew świeżości w nieco zastałym ekosystemie.
Od tego czasu świat zdążył się zmienić. Pojawiła się cała nowa generacja frameworków, takich jak Helidon i Quarkus, a Micronaut – choć wciąż popularny – nie jest już w awangardzie JVMowego programowania. Dlatego też wiadomość o pojawieniu się trzeciego wydania przeszła nieco bez echa. Nie oznacza to jednak, że twórcy nie przygotowali niczego interesującego.
Jeden z “highlightów” wydania to z pewnością migracja z RxJava 2 do Project Reactor (co pewnie ma na celu ułatwienie migracji użytkownikom Springa). Wersja 3.0 zmienia też sposób dziedziczenia adnotacji. Do tej pory komponent domyślnie dziedziczył wszystkie adnotacje z interfejsów lub klas nadrzędnych. Od nowej edycji tak będzie się działo tylko w wypadku dostarczenia dodatkowej adnotacji @Inherited.
Micronaut ostatecznie “przepisał” się też na namespace jakarty, porzucając stare interfejsy javax dla anotacji PreDestroy i PostConstruct. Wprowadzono również sporo zmian w obsłudze GraalVM, a także przepisano implementacje filtrów serwerowych, które zaczną zachowywać się inaczej w sytuacji wystąpienia wyjątku. W Micronaut 2.0 zdarzała się możliwość ponownego wykonania filtru w niektórych przypadkach, Micronaut 3.0 postanowił położyć nacisk na spójność i przewidywalność – niezależnie od sytuacji, konkretny filtr wykona się tylko raz.
Prywata: Sam używałem Micronauta w jednym z projektów i bardzo dobrze to wspominam (poza pewnymi brakami w dokumentacji…). Dlatego jeśli macie ochotę poeksperymentować – myślę że będzie to odświeżające doświadczenie.
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Wydano Kotlina 1.5.30 🍅
O Kotlinie 1.5.30 już pisaliśmy przy okazji wersji bety tego wydania, ale jako że nareszcie trafiło ono do szerokiej publiki, warto się mu przyglądnąć nieco bliżej. Ponieważ Kotlin 1.5.30 jest ostatnim “minorem” przed Kotlin 1.6.0, zawiera wiele funkcji języka eksperymentalnego i standardowych bibliotek, które pojawią się w dużym wydaniu. O środowisku uruchomieniowym (wsparcie dla M1, nowa reprezentacja pośrednia) pisaliśmy w linkowanym poście, dzisiaj zajmiemy się zmianami w samym języku.
Nowe wydanie przynosi między innymi ‘sealed when’, które mają zapewnić, że ta kotlinowa alternatywa dla switchy stanie się “wyczerpująca” – kompilator rzuci błąd, jeśli nie obsłużymy wszystkich przypadków.
Wprowadzona też zostaje obsługa funkcji suspend jako funkcyjnych nadtypów:
class MyClass: suspend () -> Unit {
override suspend fun invoke() { TODO() }
}
Należy tutaj wspomnieć, że w przypadku tego ostatniego istnieją ograniczenia. Ze względu na sposób, w jaki korutyny zachowują się na poziomie JVMa (miałem okazję kiedyś zrobić wystąpienie na ten temat), niemożliwe jest przykładowo miksowanie ich z funkcyjnymi typami:
suspend (Int) -> ((Int) -> Unit)
Oprócz powyższych zmian w funkcjach i składni języka (dostępnych za eksperymentalną flagą), Kotlin 1.5.30 to także sporo zmian pod maską. Wprowadzone zostało m.in. wsparcie dla tak zwanych “recursive generic types”, czyli rekurencyjnych typach generycznych – takie, w których typ jest definiowany poprzez samego siebie. Jest to uzupełnienie Kotlina o pewne braki jego systemu typów w stosunku do Javy, które uwidoczniły się w sytuacjach brzegowych. Przykładem niech będzie interfejs TestContainers:
public class PostgreSQLContainer<SELF extends PostgreSQLContainer<SELF>> extends JdbcDatabaseContainer<SELF> {
Do tej pory Kotlin miał problemy z inferowaniem tego rodzaju typów, co prowadziło do koślawców językowych. Teraz zmieni się to wraz z nową wersją języka.
Jak widać, niektóre z powyższych zmiany są dość hermetyczne (Kotlin pod tym względem przypomina mi nieco TypeScripta), jednak ostatecznie składają się one na coraz wygodniejszy i bezpieczny dla programisty język. Osobiście bardzo czekam na “zapieczętowane wheny”, już widzę dla nich kilka zastosowań.
Zainstaluj teraz i czytaj tylko dobre teksty!
3. Snippety trafiają do JavaDocs 📜
A na koniec drobnica… ale dawno nie było JEPów. Java wprowadziła znacznik @snippet do JavaDoc, co ma na celu uprościć dołączanie przykładowego kodu źródłowego do dokumentacji API.
Do tej pory dokumentacja nie posiadała specjalnego tagu pozwalającego programistom przekazać przykładowe użycia API. Teraz to się zmieni. Co ciekawe, twórcy API zapewnili użytkownikom dwa różne warianty. Przykłady będzie można przekazać “inline”:
/**
* The following code shows how to use {@code Optional.isPresent}:
* {@snippet :
* if (v.isPresent()) {
* System.out.println("v: " + v.get());
* }
* }
*/
Ale również jako zewnętrzny plik:
/**
* The following code shows how to use {@code Optional.isPresent}:
* {@snippet file="ShowOptional.java" region="example"}
*/
---------------------------
public class ShowOptional {
void show(Optional<String> v) {
// @start region="example"
if (v.isPresent()) {
System.out.println("v: " + v.get());
}
// @end
}
}
Pytanie do Was – czy często zdarza się Wam używać znaczników JavaDocs w swoim kodzie? Osobiście robiłemrobiłe to raz, przy tworzeniu generycznej biblioteki dla całej firmy… i muszę przyznać, że trochę mnie to bolało ze względu na pogorszenie czytelności kodu – dlatego też cieszę się, że twórcy rozważyli możliwość użycia zewnętrznych plików jako “sampli”. Przy całym moim oporze przed dokładaniem JavaDoców samemu, z perspektywy użytkownika API szanuje bowiem jednak każde działania tego typu. Ot, ludzka natura jest pełna sprzeczności.