Blogg

Här finns tekniska artiklar, presentationer och nyheter om arkitektur och systemutveckling. Håll dig uppdaterad, följ oss på LinkedIn

Callista medarbetare Anders Asplund Callista medarbetare Jesper Holmberg

KotlinConf 25

// Anders AsplundJesper Holmberg

Tillsammans med några kollegor deltog vi nyligen på KotlinConf 2025 i Köpenhamn – den årliga konferensen för Kotlinutvecklare. Programmet bestod precis som förra året av två intensiva konferensdagar med parallella spår och en workshopdag. Vi deltog i en heldagsworkshop med fokus på funktionell refaktorisering i Kotlin.

Kotlinconf innehåller presentationer om alla aspekter av Kotlin-världen. Många presentationer handlade i år om Compose Multiplatform och andra Android-teman, vilket ibland gav ett begränsat val av presentationer för oss med backend som främsta inriktning.

Naturligtvis var AI ett genomgående tema. Jetbrains presenterade sitt nya ramverk Koog som används för att bygga AI-agenter. Även Rod Johnson, grundaren av Spring Framework, presenterade sitt nya agent-ramverk Embabel. Båda verktygen är nysläppta och det blir intressant att följa hur de utvecklas.

kotlinconf25.png
Keynote-salen på KotlinConf 2025 i Köpenhamn (bild från KotlinConfs webbsida)

Små steg mot funktionell kod – vår workshopupplevelse


Workshopen där vi deltog utgick från ett existerande Kotlin-projekt med en någorlunda realistisk kodbas – tillräckligt komplex för att kännas igen från vardagen, men ändå hanterbar för övningar. Målet var att förbättra kodens struktur och uttrycksfullhet med hjälp av funktionella tekniker, utan att göra om allt från grunden.

Vi började med att identifiera och plocka bort onödig föränderlighet (mutability) i applikationens modellklasser. Steg för steg gjorde vi objekten mer oföränderliga (immutable), vilket bidrog till att göra flöden och beroenden tydligare.

Vi gick sedan vidare till att byta ut arvshierarkier mot en mer flexibel strategi-baserad design. Detta minskade kopplingar och gjorde det enklare att förstå olika beteenden i systemet utan att behöva följa långa kedjor av arv.

Ett annat fokusområde var felhantering. Istället för att kasta undantag överallt, introducerade vi explicita resultattyper (Result), som gjorde det tydligare vad som kunde gå fel – och när. Detta hjälpte till att lyfta ut affärslogiken och fånga upp fel tidigt.

En viktig lärdom var att göra förändringarna i små, inkrementella steg, där kodbasen hela tiden förblev körbar. Varje övning avslutades med ett stabilt mellanläge, ofta representerat av en commit. Det gav både trygghet och tydlighet i processen – och visade att refaktorisering inte måste vara ett stort risktagande.

Det handlade inte så mycket om att följa en viss filosofi till punkt och pricka, utan om att upptäcka hur funktionellt tänkande kan bidra till bättre och tydligare kod.

Kotlin utvecklas som språk


Utvecklingen av Kotlin som programmeringsspråk har varit en aning stillastående på senare år, främst p.g.a. att man behövde bli klar med den stora refaktoriseringen till Kotlin 2.0. Nu finns det dock några intressanta förändringar som kommer att finnas tillgängliga i uppkommande språk-releaser.

Kontextparametrar

Sedan den tidigare lösningen Context receivers drogs tillbaka har Kotlin-konstruktörerna arbetat på ersättningen Context parameters som i den uppkommande 2.2-releasen blir tillgänglig i beta-version. Context parameters ger en möjlighet att etablera en global kontext inom ett visst scope av koden. Kod längre ner i anropshierarkin kan sedan använda sig av denna kontext för sin egen logik, utan att kontexten explicit behöver skickas med i varje anrop.

Områden där detta kan vara användbart är t.ex. loggning, transaktioner eller felhantering. En övergripande metod kan t.ex. sätta upp en transaktion som underliggande metoder sedan verkar inom, utan att något transaktionsobjekt behöver skickas med. I och med att den underliggande koden har specificerat att en transaktionskontext måste finnas tillgänglig, kommer kompilatorn att säkerställa att den skrivna lösningen uppfyller kraven. Context parameters möjliggör också typsäker felhantering där kompilatorn kan garantera att fel som uppstår i en metod har logik högre upp i anropskedjan som kan hantera felet.

Obligatorisk Användning av Returvärden

En förändring i Kotlin som verkar kunna införas redan till hösten är att kompilatorn kommer att börja varna när returvärdet från ett metodanrop inte används av den anropande koden. Detta är en vanlig källa till fel, och är extra problematisk i funktionell kod där en metod ofta lämnar ifrån sig en kopia av den ingående parametern (eftersom man strävar efter icke-muterbara objekt). Samtidigt finns det situationer där det är korrekt att ignorera det returnerade objektet, men Kotlin-konstruktörerna har konstaterat att felaktig användning starkt överväger, och default-läget kommer därför att varna för all missad hantering. Vill man markera att ett returvärde kan ignoreras får man göra det med en annotering.

En ny typ av fel - Rich Errors

En uppkommande förändring av Kotlins typhierarki presenterades där Errors introduceras som en egen typ-kategori vid sidan av den existerande hierarkin där alla klasser ärver från Any-klassen. Det kommer att göra det möjligt för oss utvecklare att ange vilka fel som en metod kan producera redan i retur-värdet. Dessa fel måste sedan hanteras av anropande kod. Om detta låter som Checked exceptions i Java-utvecklares öron så är det här tänkt att fylla samma behov, men utan nackdelarna från Checked exceptions. Den största skillnaden är att ett Error kan fungera även med högre ordningens funktioner, och inte kastar hela stacken när ett fel uppstår.

Rich errors är en sorts fattigmans-version av Union types som finns i andra programmeringsspråk: det är bara en vanlig returtyp och ett eller flera errors som kan användas som signatur på en metod; det finns ingen möjlighet att kombinera två vanliga klasser. Anledningen till det är att Kotlin-konstruktörerna vill undvika att kompilatorn hamnar i situationer där fastställandet av runtime-typer leder till exponentiell komplexitet.

Detta verktyg får vi dock vänta på ett tag, eftersom det kommer att släppas i beta-version först med Kotlin 2.4, som är mer än ett år bort.

Namn-baserad Destructuring

En liten godbit som kommer experimentellt i Kotlin 2.4 är namn-baserad destructuring. I Kotlin har vi redan idag en lättanvänd möjlighet att lösa upp en komplex typ i enskilda variabler: val (street, city) = Address(street, city). De ingående komponenterna tilldelas ett eget variabelnamn, vilket är lättanvänt, men kompilatorn kan inte garantera att upplösningen blir korrekt om utvecklaren t.ex. har blandat ihop ordningen på parametrarna: val (city, street) = Address(street, city). Med namn-baserad destructuring flyttar man in val innanför parenteserna och dessutom anger man i koden vilket internt namn i den komplexa typen som ska tilldelas respektive variabel, och minskar därmed risken för fel. T.ex kommer föjande konstruktion inte att kompilera då variabeln inte matchar namnet i typen: (val streetName, val city) = Address(street, city)

Tack för att du läser Callistas blogg.
Hjälp oss att nå ut med information genom att dela nyheter och artiklar i ditt nätverk.

Kommentarer