Dzisiaj mamy dla Was coś specjalnego – jeśli kiedykolwiek chcieliście poznać podstawy Kotlina, nowa edycja naszego przeglądu będzie do tego świetnym miejscem. Zapraszam serdecznie.
Cześć,
Dzisiaj mam dla Was specjalne wydanie. W dniu jutrzejszym mam przyjemność robić na AGH w Krakowie wprowadzenie do Kotlina dla koła naukowego „Kernel”, dlatego też przygotowałem dość bogaty zestaw notatek, który pomoże każdemu kto chce poznać się z językiem od JetBrains. Jako, że może wielu z Was potrzebuje takiego wprowadzenia, bo np. nie mieli jeszcze do czynienia z Kotliniem a chcieli go spróbować, postanowiłem dzisiejszą edycję poświęcić właśnie temu tematowi. Zapraszam do lektury
Zacznijmy od odrobiny historii
Należę do ludzi, którzy twierdzą, że nic tak nie pomaga w zrozumieniu filozofii stojącej za danym językiem programowania, jak poznanie kontekstu, w którym powstawał. Nie zawsze jest to proste – wiele z dziś używanych technologii powstawało jeszcze w czasach przedinternetowych, więc wszelkiej maści materiały są mocno porozrzucane – złożenie ich więc w spójny obrazek wymaga sporej ilości pracy. Na szczęście w wypadku Kotlina, który w tym roku skończył 10 lat, wszystko mamy w zasadzie podane na tacy. Nie dość, że JetBrains od samego początku było bardzo otwarte i dbało o dobrą pracę ze społecznością, to jeszcze z przypadającej na ten rok dziesiątej rocznicy postanowili dokonać kronikarskiego obowiązku spisania pełnej linii czasu rozwoju języka.
I nie mówimy tutaj o jakimś poście blogowym, a o pełnej, bogato ilustrowanej historii oryginalnych prototypów i kolejno dodawanych funkcjonalności.
To jednak nie wszystko. Okrągłą rocznicę dopełnił też specjalnie nakręcony na tą okazję dokument. Znajdziecie w nim wypowiedzi oryginalnych twórców, wspominki z pierwszych spotkań projektowych, nadzieje i obawy. Powyższa strona internetowa jest źródłem nieco treściwszym, ale to wspomniane wideo pozwoli poczuć Wam atmosferę, w jakiej rodził się Kotlin jako język. Dowiecie się m.in. skąd taka, a nie inna nazwa.
Ten Years of Kotlin: The Story of The Programming Language
Zainstaluj teraz i czytaj tylko dobre teksty!
Zachęciłeś mnie – chciałbym się nauczyć trochę składni języka – gdzie najlepiej zacząć?
Zdecydowanie pierwszym Waszym krokiem powinna być oficjalna dokumentacja. I nie mówimy tutaj o zwykłych docsach w klasycznym tego słowa znaczeniu – Kotlin to język nowoczesny nie tylko sam w sobie, ale jego cała otoczka zdecydowanie przystaje do obecnych standardów. Dlatego też oficjalna strona powinna być miejscem, od którego zaczniesz.
Znajdziecie na niej:
- Przewodnik stanowiący idealne wprowadzenie dla wszystkich zaczynających swoją przygodę z Kotlinem, który przeprowadzi Cię przez niezbędne podstawy
- REPL w przeglądarce, pozwalający pobawić się składnią
- Plugin do Intellij Idea, który umożliwia przejście przez szereg zadań pozwalających sprawdzić, czy coś nam w głowie z przeczytanej teorii zostało
- No i oczywiście pełną dokumentacje referencyjną.
To właśnie na stronie Kotlina znajdziecie też opracowanie bardziej zaawansowanych tematów, takich jak Korutyny. Ten feature jest w mojej opinii jednym z najciekawszych aspektów języka i niejeden z Was właśnie dla niego się nim właśnie zainteresował. Tutaj ponownie odezwie się moja żyłka historyka, ponieważ nie mogę nie polecić Wam prezentacji Roman Elizarov — Structured concurrency. To właśnie Elizarowowi zawdzięczamy to, jak korutyny wyglądają w swojej ostatecznej formie, a swoją pracę wykonał tak dobrze, że obecnie pełni rolę szefa całego projektu.
Jeżeli chodzi zaś o materiały nie pochodzące bezpośrednio od JetBrains, na pewno godnym wspomnienia jest tutaj Kotlin is Awesome!. Jeżeli nie znacie tak zwanych “awesomów”, to są to utrzymywane przez społeczność zbiory najlepszych zasobów powiązanych z daną technologią. Zwykle występują pod postacią GitHubowych repozytoriów, w wypadku Kotlina mamy do czynienia z pełną stroną internetową.
Sam język to tylko wierzchołek góry lodowej. Jak wygląda tooling?
Dlatego teraz zrobimy szybki przegląd przez najważniejszy tooling dla Kotlina.
Intellij Idea
Wszystkim działaniom JetBrains przyświeca fakt, że dobra narzędziówka zwiększa w olbrzymim stopniu wydajność programistów. Dlatego nikogo nie dziwi, że jedną z idei (hehe) założycielskich Kotlina było stworzenie języka, który będzie w maksymalnie wygodny sposób integrował się z IDE. Ma to swoje dobre strony – Intellij Idea jest świetnym IDE, które jest używane przez prawie 80% programistów Java. W 2020 roku do beczki miodu dosypano jednak łyżkę dziegciu – o ile ilość użytkowników Kotlina nie używających narzędzi od jego twórców zawsze była homeopatyczna, to w zeszłym roku JetBrains zdecydowało się na iście applowski ruch, “wmergowując” plugin do obsługi Kotlina do repozytorium IDE. Spowodowało to, że język bardzo mocno splątał się z jedynym słusznym narzędziem, przez co w zasadzie niemożliwe stało się używanie go z jakimkolwiek innym IDE. JetBrains twierdzi, że pozwoliło im to na uzyskanie znacznie wyższej jakości narzędzi, ale jeżeli cenisz sobie otwartość ekosystemu lub jesteś fanem Emacsa, Twoje zęby mogą niejednokrotnie zazgrzytać.
Gradle
Kolejnym ważnym narzędziem jeśli chodzi o wytwarzanie oprogramowania w Kotlinie jest Gradle. Tutaj, co ciekawe, mówimy o obopólnej korzyści. Z jednej strony, Gradle od początku było build toolem wspierającym język JetBrains, z drugiej Kotlin dokonał w nim sporej rewolucji. To właśnie w tym języku pojawił się bowiem pierwszy alternatywny DSL do definiowania buildów gradlowych.
W porównaniu do oryginalnego syntaxu, opierającego się o język Groovy, wariant Kotlinowy pozwala na znacznie lepsze podpowiadanie składni. Jest to więc obiektywnie lepsza metoda tworzenia build skryptów, ale niestety nie mogę jej z czystym sumieniem polecić. Przez lata w sieci pojawiło się masę tutoriali, poradników i przykładów dla groove’owego wariantu Gradle, dlatego też o wiele łatwiej ciągle trafić na “gotowce” rozwiązań właśnie w nim. Kotlin niestety ciągle stanowi w tym ekosystemie język drugiej kategorii. To się powoli zmienia, ale jednak nie tak szybko jak się spodziewałem, gdy rozwiązanie debiutowało kilka lat temu.
Kompilator
Ach zbierają nam się te wady Kotlina jakoś przy tej sekcji tooling. Przez lata to właśnie wolna kompilacja była najczęściej przywoływaną wadą języka od JetBrains. I jeśli wydaje Wam się, że to pewnie przesada, to niestety nie – sam pamiętam, że moje pierwsza przygoda z Kotlinem prawie zakończyła się w momencie, gdy okazało się, że odpalenie unit testów trwa około minuty (!). Na szczęście od tamtego czasu sytuacja się znacznie poprawiła, a dzięki nowej reprezentacji wewnętrznej zyskaliśmy nie tylko szybkość kompilacji, ale również lepszą interoperacyjność z samą Javą (co też historycznie bywało problemem). Kompilacja Kotlina jest zresztą bardzo ciekawym tematem, twórcy stosują masę sztuczek, żeby zapewnić efektywność całego procesu. Kulminacją prac ostatnich lat ma być zaś K2 – kompilator, który ma pozwolić na szybszą iterację nad nowymi funkcjami języka poprzez uwspólnienie kluczowych elementów procesu między Kotlina JVM, Kotlina JS i Kotlina Native.
Analiza Statyczna
Jestem fanem analizy statycznej, dlatego bardzo cieszę się, że Kotlin posiada w tym temacie sporo interesujących narzędzi. Przez lata były one utrzymywane głównie przez społeczność. Mogliśmy używać:
- ktlinta, który sprawdzał nasz kod ze zbiorem predefiniowanych reguł syntaktycznych
- detekt, który sprawdzał nasz kod pod kątem popularnych podatności.
JetBrains postanowiło jednak postanowiło dorzucić coś od siebie i stworzyło Qodanę – narzędzie przeznaczone do odpalania w ramach terminala lub systemu CI, posiadające możliwości zbliżone do tych posiadanych przez tooling Intellij. Qodana jest obecnie w Preview, ale już teraz zapowiada się na istotny dodatek do portfolio narzędzi od JetBrains.
A jak już jesteśmy w temacie analizy statycznej: firma pokazała ostatnio również Kover – narzędzie do liczenia pokrycia kodem. Sama praktyka liczenia Code Coverage stała się ostatnimi czasy dość kontrowersyjna, ale według ma ona sporo zastosowań, więc cieszy mnie inwestycja również w tym obszarze.
To jeszcze przejdźmy przez najważniejsze biblioteki
- Spek – główna biblioteka do testów, która mnie osobiście ze wszystkich dostępnych na rynku najbardziej przypomina JavaScriptow Jasmine. Pozwala na ładne pisanie zagnieżdżonych testów w stylu BDD i posiada dobre wsparcie do testowania korutyn
- kotlinx.serialization – Kotlin posiada bardzo dobre wsparcie dla serializacji do różnych formatów takich jak JSON czy YAML, ale nie w bibliotece standardowej a właśnie w zewnętrznym rozszerzeniu kotlinx.serialization (które też jest tworzone przez JetBrains). Oprócz tego, że jego konfiguracja wymaga nieco Gradlowej magii, to jest na tyle wygodne, że dokładam je do właściwie każdego projektu, nie spoglądając wcale w kierunku np. Jacksona, który też ma wsparcie dla Kotlina
- http4k – mamy tu do czynienia z klientem HTTP. Choć nie jest to produkt JetBrains, co nie przeszkadza jej w byciu jednym z najczęściej wybieranych rozwiązań w Kotlinowym świecie. Podobnie jak poprzednicy, cechuje się dobrym natywnym wsparciem dla różnych rozwiązań języka i stanowi wygodne rozwiązanie do produkcji i konsumpcji różnych API
- KTOR – tutaj mówimy już o rozwiązaniu, które można umiejscowić gdzieś pomiędzy biblioteką, a frameworkiem. Jest to forma http4k na sterydach, dająca użytkownikom w zasadzie możliwość stworzenia pełnego restowego API w sposób mocno funkcyjny. KTOR w pełni wykorzystuje moc korutyny przy tworzenia API.
Całość zakończymy zaś przeglądem wsparcia Kotlina w popularnych frameworkach
Spring Boot
Spring od dawna mocno inwestuje w Kotlina – i to widać. Jego twórcy regularnie wydają kolejne edycje swojego przeglądu The State of Kotlin Support in Spring, gdzie chwalą się jak bardzo kochają Kotlina i starają się być na bieżąco z zamieszczanymi zmianami. Dlatego też np. już dzisiaj możecie używać WebFluxa opartego o korutyny. Bardzo ciekawym projektem jest też KoFu – specjalny DSL, pozwalający na konfigurowanie Spring Bootowej aplikacji za pomocą Kotlina
val app = webApplication {
logging { level = LogLevel.DEBUG }
beans { bean<SampleService>()}
webMvc {
port = if (profiles.contains("test")) 8181 else 8080
router {
val service = ref<SampleService>()
GET("/api") {
ok().body(Sample(service.generateMessage()))
}
}
converters {
string()
jackson {
indentOutput = true
}
}}}
data class Sample(val message: String)
class SampleService { fun generateMessage() = "Hello world!" }
fun main() {
app.run()
}
Na koniec wspomnę, że również Spring Native wspiera Kotlina (w jego edycji Native), pozwalając na generowanie obrazów do uruchomienia w ramach maszyny GraalVM (stan obecnego wsparcia dla GraalVM to jest ogólnie frapujący temat, który kiedyś nie omieszkam tu opisać).
Micronaut
Następca Grailsów od razu wskoczył też na Kotlinowy wagonik, a twórcy chwalą się, że od początku traktowali język jako obywatela pierwszej kategorii – co akurat jest do nich podobne, zawsze lubili nowinki (Grails to w końcu skrót od Groovy on Grails). Widać, że wzięli sobie do serca wspieranie wszystkich konceptów języka, ponieważ pozwalają na użycie korutyn w zasadzie na przekrój całego stacku aplikacji. Ich wsparcie opiera się wprawdzie o nakładkę na Reactora poprzez użyciu biblioteki org.jetbrains.kotlinx:kotlinx-coroutines-reactor, ale w dalszym ciągu pozwala to na tworzenie np. bardzo eleganckich kontrolerów:
@Get("/simple", produces = [MediaType.TEXT_PLAIN])
suspend fun simple(): String {
return "Hello"
}
Całość oczywiście również wspiera Kotlinowy wariant GraalVM, a także bardzo dobrze integruje się ze wspomnianym KTORem. Nie umniejszając Springowi, śmiem twierdzić, że ze wszystkich narzędzi to właśnie Micronaut najlepiej sprawdza się w użyciu z Kotlinem.
Quarkus
Ze względu na specjalne miejsce w moim serduszku dla Jakarty EE, oparty o Microprofile Quarkus to mój ulubiony z nowopowstałych JVMowych frameworków. Niestety, jeżeli chodzi o wsparcie Kotlina, wypada on chyba najsłabiej. Oczywiście, większość funkcjonalności działa dobrze (twórcy Quarkusa chwalą się min. świetnym wsparciem Kotlina przez ich “dev mode”, pozwalający na szybkie przeładowanie klas w aplikacji), ale niestety wsparcie korutyn mocno kuleje. Microprofile – młodszy, zwinniejszy brat Jakarty EE jest tutaj pewną kulą u nogi. Samych korutyn można używać, ale w miejscach, gdzie wspierany jest standard Microprofile (czyli np. w endpointach Restowych), niezbędne jest opakowanie suspendów za pomocą biblioteki SmallRye Mutiny.
fun mutinyService(id: Long): Uni<Fruit?> {
GlobalScope.async {
findById(id)
}.asUni()
}
Jest to bardzo brzydkie, a efekt robi się co najwyżej średni. Dlatego o ile nie zniechęcam zupełnie do używania Quarkusa z Kotlinem, to jednak nie wykorzystacie w ten sposób najpotężniejszych możliwości języka jeśli chodzi o współbieżność… przynajmniej nie w elegancki sposób.
Zainstaluj teraz i czytaj tylko dobre teksty!