Multiplattform-Entwicklung fĂŒr Android und Web? Kotlin macht‘s möglich!

Seite 2: KMPs Modulstruktur und expect/actual-FunktionalitÀt

Inhaltsverzeichnis

Das HerzstĂŒck jeder KMP-Anwendung ist das Common-Modul. Es beherbergt den Code, der plattformĂŒbergreifend verwendet wird – beispielsweise Datenmodelle, Netzwerklogik, ViewModels und Use Cases (Abbildung 2).

Beispielhaftes Architekturdiagramm einer KMP-Anwendung fĂŒr Android und Web (Abb. 2)

Innerhalb des Common-Moduls befinden sich Unterordner. commonMain enthĂ€lt die Definition plattformunabhĂ€ngigem Codes. Um plattformspezifische Anpassungen vorzunehmen, ohne die gemeinsame Logik zu beeintrĂ€chtigen, sind zwei weitere Unterordner vorgesehen: jsMain fĂŒr das Web und androidMain fĂŒr Android.

Diese Struktur ermöglicht den Einsatz der expect/actual-FunktionalitĂ€t (Abbildung 3). Das bedeutet, dass Entwicklerinnen und Entwickler in commonMain generelle Erwartungen (expects) bezĂŒglich des Verhaltens setzen, und in den spezifischen Ordnern (jsMain und androidMain) wird dann die tatsĂ€chliche (actual) Umsetzung dieser Erwartungen vorgenommen. Man kann sich das vorstellen wie ein Interface, das sich implementieren lĂ€sst.

Expect-/actual-Mechanismus zur Nutzung des lokalen Speichers (Abb. 3)

Ein praxisnahes Beispiel ist das Speichern von Daten. WĂ€hrend Key-Value-Paare im Web oft in localStorage des Browsers zu finden sind, kommen dafĂŒr in Android die SharedPreferences zum Einsatz. Kein Grund, die gesamte Logik zum Ablegen dieser Daten separat zu implementieren. commonMain enthĂ€lt die Definition einer expect-Klasse oder -Funktion und der Compiler erwartet die entsprechende actual-Implementierung in androidMain und jsMain.

Beim AusfĂŒhren der Anwendung wird dann zur Laufzeit ermittelt, welches Verhalten fĂŒr die jeweilige Plattform gelten soll.

ZusĂ€tzlich zum Common-Modul gibt es die plattformspezifischen Module androidApp und webApp. Darin implementiert man alles, was tatsĂ€chlich nur fĂŒr die jeweilige Plattform nötig ist, wie das Frontend und die Navigationslogik.

Code zu teilen, verringert den Wartungsaufwand und reduziert Entwicklungskosten. Diese Hoffnung erfĂŒllt sich spĂ€testens dann nicht, wenn das Multiplattform-Framework spezielle plattformspezifische APIs nicht unterstĂŒtzt. KMP bringt mit seinem flexiblen Ansatz frischen Wind in die Betrachtung. Entwicklerinnen und Entwickler können projektspezifisch entscheiden, welche Elemente des Codes sie teilen möchten. Das ist besonders praktisch, wenn sich die Zielplattformen so gravierend unterscheiden wie Android und Web.

Das wachsende Ökosystem und die begeisterte Community um KMP ermöglichen es, dass sich trotz der großen Unterschiede viele Komponenten und Funktionen teilen lassen. Denn die meisten plattformspezifischen Probleme lassen sich mit geeigneten Bibliotheken lösen.

Beim plattformĂŒbergreifenden Implementieren der Netzwerklogik kann JetBrains' quelloffene Kotlin-Bibliothek Ktor helfen. Eine plattformunabhĂ€ngige lokale Datenbank zu implementieren, stellt dank SQLDelight keine HĂŒrde dar. Dependency Injection fĂŒr Android und Web? Kodein (Kotlin Dependency Injection) macht’s möglich! Und selbst die Android-Entwicklern vertrauten ViewModels lassen sich dank kmp-viewmodel plattformĂŒbergreifend nutzen.

FĂŒr all die, die jetzt die Nase rĂŒmpfen, bei dem Gedanken Model-View-ViewModel (MVVM) im Web zu nutzen, gibt es natĂŒrlich auch andere Möglichkeiten, wie Model-View-Intent (MVI).

Sich zu sehr auf verschiedene, mitunter kleine Bibliotheken zu verlassen, birgt natĂŒrlich auch Risiken, wie Wartungsunsicherheit, KompatibilitĂ€tsprobleme und potenzielle SicherheitslĂŒcken. Hier bedarf es sinnvollen AbwĂ€gens, wann eine Bibliothek und wann lieber das expect/actual-Konzept zum Einsatz kommen sollte. Außerdem ist es ratsam, die ZukunftsfĂ€higkeit der genutzten Bibliotheken im Blick zu behalten. Sonst kommt es im Projektverlauf möglicherweise zu bösen Überraschungen, wenn man eine weitere Plattform ergĂ€nzen möchte.