Correct gebruik van Optional in Java 8

Met de introductie van Java 8 kregen we ook de beschikking over de class java.util.Optional. Het correct gebruik hiervan kan, zeker in combinatie met streams, veel cleanere code opleveren. Maar niet altijd biedt het voordelen.

Optional in plaats van if-else

Vaak zie ik constructies als deze verschijnen:

In plaats van de ‘oude stijl’ if-statement:

Ik vind het laatste nog steeds een stuk leesbaarder. In dit geval levert het wrappen in een Optional dus niets op. Sterker nog: de performance van een Optional is in dit geval een stuk slechter dan een simpel if-statement, vanwege het instantiëren van een nieuw object en extra methode aanroepen. In dit geval zou ik dus ook gewoon een if-statement gaan.

Soms zou het gebruik van Optional iets leesbaarder zijn ten opzichte van if-else-statements:

In plaats van:

Maar hier wordt het voor statische code analyseertools zoals SonarQube als een stuk lastiger om te bepalen welke paden je code heeft en welke je getest hebt. Dat is dus ook iets om rekening mee te houden.

Optional bij ontwerp van APIs

Waar Optional erg kan helpen is bij het ontwerpen van APIs.

Ik hanteer tegenwoordig de volgende regels:

  1. Als een methode een lege waarde kan returnen, declareer het return type dan als Optional en return in zo’n geval Optional.empty().
  2. Als een methode géén Optional return type heeft, dan mag ik er als aanroeper vanuit gaan kunnen dat de return value nooit null is.
  3. Parameters zijn nooit van het type Optional en dus ook nooit null.

Dit communiceert namelijk veel beter de intentie en mogelijke gevallen naar de gebruiker van een API en dwingt de aanroeper om dergelijke situaties netjes af te handelen.
Parameters die null kunnen zijn, zijn eigenlijk extra paden in een methode die beter op een andere manier kunnen worden opgelost (met classes of overloaded methoden).

Nadelen van Optional

Het maakt debuggen iets lastiger omdat het de daadwerkelijke waarde wrapt.

Optional is niet Serializable waardoor je hem moeilijk als type van een field kan gebruiken.

Conclusie

Als ik alles afweeg moet ik concluderen: gebruik Optional alleen als return type bij APIs en gebruik in andere gevallen gewoon if-else-statements. Hierbij communiceer je de intentie duidelijk, maar houd je code ook simpel. En simpel is altijd beter.

 

Lazy properties in Kotlin

Soms heb je een alleen-lezen property in een class waarvan de waarde gecalculeerd wordt. Als het calculeren dan complex is en traag, dan wil je dit wellicht alleen doen wanneer de property daadwerkelijk wordt uitgelezen en ook slecht één keer.

In dat geval biedt Kotlin een interessant constructie: lazy properties.

Voor de implementatie van het bordspel Hoogspanning (code zie GitHub) is het nodig om te bepalen hoeveel steden een speler van stroom kan voorzien.

Dit is een combinatorisch NP-hard probleem en de calculatie daarvan kan ik met een lazy property oplossen:

Lees meer over delegated properties en de standaard lazy delegate: https://kotlinlang.org/docs/reference/delegated-properties.html#lazy

Unit testing in Kotlin met Spek

Voor deze blog post gebruik ik een side project als basis: een implementatie van het populaire bordspel Hoogspanning (PowerGrid) geschreven in Kotlin (GitHub).

Spek

Tests zijn feitelijk je specificaties en de documentatie van de systeem. Bij unit tests die geschreven zijn voor bijvoorbeeld JUnit is het vaak lastig om te zien wat precies de gegeven situatie is en wat het verwachte resultaat is.

En natuurlijk willen we bij een Kotlin project ook een testoplossing die past bij Kotlin! Daar komt Spek om de hoek kijken. Spek heeft een eigen DSL die deze aspecten van tests expliciet maakt. Een beetje vergelijkbaar met frameworks als Spock voor Groovy of Jasmine voor JavaScript.

Dependencies

Voeg Spek toe aan je Gradle project:

 

Heb je een Maven project? Daar is ook een plugin voor beschikbaar.

Installeer ook de Spek plugin voor IntelliJ IDEA om de tests vanuit de IDE te kunnen draaien.

Tests schrijven in Spek

Een specificatie voor de class PowerGrid zou er bijvoorbeeld zo uit kunnen zien:

Lees er meer over op: http://spekframework.org/

Waarom ik Kotlin te gek vind

Kotlin is een relatief nieuwe programmeertaal ontwikkeld door JetBrains, het bedrijf achter de bekende ontwikkelomgeving IntelliJ IDEA.

Een tijd geleden besloot ik me eens te verdiepen in Kotlin om er achter te komen wat de voor- en nadelen zijn. Sinds ik een side project met Kotlin heb gedaan ben ik helemaal om: ik vind het te gek. Waarom?

Veelzijdig

Het target zowel de JVM, Android en je browser (JavaScript). Eén taal voor je backend, mobile app en web frontend dus.

Kort en veilig

Voor ontwikkelaars die bekend zijn met Java zal Kotlin zeer comfortabel aanvoelen.

De filosofie er achter is super tof: neem gewoon de facto standaarden en industry good practices als defaults! Zo zijn classes standaard closed en parameters final. Ook is de type inference zeer goed en is werken met generics een stuk makkelijker dan in Java.

Je hoeft ook niet meer op te schrijven dan strikt noodzakelijk. Zo mag je bijvoorbeeld accolades weglaten als een class geen verdere members declareert.

En nooit meer NullPointerExceptions! Variabelen kunnen standaard niet null zijn. Wil je dat toch per se wel, dan zal je dat expliciet moeten aangeven en dwingt de compiler je om het overal netjes af te handelen.

Ook biedt Kotlin veel meer mogelijkheden om echt functioneel te programmeren ten opzichte van Java. Zo zijn higher-order en pure functies veel natuurlijker op te schrijven en gaat Kotlin efficient om met staartrecursie.

Compabiliteit

Kotlin is 100% compatibel met classes uit Java of Scala en andersom. Dit stelt je in staat om te integreren met bestaande code bases of zelfs hybride te werken.

Uiteraard heeft de ontwikkelomgeving IntelliJ IDEA volledige ondersteuning voor Kotlin. Verder zijn er plugins voor zowel Maven en Gradle. Ontwikkel je in Spring Framework? Ook daarin kan je perfect met Kotlin uit de voeten.

Lees er meer over op https://kotlinlang.org/. Voor een volledig overzicht van alle features: https://kotlinlang.org/docs/reference/.