)
White paper
Native apps voor de prijs van een cross-platform-oplossing: Kotlin Multiplatform
Jarenlang hadden mobile developers twee opties om hun apps tot bij de gebruiker te krijgen: native of cross-platform. Beide hebben hun eigen voordelen en uitdagingen, en de uiteindelijke keuze hangt vooral af van de specifieke vereisten en beschikbare resources van een project. Kotlin Multiplatform voegt hier nu een derde optie aan toe, door het beste van native en cross-platform te combineren, zónder de nadelen.
Native vs. cross-platform: perfectie bestaat niet
Laten we eens kijken wat native en cross-platform-stacks precies te bieden hebben. Hoewel de impact van hun voor- en nadelen per project anders is, zetten we de belangrijkste verschillen op een rij.
Een van de meest genoemde voordelen van native apps is hun performance. Native apps communiceren namelijk rechtstreeks met het besturingssysteem. Dat leidt tot vloeiendere animaties, betere gameprestaties en minder batterijverbruik.
Bij cross-platform-oplossingen werkt het net iets anders. React Native gebruikt bijvoorbeeld een vertaallaag om abstracte JavaScript-code (die van nature wat trager is) op elk platform te draaien. Flutter daarentegen is een volledig gecompileerde app geschreven in Dart, waardoor hij qua performance dicht in de buurt komt van native apps.
Sommige functionaliteiten zijn alleen mogelijk in native code omdat ze directe toegang tot de hardware van het toestel vereisen. Denk bijvoorbeeld aan NFC, Bluetooth of bepaalde vormen van videoweergave.
Cross-platform-frameworks bieden vaak wrappers aan voor de meest gebruikte systeemfuncties, maar lopen regelmatig tegen beperkingen aan of moeten omwegen gebruiken.
Native apps daarentegen kunnen volledig gebruikmaken van alle systeemeigenschappen omdat ze rechtstreeks werken met software die door Google of Apple zelf is ontwikkeld.
Native apps voelen vertrouwd aan op het platform waarvoor ze gebouwd zijn, omdat ze gebruikmaken van de UX- en UI-patronen die gebruikers gewend zijn. Wanneer je cross-platform-apps ontwikkelt daarentegen, is het soms bijna onmogelijk om een app te bouwen die op élk platform goed aanvoelt. Gebruikers ervaren apps die niet goed zijn afgestemd op hun toestel vaak als minder van kwaliteit in vergelijking met native apps.
Eén ding is zeker: het vraagt meer werk om twee aparte apps te bouwen dan één app die overal werkt. En precies hier blinken cross-platform-apps in uit. Ze zijn vaak de meest kostenefficiënte manier om je app beschikbaar te maken op alle gangbare platformen.
Een gedeelde codebase maakt het onderhoud van een app een stuk eenvoudiger. De app ziet er overal hetzelfde uit en gedraagt zich op elk platform hetzelfde. Bugs komen vaak op alle platformen tegelijk voor en kunnen in één keer worden opgelost. Dat is efficiënter dan per platform apart problemen te moeten analyseren, oplossen en opnieuw uitrollen.
Voor sommige apps is beveiliging cruciaal. Denk bijvoorbeeld aan bankapps en medische toepassingen — onze specialiteit. Het verschil zit hierbij vooral in de manier waarop de app functioneert. Cross-platform-apps maken gebruik van een extra tussenlaag, geleverd door de cross-platform-stack. En hoe meer software, hoe groter de kans op beveiligingslekken of kwetsbaarheden.
Zoals je ziet hebben native en cross-platform-apps allebei hun voor- en nadelen. Maar wat als je een vlotte, snelle app wilt, met alle functionaliteiten en zónder het hoge prijskaartje?
Kotlin Multiplatform: het beste van twee werelden
Enter Kotlin Multiplatform (KMP): al meer dan vijf jaar de native taal voor Android die standaard gebruikt wordt onder Android-developers. De afgelopen jaren heeft JetBrains, de maker van Kotlin, het bereik van de taal steeds verder uitgebreid door ondersteuning toe te voegen voor meer platformen.
Naast Android maakt Kotlin/Native het mogelijk om Kotlincode te compileren naar native code voor iOS, macOS, Linux en Windows. Met Kotlin/JS en Kotlin/WASM kan Kotlin ook gebruikt worden voor webontwikkeling.
Al deze mogelijkheden komen samen in Kotlin Multiplatform (KMP). KMP maakt het mogelijk om één gedeelde codebase te gebruiken voor meerdere doelplatformen. Deze gedeelde code kan geïmporteerd worden als dependency in native projecten voor iOS, Android en andere platformen zoals web, en kan alle niet-zichtbare delen van een app bevatten. Denk aan netwerkcommunicatie, caching, businesslogica, ... die hergebruikt kunnen worden in al je apps.
Het enige wat je nog moet doen is een native UI toevoegen aan de apps, wat dankzij moderne UI-frameworks zoals Jetpack Compose en SwiftUI makkelijker is dan ooit. Sterker nog: binnenkort zal het zelfs mogelijk zijn om ook UI-elementen te delen met Compose Multiplatform.
Op basis van meerdere succesvolle apps die we lanceerden voor onze klanten, kunnen we stellen dat vrijwel alle code die niet direct met de gebruikersinterface te maken heeft, gedeeld kan worden zonder af te doen aan de voordelen van native development. De prestaties van KMP liggen op native niveau omdat Kotlincode gecompileerd wordt naar native code. Alles wat de gebruiker ziet en aanraakt is 100% native. Dat zorgt voor een authentieke gebruikerservaring, gecombineerd met alle voordelen van cross-platform-oplossingen voor zowel ons developmentproces als de klant.
Er is bovendien een waaier aan KMP-libraries beschikbaar die development versnellen, en het aantal community libraries groeit continu. KMP heeft ook geen moeite met native platformfunctionaliteiten. Kotlincode kan alle native functies aanroepen die een besturingssysteem voorziet.
Kort samengevat biedt KMP het beste van twee werelden: de prestaties en look-and-feel van native apps, met de efficiëntie van gedeelde code. Omdat alleen de UI nog per platform ontwikkeld moet worden, levert dit een aanzienlijke besparing op qua werk en onderhoud. En hoewel we in dit artikel vooral focussen op Android en iOS, ondersteunt Kotlin Multiplatform ook native apps voor macOS, Java-gebaseerde Windowsprogramma’s en webapplicaties.
Een unieke eigenschap van KMP is dat het bestaande native apps kan omvormen tot een gedeeld cross-platform-project, ook als ze al lang bestaan. Een goed onderhouden Android-codebase kan als basis dienen voor een gedeeld KMP-project, waarbij Android-functionaliteit wordt geëxtraheerd naar een gedeelde codebase.
Wij hebben met succes ons grootste app-project gemigreerd van twee native apps naar één KMP-app met een grote gedeelde codebase. Daarbij werd meer dan 40% van de iOS-code verwijderd, terwijl we toekomstige ontwikkelingen juist konden versnellen. Veel nieuwe functies of aanpassingen verschijnen nu "vanzelf" op iOS zodra de KMP-dependency wordt geüpdatet. Omdat native teams doorgaans al ervaring hebben met KMP-code, kan deze overstap geleidelijk gebeuren zonder het lopende developmentwerk te verstoren.
Maar wat als we de muren tussen platforms willen weghalen en (stukken van) onze UI willen delen? Dat is wat Compose Multiplatform belooft, zodra het beschikbaar is voor alle platforms. Net zoals bij Flutter kan je één gedeelde UI schrijven voor alle platforms, gebaseerd op wat Android-gebruikers al kennen. De API’s die worden aangeboden in Compose Multiplatform zijn bijna identiek aan Android’s native UI-framework Jetpack Compose.
Hoewel je de voordelen van een native UI op iOS verliest wanneer je gebruik maakt van Compose Multiplatform, zullen Android-gebruikers geen verschil zien. Maar het delen van je UI is geen zwart-wit beslissing. Veel elementen in de UI zijn identiek tussen platforms. Cellen of lijstitems moeten er bijvoorbeeld vaak hetzelfde uitzien. In plaats van de gehele UI te delen, kun je ook kleinere elementen in de UI delen en ze embedden in de native UI van je app. Wanneer dat goed gedaan wordt zal de gebruiker geen verschil merken, maar jij hebt het bereik van je gedeelde codebase nog verder uitgebreid.
Compose Multiplatform is momenteel nog in beta voor iOS en alpha voor web, maar je kan het al gebruiken voor Android- en desktoptapps.
Samenvatting
Kotlin Multiplatform combineert de voordelen van native en cross-platform-development. In plaats van te moeten kiezen tussen de twee, bepaal je zelf hoeveel gedeelde code je in je project wilt gebruiken en hoeveel je platform-specifiek houdt. Die flexibiliteit maakt van KMP in veel gevallen dé ideale oplossing. Voorlopig blijft de UI volledig native, maar in de toekomst zal je er ook voor kunnen kiezen om stukken (of zelfs de volledige interface) te delen tussen platforms.