Event-driven-Architektur mit Kotlin: Von Coroutinen zu reaktiven Streams

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Event-driven-Architektur mit Kotlin: Warum das nicht nur ein modischer Trend ist

\n

Stellen Sie sich vor, Ihre Anwendung ist ein perfekt abgestimmter Mechanismus. Jedes Zahnrad weiß, wann es sich drehen muss, jeder Kolben, wann er sich bewegen muss. Aber was, wenn eines Tages ein neues Teil hinzugefügt werden muss, ohne die gesamte Maschine anzuhalten? In einer traditionellen synchronen Architektur wird dies oft zum Albtraum: Umschreiben ganzer Module, Testen endloser Aufrufketten und schlaflose Nächte.

\n

Hier kommt die Event-driven-Architektur mit Kotlin ins Spiel – ein Paradigma, bei dem Komponenten über Ereignisse kommunizieren und nicht über direkte Aufrufe. Kotlin bietet mit seinen Coroutinen und reaktiven Streams einfach ideale Werkzeuge dafür. In diesem Artikel werden wir nicht nur über die Theorie sprechen – wir schreiben echten Code, analysieren Kotlin Flow und Channels, und ich zeige Ihnen, wie Sie ein flexibles, skalierbares System aufbauen, das bei der ersten Belastung nicht auseinanderfällt.

\n\n

Was ist eine ereignisgesteuerte Architektur einfach erklärt

\n

Beim klassischen Ansatz (stellen Sie sich Microservices vor, die sich gegenseitig per REST anrufen) ist jede Anfrage eine starre Verbindung. Dienst A ruft Dienst B auf, wartet auf eine Antwort, und wenn B ausfällt, bricht alles zusammen. In einer Event-driven-Architektur ist alles anders: Komponenten veröffentlichen Ereignisse (z. B. "Bestellung erstellt") und abonnieren diese. Niemand wartet auf jemanden, niemand ruft direkt an.

\n

Das Schöne an Kotlin ist, dass es ermöglicht, dieses Modell nativ zu implementieren, ohne umfangreiche Frameworks einbinden zu müssen. Coroutinen bieten leichtgewichtige Threads, und Channel und Flow sind fertige Busse für Ereignisse.

\n

Schauen wir uns ein einfaches Beispiel an – einen eigenen EventBus in Kotlin:

\n\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.channels.*\n\nclass SimpleEventBus {\n    private val events = Channel<Any>(Channel.UNLIMITED)\n\n    suspend fun publish(event: Any) {\n        events.send(event)\n    }\n\n    suspend fun subscribe(handler: suspend (Any) -> Unit) {\n        for (event in events) {\n            handler(event)\n        }\n    }\n}\n\n// Verwendung\nfun main() = runBlocking {\n    val bus = SimpleEventBus()\n    \n    launch {\n        bus.subscribe { event ->\n            println("Ereignis empfangen: $event")\n        }\n    }\n    \n    delay(100)\n    bus.publish("Hallo, Event-Driven!")\n    delay(100)\n}
\n\n

Dieser Code ist die Basis. Wir erstellen einen Kanal, der wie eine asynchrone Warteschlange funktioniert. Der Herausgeber legt ein Ereignis ab, der Abonnent holt es ab. Alles einfach, aber hier zeigt sich bereits die Stärke der Event-driven-Architektur mit Kotlin: Abonnent und Herausgeber wissen nichts voneinander.

\n\n

Kotlin Flow: Reaktive Streams für Ereignisse

\n

Channel ist großartig, aber für reale Projekte wird oft mehr benötigt: kalte und heiße Streams, Transformationen, Fehlerbehandlung. Hier kommt Kotlin Flow ins Spiel – eine reaktive Bibliothek, die direkt in die Sprache integriert ist.

\n

Flow eignet sich ideal für die asynchrone Programmierung mit Kotlin, wenn Ereignisse kontinuierlich generiert werden. Zum Beispiel Wechselkursaktualisierungen, Nachrichtenfeeds oder UI-Zustände.

\n\n

Kalte vs. heiße Streams

\n

Es ist wichtig, den Unterschied zu verstehen:

\n
    \n
  • Kalte Streams (Cold Stream) – beginnen nur zu arbeiten, wenn jemand sie abonniert hat. Jeder Abonnent erhält seinen eigenen Datenstrom.
  • \n
  • Heiße Streams (Hot Stream) – arbeiten ständig, unabhängig von Abonnenten. Späte Abonnenten verpassen alte Ereignisse.
  • \n
\n

Für eine Event-driven-Architektur werden in der Regel heiße Streams benötigt. In Kotlin werden diese über SharedFlow oder StateFlow implementiert.

\n\n

Beispiel – ein Benachrichtigungssystem:

\n\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\n\ndata class Notification(val userId: String, val message: String)\n\nclass NotificationService {\n    private val _notifications = MutableSharedF                

Blogs

Buchempfehlungen