Das Entwicklertagebuch Kennzeichner #3: Shared Core – der Kern des Ganzen
Nun geht es endlich los. Wir starten mit der Entwicklung der App. Diese ist vorerst in drei PoCs – also Proof of Concepts – aufgeteilt. Als Erstes steht der sogenannte Shared Core an. Also das Modul, was in Zukunft zwischen den beiden Apps geteilt werden soll. Nachfolgend wird die Android-App entwickelt und zu guter Letzt folgt iOS.
Für alle, denen diese Artikelreihe noch unbekannt ist – das habt ihr bislang verpasst, könnt euch aber natürlich nachträglich einlesen:
- Entwicklertagebuch #1: mit Bing AI Chat als Datengrundlage
- Entwicklertagebuch #2: Excel kann Geografie und mag kein Berlin
- (aktuell) Entwicklertagebuch #3: Shared Core – Der Kern des Ganzen
Begriffserklärung
Ständig fallen Begriffe und Abkürzungen während der Tagebucheinträge, welche schnell zu einem Wirrwarr im Lernprozess des neuen Technologiestacks werden können. Dies alles haargenau zu erklären, fällt auch mir noch schwer, doch generell kann man KMM in drei Teilgebiete unterteilen. Für etwaige Berichtigungen stehen die Kommentare des Artikels offen.
Kotlin
… ist eine plattformunabhängige und quelloffene Programmiersprache aus dem Hause JetBrains, welche ähnlich wie Java in Bytecode für die JVM (Java Virtual Machine) übersetzt wird. Andere Sprachen für die JVM wären beispielsweise Groovy oder Scala. Sie ist de facto die Sprache, in der unter anderem moderne Android-Apps entwickelt werden. Kotlin zu Java lässt sich im gleichen Verhältnis sehen wie Swift zu Objective C.
KMM
… steht für Kotlin Mobile Multiplatform und bedeutet, dass man einen gemeinsamen Kern der Apps entwickelt, welche auf verschiedene Betriebssystemen wie Android oder iOS laufen. Im Laufe der Artikelreihe werde ich die verschiedenen Bestandteile eines KMM-Projektes als „:shared“ für den Kern, „:android“ und „:ios“ für die jeweiligen nativen Apps bezeichnen.
In der Strukturierung von KMM-Architekturen gibt es keine harte Grenze, ab wann es plattformspezifischer Code wird und ab wann nicht. Um unseren Einstieg in KMM einfach zu halten, machen wir den Schnitt bei der “Datenbeschaffung” und alles darüber wird je App entwickelt. So lehnen wir uns am zweiten Diagramm im unteren Schaubild an.
Durch CMP (Compose Multiplatform) könnte sogar die Oberfläche geteilt werden. Dieser spannende Ansatz hat erst die “Experimental”-Phase verlassen und ist zum Zeitpunkt des Artikels in einem Alpha-Status. Hierdurch wäre es dann auch möglich, Webseiten mittels Compose zu bauen. Ein Feature, welches ich bei .NET MAUI schmerzlich vermisse.
Ktor
… diese von JetBrains gepflegten und in Kotlin entwickelte Bibliothek ermöglicht es, moderne, leichtgewichtige und vor allem plattformunabhängige http-Server und -Clients zu entwickeln. Für den Kennzeichner verwenden wir neben der Client Seite des Frameworks auch dessen Funktionen rund um JSON-Deseralisierung und Mapping.
Gradle
… ist das Standard Build-Management-Tooling hinter modernen Kotlin Apps. Es ist nicht nur Abhängigkeitsverwaltung, sondern kann auch mit den verschiedensten Tasks die unterschiedlichsten Aufgaben während der Entwicklung von JVM-basierenden Apps übernehmen. Die naheliegenden Tasks wären das Bauen der eigentlichen Applikation, das Einbetten des geteilten Kerns oder auch das Signieren, um eine Unberührtheit der erstellten Datei zu gewährleisten. Ein zentraler Startpunkt, um zu verstehen, welche Abhängigkeiten oder Features seitens Gradle aktiviert sind, ist die jeweilige Modul-Datei build.gradle.kts.
Zusammenfassung
Somit wird unsere App Kennzeichner eine in Kotlin geschriebene KMM-Applikation, welche Webrequests durch Ktor absetzt und verarbeitet. Als Build Chain Tooling wird Gradle verwendet.
Begriffe, welche im späteren Verlauf unsere Bastelei verwendet werden, erkläre ich in den folgenden Beiträgen dieser Serie.
Der Kern des Ganzen
Den Grundpfeiler bildet das Modul „shared“, jenes enthält neben der Datenbeschaffung auch dessen Aufarbeitung und das State-Management hierzu. Dies wiederum wird anschließend von den einzelnen Apps eingebunden. Somit haben wir die Logik nur einmal zu schreiben. Dies hilft auch dabei, dass sich beide Apps gleich verhalten und keine Unterschiede in der Datenverwaltung haben.
Datenbeschaffung
Im letzten Beitrag haben wir die JSON-Datei erstellt und auf einer GitHub Page abgelegt, um diese nun innerhalb unseres Repositories (LicensePlateRepository.kt) abgreifen zu können. Ein pures Ablegen im Git und Einbinden via GitHub-Link schlägt fehl, da hier keine entsprechenden Http-Header gesetzt werden und die App es hierdurch nicht verwenden könnte.
Hierbei müssen wir das Rad nicht neu erfinden und können auf bewährte Frameworks aus dem Kotlin-Ökosystem zurückgreifen. Einerseits ist es das „Ktor“-Framework, welches sich um die gesamte Netzwerkkommunikation bis zum Validieren der empfangenen Datenströme kümmert. Andererseits finden auch die Coroutinen von KotlinX (Kotlin eXtensions) den Einsatz in der Kennzeichner App.
Wie ihr seht, ist der Programmcode bisher nur auf den Happy Path ausgelegt und es fehlt noch jegliche Fehler-Handhabung im Falle eines Server-Problems oder eines clientseitigen Vorfalles, etwa wenn der Nutzer keine Verbindung zum Internet hat.
Die Liste der Dependencies wird wohl im Laufe der Entwicklung stetig anwachsen. Dennoch versuche ich es hier auf das Mindeste zu reduzieren und wenn wirklich nötig, dann auf namhafte Vertreter der jeweiligen Bibliotheken zurückzugreifen.
Ein gutes Learning war, dass für Multiplatform mehrere http-Engines benötigt werden, da keine davon beispielsweise iOS und Android simultan unterstützt. Dies habe ich durch eine expect/actual Implementierung der HttpClient-Factory gelöst. Unter iOS kommt die „Darwin“ Engine zum Einsatz und Android verwendet „CIO“.
Datenaufbereitung
Da ich bewusst die DTO (Data-Transfer-Objects), also die Daten, welche der Server sendet, dumm gehalten habe, ist ein Aufbereitungsschritt zwischengeschaltet. In diesem sogenannten Mapping von DTOs auf DMs (Domain Model) werden Daten gruppiert, validiert und entsprechend dem Verwendungszweck auch zwischen Typen konvertiert.
Dies alles dient dem Gedanken, den Apps das Darstellen der Daten so bequem wie möglich zu gestalten und nicht noch extra Arbeit bezüglich Datenhygiene aufzubürden. Bei der Entwicklung für Multiplatform-Apps, welche native Oberflächensubprojekte haben, ist es wichtig, dass sich Android- und iOS-Entwickler bei der Verwendung der geteilten Komponente wohl und zuhause fühlen. Hierfür wird es in Zukunft noch extra Sprints geben, welche sich darauf fokussieren.
Daten State-Management
Im ersten Schritt ist dies sehr rudimentär umgesetzt. Das Repository im shared-Modul beinhaltet eine Liste an bereits geladenen und aufbereiteten Datenobjekten. Da sich die Daten nicht wirklich ändern, wird vorerst in einfacher Weise geprüft, ob die Liste leer ist. Falls ja, lade Daten, ansonsten sollen die bereits vorhandenen Datensätze verwendet werden. Falls in Zukunft die API mehr Dynamik entwickeln sollte, muss diese Logik beispielsweise um einen „zuletzt aktualisiert“-Hinweis erweitert werden.
Ein Feature der App ist das Filtern geladener Daten. Dies findet ebenso innerhalb des geteilten Repository statt. Hier ist in Zukunft damit zu rechnen, dass man von einfachen Listen auf Flows, Datenströme, wechselt, um an verschiedenen Stellen auf Filterungen, Sortierungen oder anderweitiger Gründe, wieso die darzustellenden Kennzeichen sich ändern, zu hören.
Kommende Schritte
Im nächsten Schritt wird die erste Version, der Proof of Concept, beider nativer Apps entwickelt, welche das nun erstellte Shared-Core einbinden sollen. Sind auch diese beiden Meilensteine vom Kennzeichner genommen, geht es an das Polieren, an die Dokumentation und die schönen Kleinigkeiten, welche die App haben sollen. Hierunter fallen beispielsweise für Android die Unterstützung des Surface Duo oder generell die Einbindung von Sprachassistenten, um Kennzeichen allein durch die Stimme finden zu können.
Bei offenen Fragen rund um das Mitwirken an der App mailt mir an tobias@drwindows.de oder erstellt gleich ein Issue auf GitHub, wo der komplette Quelltext der App liegt.
Lasst uns weiterhin gemeinsam dieses spannende Bastelprojekt weiterführen. Vielen Dank für euer stetes Interesse an diesen Nerdigkeiten.
Themen:
- Entwicklung
- News
Über den Autor
Tobias Scholze
Bayrischer Open Source- und Community-Enthusiast, Verfechter des neuen Microsoft und Wandler zwischen den Betriebssystemwelten. #communityrocks Von Herzen ein Nerd mit der festen Überzeugung, dass man gemeinsam und durch den Einsatz von moderner IT die Welt für jeden ein Stückchen besser machen kann.