Verwenden von Kotlin für die Back-End-Entwicklung: Ein kurzer Überblick

Veröffentlicht: 2022-03-11

Ich muss Kotlin nativen Android-Entwicklern nicht vorstellen, da Google im Mai 2017 angekündigt hat, dass es die offizielle Sprache für die Android-Entwicklung sein wird. Seitdem hat es als primäre Sprachwahl für die Entwicklung neuer und glänzender Android-Apps viel Anklang gefunden. Es löst viele Schwachstellen von Java, sodass die neuen Apps hauptsächlich darin geschrieben werden und die alten darin neu geschrieben werden.

Es besteht kein Zweifel, dass es auf der Front-End-Seite von Anwendungen großartig ist, und wenn Sie Kotlin zum ersten Mal erwähnen, assoziieren die meisten Leute es mit dem Android-Betriebssystem. In diesem Artikel möchte ich jedoch über Kotlin als Backend-Sprache sprechen und ich möchte meine Geschichte über die Erstellung eines schnellen, zuverlässigen und asynchronen Kotlin-Backends für mein Android-Hobbyprojekt teilen. Ich werde nicht diskutieren, worum es bei dem Projekt geht, da es den Rahmen dieses Artikels sprengen würde; Stattdessen werde ich mich darauf konzentrieren, zu erklären, warum ich mich für Kotlin entschieden habe und warum ich denke, dass es eine großartige Sprache zum Schreiben serverseitiger Anwendungen oder REST-APIs ist.

Warum Kotlin?

Lassen Sie mich zum Anfang meiner Reise zurückkehren. Ich hatte schon immer unternehmerische Ambitionen und dachte, dass der erste Schritt auf diesem Weg darin besteht, etwas Eigenes zu schaffen. Nichts Großes, nichts Weltveränderndes, nur etwas Kleines, das ich und vielleicht meine Familie und Freunde nutzen können. Nachdem ich eine vernünftige Idee hatte, sprang ich direkt hinein und begann mit der Umsetzung. Das erste, was Sie zu Beginn eines jeden Projekts tun, ist die Auswahl Ihrer Werkzeuge. Denn mit dem richtigen Werkzeugset können Sie langfristig viel Zeit und Geld sparen. Das habe ich also getan.

Ich bin hauptsächlich ein Java-Entwickler. Ich habe mehrere Back-End-Systeme und REST-APIs mit Java und Spring geschrieben, und ich denke, dass diese beiden großartige Tools sind, um solche Dinge zu tun. Java allein ist eine umfassende Sprache, aber in Kombination mit Spring gibt es nichts, was Sie nicht implementieren könnten.

Es gibt jedoch nur ein winziges Haar in der Suppe. Ausführlichkeit. Obwohl Spring und die neuesten Java-Versionen dabei sehr hilfreich sind, müssen Sie dennoch mit einer Menge Boilerplate-Code umgehen. Und wie mir einmal ein toller Kerl gesagt hat – der sicherste, zuverlässigste und fehlerfreiste Code ist der Code, der nicht aufgeschrieben wird. Nehmen Sie zum Beispiel diese triviale Java-Klasse:

 public class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }

Meiner Meinung nach ist dies eine Menge Code, um einfach zu sagen: „Ich möchte eine Klasse mit zwei schreibgeschützten Feldern.“ Das Schlimmste ist, dass der Konstruktor und die Methoden automatisch generiert wurden. Wenn Sie eine Pull-Anforderung überprüfen, gehen Sie sie dennoch immer durch, weil Sie nie wissen, ob sie das sind, was Sie brauchen oder nicht. Sicher, dies kann mit Bibliotheken von Drittanbietern wie Lombok verkürzt werden, aber wäre es nicht schön, wenn wir dies sofort tun könnten? Sehen wir uns genau dieselbe Klasse in Kotlin an:

 class Person( val name: String, val age: Int )

Es ist definitiv kürzer und einfacher. Die Variablen sind endgültig, da wir das Schlüsselwort val verwenden; Der Konstruktor und die Getter werden zur Kompilierzeit generiert. Wenn wir es vorziehen, kein unveränderliches Personenobjekt zu haben, können wir einfach val in var ändern, und voila, wir haben eine veränderliche Person, und alles, was wir tun müssen, ist nur einen Buchstaben zu ändern.

Mein zweitliebster Teil in einer einfachen Java-POJO-Klasse ist das überschriebene equals() und hashCode() . Auch diese werden meistens automatisch generiert, aber man muss sie immer wieder durchgehen, nur um sicherzugehen. Die gute Nachricht ist, dass Kotlin auch damit umgehen kann. Ändern Sie einfach Ihre class in eine data class und Sie erhalten equals() und hashCode() sofort einsatzbereit.

 data class Person( val name: String, val age: Int )

Kurz gesagt, obwohl ich Java liebe, wollte ich so schnell wie möglich in kurzer Zeit ein Minimum Viable Product für mein Projekt erstellen. Und im Fall der Softwareentwicklung ist der einfachste Weg, dies zu erreichen, weniger Code zu schreiben. Daher ging meine Suche nach einer besseren Sprache für die Backend-Entwicklung weiter. Mit diesem Gedanken im Hinterkopf wechselte ich zunächst zu Node.js. Es hat einige bedeutende Vorteile – ein paar Zeilen und Ihr Express-Server ist betriebsbereit, lauscht auf Port 8080 und antwortet mit Hello World! jedes Mal, wenn Sie eine Get-Anforderung senden.

 let express = require('express') let app = express(); app.get('/', (req, res) => res.send('Hello World!')); app.listen(8080);

Einfach, einfach und schnell. Genau das, was Sie von einer der beliebtesten Programmiersprachen erwarten würden. Ich arbeite gerne mit JavaScript und für einen kurzen Moment dachte ich, ich hätte das richtige Tool gefunden, aber dann wurde ich von der Tatsache verfolgt, dass JavaScript dynamisch typisiert ist. Verstehen Sie mich nicht falsch, ich denke, dass die dynamische Typisierung am Frontend großartig ist, aber meiner Erfahrung nach gibt Ihnen ein statisch typisiertes Backend einfach zusätzliches Vertrauen, dass Ihr Server zur Laufzeit aufgrund von Typkonflikten weniger wahrscheinlich abstürzt . Und seien wir ehrlich, wenn Ihr Backend mehrere hunderttausend Benutzer bedient, möchten Sie wirklich nicht, dass das passiert. Node.js bot jedoch eine großartige Funktion, die ich beibehalten wollte, nämlich die Möglichkeit, asynchronen Code und Dienste einfach zu schreiben.

Angesichts dieser Anforderungen habe ich mich entschieden, mein Kotlin-Android-Backend ebenfalls in Kotlin zu schreiben.

Kotlin: Ein kurzer Überblick

Für diejenigen unter Ihnen, die noch nie davon gehört haben: Kotlin ist eine statisch typisierte Open-Source-Programmiersprache, die sowohl objektorientierte als auch funktionale Programmierung unterstützt. Es bietet ähnliche Syntax und Konzepte wie C#, Java oder Scala und zielt hauptsächlich auf die JVM ab, hat aber auch Varianten, die auf JavaScript oder nativen Code abzielen. Es ist Java insofern sehr ähnlich, als Kotlin/JVM in Java-Bytecode kompiliert wird, sodass für Back-End-Ingenieure mit JVM-Hintergrund Kotlin leicht zu verstehen ist.

Wie auf der offiziellen Seite angegeben, ist das Ziel von Kotlin nicht, einzigartig zu sein, sondern Inspiration und Best Practices aus Jahrzehnten der Sprachentwicklung zu ziehen. Es kann mit jeder Java-IDE oder über die Befehlszeile verwendet werden, aber ich persönlich bevorzuge und empfehle die Verwendung mit IntelliJ. Es wird vom JetBrains-Team aktiv gewartet und aktualisiert, und machen Sie sich keine Sorgen über den Kauf der kostenpflichtigen Version – wenn Sie gerade erst mit Kotlin angefangen haben, wird die Community-Version von IntelliJ all Ihre Bedürfnisse erfüllen. Die drei wichtigsten Aspekte von Kotlin, auf die ich hinweisen möchte, sind, dass es a) prägnant ist (es reduziert den Boilerplate-Code drastisch), b) sicher (zum einen ist es darauf ausgelegt, Nullzeiger-Ausnahmen zu vermeiden) und c ) interoperabel (Sie können die vorhandenen Bibliotheken für die JVM, Android oder den Browser nutzen).

Kotlin-Koroutinen

Jeder möchte Dienste haben, die den Benutzern schnell dienen. Um die maximale Kapazität Ihres Servers zu erreichen, können Sie als Erstes eine Multithread-Anwendung verwenden. Java ist damit ziemlich umständlich. Wenn Sie Java lernen, lernen Sie zunächst, dass Sie, wenn Sie eine Multithread-Anwendung wünschen, entweder die Thread-Klasse erweitern oder die Runnable-Schnittstelle implementieren sollten. Anfänger verstehen nie wirklich, was der Unterschied ist (falls es einen gibt), aber um die Verwirrung zu verstärken, wird ihnen auch gesagt, dass sie einen Thread immer mit der Methode run starten sollen, niemals die Methode start. Oder warte, war es umgekehrt? Ist ja schließlich auch egal, einen Thread sollte man ohnehin nicht manuell starten, das ist zu teuer, sondern einen Thread-Pool nutzen. Einfach, außer dass es nicht ist.

Glücklicherweise hat Kotlin eine noch einfachere Lösung namens Coroutinen. Einfach ausgedrückt, Coroutinen ermöglichen es, sehr flüssig asynchronen, nicht blockierenden Code zu schreiben. Die Kernidee sind Funktionen, die ausgesetzt werden können; mit anderen Worten, die Berechnung kann irgendwann unterbrochen und später wieder aufgenommen werden. Das Beste daran ist, dass sich beim Schreiben von nicht blockierendem Code das Programmiermodell nicht wirklich ändert, sodass das Schreiben von nicht blockierendem Code im Wesentlichen dasselbe ist wie das Schreiben von blockierendem Code. Sehen wir uns zwei Beispiele an:

 fun sendRequest(): Int { /* do some heavy work */ return 1; }

Dieses Beispiel zeigt eine Sperrfunktion. Der Thread, der dieses Code-Snippet ausführt, wird keine andere Arbeit ausführen, bis die Funktion zurückkehrt, was im Falle eines API- oder Datenbankaufrufs einige Sekunden dauern kann. Wir wollen unseren Thread wirklich nicht blockieren, während wir auf einen anderen Dienst warten, also lasst uns diese Funktion in eine nicht blockierende umwandeln.

 suspend fun sendRequest(): Int { /* do some heavy work */ return 1; }

Dieses Beispiel zeigt, wie wir unsere Methode in eine nicht blockierende Funktion verwandeln können, die ausgesetzt werden kann. Dies bedeutet, dass, wenn die schwere Arbeit der Einfachheit halber ein einfacher Aufruf der Funktion delay() von 10 Sekunden ist, der ausführende Thread für diese Zeit an anderen Aufgaben weiterarbeitet und die Ausführung der Funktion nach Ablauf der 10 Sekunden wieder aufnimmt. Schöner, nicht blockierender Code, der mit einem Schlüsselwort erreicht wird.

Asynchroner Dienst mit Ktor

Wenn es um das Schreiben von REST-APIs geht, müssen einige zusätzliche Schritte unternommen werden, z. B. das Starten eines eingebetteten Servers oder das Analysieren der Anforderung, und natürlich möchte niemand dies manuell tun. Java hat Spring Boot, was die Dinge wirklich einfach macht, und zum Glück hat Kotlin ein Framework namens Ktor. Ktor ist ein Web-Framework zum Erstellen asynchroner Server. Wie auf der Website angegeben, ist Ktor „einfach zu bedienen, macht Spaß und ist asynchron“. Nun, Spaß ist subjektiv, also möchte ich das nicht beweisen, aber sehen wir uns einen Ausschnitt an, der sich als einfach zu verwenden und asynchron erweist.

 fun main() { embeddedServer(Tomcat, 8080) { routing { get { call.respond("Hello world!") } } }.start(wait = true) }

Das obige Beispiel zeigt einen voll funktionsfähigen Kotlin Ktor-Server, der auf einem eingebetteten Tomcat-Server ausgeführt wird, auf Port 8080 lauscht und asynchron mit „Hello world!“ antwortet. Anfragen zu bekommen. All dies in weniger als 10 Codezeilen.

Ktor kann offensichtlich viel mehr als das. Um alle Funktionen von Ktor vorzustellen, ist ein eigener Artikel erforderlich, aber unter anderem macht es die Anmeldung und Authentifizierung zum Kinderspiel. Lesen Sie hier mehr darüber, was Ktor serverseitig tun kann und wie es konfiguriert wird.

Weitere Vorteile von Kotlin im Backend

Der erste Vorteil, den ich hervorheben möchte, ist, dass Sie Java-Bibliotheken in Kotlin verwenden können, und glauben Sie mir, es gibt viele erstaunliche Bibliotheken von Drittanbietern für Java, die Ihnen das Leben erleichtern können. Warum sollten Sie Ihre eigene Implementierung schreiben, wenn es eine gebrauchsfertige Open-Source-Bibliothek gibt, die die Aufgabe perfekt erfüllt? Die Verwendung mit Kotlin funktioniert einwandfrei.

Ein weiterer großer Vorteil von Kotlin und Ktor sind die umfangreichen Testbibliotheken und Frameworks, die Sie verwenden können. Das Junit-Framework funktioniert wie ein Zauber mit Kotlin, und Ktor fügt darüber hinaus eine eigene Testbibliothek hinzu, mit der Sie im Handumdrehen End-to-End-Tests und Integrationstests schreiben können. Sie können eine benutzerdefinierte Test-Engine verwenden, die Ihre gesamte Anwendung ausführt und Anforderungen genauso verarbeiten kann wie die Live-Anwendung.

Fazit

Wie ich bereits erwähnt habe, bin ich in erster Linie ein Java-Back-End-Entwickler, der mehrere serverseitige Anwendungen und REST-APIs hinter mir hat. Obwohl ich gerne in Java programmiere, denke ich, dass es keine einzelne beste Sprache oder kein Framework gibt, das perfekt für jeden Job ist und jedes Problem lösen kann. Mein Ansatz besteht darin, sich mit so vielen Tools wie möglich vertraut zu machen, und wenn ein Problem auftritt, das beste Tool auszuwählen, das dieses spezielle Problem fehlerfrei lösen kann.

Wie auf der Kotlin-Site angegeben, ist das Ziel von Kotlin nicht, einzigartig zu sein; Stattdessen zieht es Inspiration und Best Practices aus Jahrzehnten der Sprachentwicklung, und ich glaube, dass Kotlin, Coroutines und Ktor ein erstaunliches Trio abgeben, wenn es um die Backend-Entwicklung geht. Hier können Sie mehr über Kotlin und seine Nützlichkeit als Programmiersprache lesen.