Kotlin Multiplattform-Projekte für die Web-Entwicklung

Kotlin Multiplatform says that it will take care of the business logic and we just need to take care of the UI.

Laut GitHub war Kotlin die am schnellsten wachsende Programmiersprache des Jahres 2018, was die Verwendung in GitHub-Repositorien betrifft. Die Kotlin-Multiplattformfunktion ist seit Version 1.2, die Ende 2017 veröffentlicht wurde, Teil der Kotlin-Programmiersprache. Der Kotlin-Compiler bietet Unterstützung für die Kompilierung von Code in ein natives Zielformat. Folglich können Kotlin-Anwendungen in Umgebungen ausgeführt werden, die virtuelle Maschinen zum Ausführen von Anwendungen nicht unterstützen, z. B. Apple Smartphones mit iOS. Die unterstützten Plattformen für native Anwendungen sind Android NDK, iOS, Linux, MacOS, Windows und WebAssembly. Kotlin bietet auch Unterstützung für die Kompilierung nach Javascript.

Ein Kotlin-Multiplattform-Projekt besteht aus den Bausteinen Targets, Kompilierungen und Quellensätze. Ein Target ist der Teil des Projekts, der für die Erstellung, das Testen und die Paketierung der Anwendung für eine bestimmte Plattform verantwortlich ist. In einem Multiplattform-Projekt gibt es in der Regel mehr als ein Ziel, da solche Projekte auf mehr als eine Plattform abzielen. Eine Kompilierung ist, wie der Name schon sagt, die Kompilierung des Kotlin-Quellcodes. Ein Target hat mindestens eine Kompilierung, kann aber auch mehrere haben, z.B. eine Kompilierung für die Produktion, eine für das Testen usw. Die Quelldateien werden zusammen mit den zugehörigen Ressourcendateien, Abhängigkeiten und Spracheinstellungen in Quellmengen gruppiert. Die Quellensätze sind plattformunabhängig, was bedeutet, dass der Quellensatz nicht zwangsläufig für eine Plattform spezifisch ist. Es muss jedoch auch nicht der gesamte Quellensatz gemeinsam genutzt werden. Stattdessen können einige Teile des Quellensatzes von verschiedenen Plattformen gemeinsam genutzt werden, und einige, die nur für eine Plattform kompiliert werden sollen, können plattformspezifische Abhängigkeiten enthalten. Ein Quellcode-Satz kann gemeinsame Abhängigkeiten haben, d.h. Bibliotheken oder andere Projekte, auf die der Quellcode-Satz explizit Zugriff benötigt. Zusammenfassend lässt sich sagen, dass Kotlin Multiplattform eine Möglichkeit ist, Code zwischen verschiedenen Plattformen auszutauschen.

Lass uns einen Moment darüber nachdenken, was passiert, wenn wir eine Kotlin-Anwendung kompilieren. Der Kotlin-Compiler (kotlinc) nimmt Dateien mit der Erweiterung *.kt als Eingabe und generiert Bytecode als *.class Dateien. An diesem Punkt kann die JVM die *.class-Dateien ausführen.

Wenn man jedoch Kotlin-Anwendungen ausführt, benötigt man neben der JRE auch die Kotlin-Laufzeitbibliothek. Der Kotlin-Compiler kompiliert also *.kt-Dateien in *.class-Dateien, die Bytecode enthalten. Die *.class-Dateien können von der JVM geladen werden, genau wie aus Java-Code generierte Klassendateien. Wenn man eine Kotlin-Anwendung verteilen will, muss man die Kotlin-Laufzeitbibliothek und das JRE verteilen, sonst wird die Anwendung nicht ausgeführt.

Erstelltung eines Projektes

Lass uns einsteigen und ein Kotlin-Multiplattformprojekt in IntelliJ erstellen. Man muss sicherstellen, dass man die neueste Version des Kotlin-Plugins installiert hat. Man wählt File | New | Project…, danach wählt man Kotlin | Kotlin (Multiplatform Library) und dann konfiguriert man das Projekt:

Eine Multiplattform-Beispielbibliothek wird jetzt erstellt und in IntelliJ IDEA importiert. Die Projektstruktur sollte folgende sein:

Gradle Build (Grundlagen)

Kotlin Multiplattformprojekte erfordern Gradle Version 4.7 oder höher, ältere Gradle-Versionen werden nicht unterstützt.

Nach Auswahl eines Projektnamens beginnt IntelliJ IDEA automatisch mit der Erstellung der Ordnerstruktur für das Gradle-Projekt. Um die Standard-Build-Konfiguration zu sehen und anzupassen, können wir die build.gradle Datei unserer Anwendung öffnen:

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
}
repositories {
    mavenCentral()
}
group 'com.example'
version '0.0.1'

apply plugin: 'maven-publish'

kotlin {
    jvm()
    js {
        browser {
        }
        nodejs {
        }
    }

    // For Windows, should be changed to e.g. mingwX64
    mingwX64("mingw")
    sourceSets {
        commonMain {
            dependencies {
                implementation kotlin('stdlib-common')
            }
        }
        commonTest {
            dependencies {
                implementation kotlin('test-common')
                implementation kotlin('test-annotations-common')
            }
        }
        jvmMain {
            dependencies {
                implementation kotlin('stdlib-jdk8')
            }
        }
        jvmTest {
            dependencies {
                implementation kotlin('test')
                implementation kotlin('test-junit')
            }
        }
        jsMain {
            dependencies {
                implementation kotlin('stdlib-js')
            }
        }
        jsTest {
            dependencies {
                implementation kotlin('test-js')
            }
        }
        mingwMain {
        }
        mingwTest {
        }
    }
}

Wie wir sehen können, wird das Gradle-Plugin kotlin.js verwendet, um JavaScript-Unterstützung für unser Projekt bereitzustellen. Das Plugin kümmert sich auch um die Verwaltung einer Entwicklungsumgebung für uns. Die drei Ziele werden mit den voreingestellten Funktionen jvm(), js() und mingwX64() erstellt, die eine gewisse Standardkonfiguration bieten. Es gibt Voreinstellungen für jede der unterstützten Plattformen.
Abhängig von der Zielplattform werden unterschiedliche Funktionen, z.B. macosX64, mingwX64, linuxX64, iosX64, verwendet, um das Kotlin-Target zu erstellen. Der Funktionsname ist die Plattform, für die wir unseren Code kompilieren. Diese Funktionen nehmen optional den Zielnamen als Parameter, der in unserem Fall “nativ” ist. Der angegebene Zielname wird verwendet, um die Quellpfade und Tasknamen im Projekt zu generieren.

Erstellen der Hauptfunktion

Wir erstellen eine neue Kotlin-Datei mit dem Namen Main.kt im Verzeichnis src und fügen ihr die Funktion main() wie unten gezeigt hinzu:

fun main(args: Array<String>) {
  println("Hello world!")
}

Dies ist die Hauptfunktion, die in jeder Kotlin-Anwendung obligatorisch ist. Der Kotlin-Compiler beginnt mit der Ausführung des Codes von der Hauptfunktion aus.
Die main()-Funktion der Anwendung kann sich in jeder Kotlin-Datei mit beliebigem Namen befinden, daher ist die Verwendung von Main.kt als Dateiname hier nicht unbedingt erforderlich, aber man soll nur eine main()-Funktion im Projekt haben.
Die Funktion nimmt ein Array von Zeichenketten als Parameter und gibt Unit zurück.

Plattformspezifische Erklärungen (actualexpect)

Die plattformspezifischen Implementierungen arbeiten mit den expect und actual Schlüsselwörtern. Mit expect fügt man class/property/etc-Deklarationen zu dem gemeinsamen Modul hinzu. Im folgenden Beispiel habe ich ein Plattformobjekt definiert, das für jede Zielplattform definiert werden muss:

expect object Platform {
    val name: String
}

Wir können das Schlüsselwort expect verwenden, um zu erklären, dass eine Methode auf jeder Plattform separat implementiert wird, auch indem wir sie wie eine reguläre Kotlin-Funktion aufrufen:

expect fun logMessage(msg: String)

Durch die Verwendung des actual Schlüsselwortes definiert man die eigentliche plattformspezifische Implementierung der erwarteten Deklaration. Damit unsere Anwendung kompiliert werden kann, müssen wir also für jede Plattform eine separate Implementierung bereitstellen. Diese verwenden das actual Schlüsselwort und handhaben die Nachricht in geeigneter Weise, indem sie Kotlin-Bindungen plattformspezifischer APIs verwenden:

actual object Platform {
    actual val name: String = "JVM"
}

//JVM
actual fun logMessage(msg: String) {
    println(msg)  //print the message to System.out
}

In diesem Beispiel haben wir die actual Deklaration des Plattformobjekts für JVM und die Nachricht der Protokollfunktion definiert.

Dies ermöglicht es dem Entwickler, alle notwendigen plattformspezifischen Abhängigkeiten oder technischen Anforderungen zu berücksichtigen. Während expect/actual einen sprachspezifischen Mechanismus für diese Art der Multiplattform-Entwicklung bereitstellen, ist es auch weiterhin möglich, einfach eine gemeinsame Schnittstelle zu definieren und diese Schnittstelle auch für jedes Build-Ziel zu implementieren.

Was sind die Nachteile?

Kotlin Multiplattform ist eine experimentelle Sprachfunktion und die Dokumentation für Kotlin Multiplattform kann manchmal ein wenig unvollständig sein. Da es sich um eine experimentelle Technologie handelt, ist das zu erwarten. Die Dokumentation und Beispielanwendungen werden sich wahrscheinlich verbessern, sobald Multiplattform stabil wird. Ein weiterer Aspekt ist eine Multiplattformlösung für Daten. Derzeit gibt es mehrere Implementierungen von Drittanbietern für die Unterstützung von Datum/Uhrzeit, aber das JetBrains-Team arbeitet an einer First-Party-Lösung dafür.

Schlussfolgerung

Mit dem Kotlin Multiplattform-Ansatz kann man Code in einer modernen Hochsprache austauschen, ohne die gesamte API der Zielplattformen abdecken zu müssen. Kotlin Multiplattform zielt darauf ab, die Codefreigabe zu vereinfachen, indem es dem Entwickler überlassen wird, wie viel Code freigegeben werden muss.

Möchte man nur einen bestimmten, zentralen Algorithmus teilen? Dann ist das in Ordnung. Man kann ein Kotlin-Multiplattformprojekt erstellen, das eine einzelne Funktion oder den Großteil der Logik, Modelle usw. der Anwendung enthält.

Da Kotlin Multiplattform-Projekte nicht darauf abzielen, eine komplette plattformübergreifende Anwendung zu erstellen, wird der freigegebene Code wie jede andere Bibliothek oder jedes andere Modul verwendet. Das macht es zu einer einfachen Aufgabe, dieses Modul gegen ein anderes auszutauschen, wenn es den Anforderungen nicht entspricht.
Diese Flexibilität ermöglicht es Teams, Kotlin Multiplattform zu integrieren, ohne sich an einen neuen Tech-Stack für ihre gesamte Anwendung zu ketten. Dies senkt die Einstiegshürde für das Ausprobieren dieser Methode des Code-Sharings und für die Entscheidung, ob sie für das Projekt oder Team praktikabel ist.

Insgesamt denke ich, dass Kotlin Multiplattform ein großes Potenzial für die gemeinsame Nutzung von Datenklassen und Business-Logik hat.

Views All Time
526
Views Today
1
Short URL for this post: https://blog.oio.de/B7x21
This entry was posted in Other languages for the Java VM, Web as a Platform and tagged , . Bookmark the permalink.

1 Response to Kotlin Multiplattform-Projekte für die Web-Entwicklung

  1. Pingback: Spring Boot mit Kotlin | techscouting through the java news

Leave a Reply

Your email address will not be published. Required fields are marked *