Reactive Programming im Java Umfeld

Ein kurze Beschreibung von Reactive Programming und eine Übersicht welche Frameworks es gibt und für welche Anwendungsfälle es sich lohnt


Ich durfte 2015 an der Spring I/O teilnehmen. Dort war Spring Reactor, die Reactive Programming Antwort von Spring, noch ein Thema für Early Adoptors. Heute 8 Jahre später wird der Großteil der Spring Boot Anwendungen immer noch mit dem thread-per-request Model (also non-reactive) umgesetzt. Wir stellen hier einmal Reactive Programming im Bereich Java vor und zeigen auf für welche Anwendungen es sich lohnt.

Was ist Reactive Programming?

Um Reactive Programming zu verstehen, sollte man zunächst ein gewöhnliches Programm betrachten, z.B. einen Web-Server. Hier werden Web-Anfragen synchron von Worker-Threads abgearbeitet. Stößt der Worker-Thread dabei auf eine Datenbankanfrage oder muss eine Datei von einem anderen Server herunterladen, dann wartet der Thread auf die Antwort und ist blockiert.

Sind alle Worker-Threads mit blockierenden Anfragen, z.B. Datenbankanfragen, beschäftigt, läuft die Abarbeitung-Queue vom Webserver voll und neue Anfragen laufen in ein Timeout oder können gar nicht mehr beantwortet werden. Es ist also möglich, dass alle Worker-Threads warten (blockiert sind) und quasi nichts tun und trotzdem das System keine Anfragen mehr beantworten kann.

Reactive Programming versucht dieses Problem über Events zu lösen. Das Ganze funktioniert dabei ähnlich, wie bei einer Service-Kraft, die in einem Restaurant über eine Klingel von der Küche informiert wird, dass eine Bestellung fertig ist und nicht vor der Küche warten muss. Die meisten Frameworks setzen dabei auf asynchrone Event-Datenströme („asynchronous data streams“), welche von einem oder mehreren Event-Loops-Threads (z.B. Vert.x) an Worker-Threads verteilt werden.

Vereinfacht kann man sich das Ganze so vorstellen:

  1. Der Event-Loop verwaltet eine Event-Queue. Hier werden eingehende Events inklusive Event-Type und zugehörige Kontext-Daten abgespeichert.
  2. Der Event-Loop kontrolliert dabei kontinuierlich die Event-Queue auf neue Events in einer Schleife - daher der Name - zur Abarbeitung.
  3. Der Event-Loop entfernt das erste Event aus der Event-Queue und bestimmt auf Basis des Event-Typs und der Meta-Daten einen Handler der das Event verarbeiten soll.
  4. Der Handler bearbeitet dann das Event - im besten Fall - asynchron und schreibt das z.B. über einen Callback zurück in die Event-Queue.

Dabei entstehen häufig die erwähnten Event-Datenströme, d.h. eine Anwendung wird in kleine Tasks (mapping functions) gestückelt, die ein Event als Eingabe in ein anderes Event als Ausgabe überführen. Und der Event-Loop verteilt die einzelen Tasks dann auf verschiedene Worker-Threads. Trifft eine Mapping-Function dann auf einen Datenbank-Aufruf, dann ist dieser im besten Fall selbst wieder reaktiv programmiert, d.h. der Worker-Thread muss nicht auf die Datenbank-Antwort warten, sondern übergibt dem reaktiven Datenbank-Treiber einfach einen Callback und ist sofort wieder frei für neue Arbeit. Bekommt der Datenbank-Treiber dann seine Antwort übergibt er diese direkt der nächsten Funktion oder schreibt sie verpackt als Event in die Event-Queue.

Wieso programmiert man nicht nur Reactive?

Jetzt haben wir also ungefähr eine Idee von Reactive Programming. Jetzt stellt man sich unweigerlich die Frage, warum entwickelt man nicht nur so.

Wie in vielen Bereichen so gilt auch beim reactive programming, dass nichts wirklich kostenfrei ist. Dadurch das eine Anfrage zusätzlich durch das Event-Loop-System wandern muss, ist eine einzelne Anfrage in einer reaktiven Anwendung eher langsamer als schneller verglichen mit dem non-reactive Pendant. Erst unter Last kann ein solches System seine Vorteile wirklich ausspielen, da man blockierende Anfragen vermeidet. Zusätzlich spart man sich das ständige auf- und abbauen von Threads, welches eines der Probleme im thread-per-request model ist. Unter Last wird also die durchschnittliche Abarbeitungszeit in einem reaktiven System mit steigender Last weniger steil steigen, so dass das System mehr Anfragen in einer für den Anwender akzeptablen Zeit liefern kann. Des Weiteren werden so natürlicherweise die CPUs besser ausgelastet, so dass man in einem Hochlast-System Hardware sparen kann.

Auch wenn ein reaktives Programm unter Last in der Regel mehr Anfragen pro Sekunde bedienen kann, skaliert ein solches Programm nicht endlos, d.h. irgendwann ist man doch wieder darauf angewiesen neue Hardware bzw. neue Instanzen des Programms ins Spiel zu springen.

Die Callback-Hölle

Des Weiteren bringen reaktive Frameworks auch noch zusätzliche Konzepte mit sich, die ein gewisses Umdenken bei der Programmierung erfordert. Hier kann man pauschal sagen, dass Entwickler die mit funktionaler Programmierung gut zurecht kommen, sich auch in der reaktiven Programmierung schnell zu recht finden.

Dadurch das asynchron gearbeitet wird, kann eben nicht mit den eigentlichen Antwortobjekten gearbeitet werden, sondern man muss mit Callbacks arbeiten. Durch die Verschachtelung von mehreren Callbacks kommt man schnell in die sog. Callback-Hölle:

Um der Callback-Hell (oder Callback-Pyramide) zu entkommen, setzen viele Frameworks auf Container-Objekte, die die zukünftige Antwort oder einen Fehler kapseln: bei Spring Webflux sind das z.B. Flux für eine Sequenz von Daten und Mono als Container für genau einen Wert. Diese Container-Objekte ermöglichen es die asynchronen Sequenzen oder Daten mit verschiedenen Funktionen, wie z.B. map, flatMap, merge oder doOnError zu kombinieren.

Diese Container heißen in den unterschiedlichen Frameworks anders, mal Observables, Promises oder Futures, dahinter steckt aber immer das gleiche Publisher - Subscriber Prinzip, d.h. ohne Subscriber wird auch nichts geliefert. Man spricht hier häufig von cold observables und hot observables. In dem obrigen Beispiel ist der Mono-Container noch kalt, erst durch subscribe() wird er heiß und ein Ergebnis würde produziert werden.

Reactive Programming bringt also neue Konzepte mit sich, die über die verschiedenen Programmiersprachen zwar etabliert sind, dennoch ein gewisses Umdenken erfordern.

Für welche Anwendungen lohnt sich Reactive Programming?

Wenn man mal die Komplexität der Programmierung außer Acht lässt, dann kann man grundsätzlich alle Anwendungen reaktiv umsetzen.

Um zu verstehen, welche Anwendungen sich besonders gut eignen reaktiv umgesetzt zu werden, kann man sich nochmals ein Restaurant vorstellen. Der nicht-reaktive Ansatz würde hier also z.B. bedeuten, dann Servicekräfte nach der Bestellung des Gastes vor der Küche warten bis die Bestellung abgearbeitet wurde. Wenn jetzt ein Restaurant 10 Service-Kräften und 10 Köche hat und es kommen nie mehr als 9 Gäste gleichzeitig ins Restaurant, dann ist das kein Problem. Kommen hier aber schon die 20 Gäste, hat man ein großes Problem, wenn man nicht asynchron arbeitet.

Spring Boot in Verbindung mit Tomcat z.B. reserviert in der Standardkonfiguration 200 Threads für die Abarbeitung von Anfragen (thread-per-request model). Um in einen Zustand zukommen, in dem Anfragen nicht mehr beantwortet können, benötigt es schon ein relativ viele Requests pro Sekunde. Stellt man sich also eine Datenbank in einem solchem System vor, welche alle Anfragen in max. 200ms beantwortet. Dann kommt man rechnerisch auf 1000ms / 200ms = 5 Requests pro Sekunde für einen Thread. Macht theoretisch 1000 Request pro Sekunde für das Gesamtsystem, selbst wenn man mit 30% Overhead durch das Framework rechnen würde, sind das immer noch 700 Requests pro Sekunde. Klar spielen hier Faktoren wie Anzahl der CPUs und die Gesamtinfrastruktur ein große Rolle. Zu dem sind Rechner nicht teuer, d.h. kommt man wirklich an die Grenzen, dann kann man sich recht schnell einen weiteren Service daneben stellen, vor allem wenn man seinen Service bei einem Cloud-Anbieter betreibt.

Festhalten lässt sich also, das reaktive Anwendung sich immer dann lohnen wenn: - Resourcen knapp sind, d.h. man kann nicht gut mit Hardware skalieren, z.B. ein IoT-Device, welches viele Sensordaten verarbeiten soll - Effizient gearbeitet werden soll, z.B. ein Service läuft auf einer VM und soll die maximal möglichen Req./s abarbeiten - Anfragen nicht schnell abgearbeitet werden können, z.B. ein Service der einen weit entfernten Webservice anfragen muss und ggf. mehrere Sekunden auf eine Antwort warten muss. - Echtzeitdaten angezeigt werden sollen, z.B. eine Aktienticker App, die viele User per Push über Preisänderungen informieren soll

Eine Besonderheit, die noch erwähnt werden soll, sind Anwendungen bei denen die Push-Nachrichten an z.B. ein Frontend geschickt werden sollen. Eine solche Anwendung setzt eine ständige Verbindung zwischen Client und Server voraus, z.B. über WebSockets. Hier stößt man mit einem thread-per-request model sehr schnell an Grenzen, weshalb sich reactive Programming besonders gut eignet.

Welche Frameworks existieren für Java?

Für Java-Entwickler existieren inzwischen einige Reactive Frameworks, wie z.B.:

  • RxJava, die ReactiveX Referenz-Implementation für Java
  • Kotlin Flow, JetBrains reactive Framework, stark inspiriert von Reactive Streams
  • Vert.x, die Antwort von Eclipse für Reactive applications
  • Spring Project Reactor, hier zu erwähnen ist sicherlich Spring WebFlux, als reactives Web-Framework im Spring-Kosmos
  • akka, ein Toolkit für Reactive Applications von der Firma Lightbend
  • Ratpack, ein Open-Source-Framework gebaut auf Java und Nettys Event getriebener Netzwerk-Engine

Die Wahl eines Frameworks hängt von verschiedenen Kriterien ab und muss individuell bestimmt werden. Bei allen Fragen rund um reactive Programming oder der Wahl eines Frameworks können wir Sie sehr gerne unterstützen: info[at]youniverse.com

Fazit

Reactive Programming hat sicherlich seine Anwendungsgebiete, allerdings stoßen auch diese Anwendungen irgendwann an ihre Grenzen und man kommt nicht drumherum mit Hardware zu skalieren. Da nimmt der Großteil es einfach hin, dass er etwas früher einen weiteren Knoten in seinen Cluster integrieren muss, als dass er sich ein reaktives Framework ans Bein bindet.

Wenn Websockets eine Rolle spielen oder für IoT-Geräte, die mit Java entwickelt werden sollen, dann sind Reactive Frameworks sicherlich sehr interessant. Für "normalen" CRUD-Backend-Services, die nicht auf Ressourcenoptimierung primär angelegt sind, wird man wohl entweder eine von Haus aus reactive Programmiersprache setzen oder bleibt eben beim thread-per-request-Modell.

Man muss jedoch sagen, dass durch Kotlin Flow, Spring Webflux und R2DBC es noch nie einfacher war mit Java bzw. Kotlin einen reaktiven Webservice aufzusetzen.

blog

Tutorial: Aufbau eines reaktiven RESTful Webdienstes mit Spring WebFlux

Mit Hilfe von Spring Webflux, Kotlin und R2DBC zeigen wir, wie einfach man einen reaktiven Webserver aufsetzen kann


In diesem Tutorial zeigen wir, wie leicht man Spring WebFlux mit Kotlin kombinieren kann, um einen reaktiven Web-Server zu entwickeln. Es handelt sich dabei um ein sehr einfaches Beispiel, dass nur den Einstieg aufzeigen soll und eigentlich nicht der Komplexität einer reaktiven Anwendung gerecht wird.

Wer noch nicht genau weiß, was ein reaktiver Web-Server ist, der sollte sich unser Tutorial: Reactive Programming mit Java ansehen.

Datenbank aufsetzen mit Docker Compose

In diesem Beispiel werden wir eine Postgres Datenbank nutzen. Diese können wir zum Beispiel mit Hilfe von Docker compose starten.

Die folgende Konfiguration legt eine Postgres Datenbank und startet ein Initialisierungsskript:

Das Datenbank-Skript db.sql legt uns eine Tabelle message an und füllt sie mit 1000 Testdatensätzen.

Benötigte Dependencies

Für unser kleinen reaktiven Webserver nutzen wir zwei Spring Boot Starter Bibliotheken: Spring Boot Webflux Starter für den non-blocking REST-API-WebServer und Spring Boot Starter Data R2DBC für den non-blocking Datenbank Zugriff. Um die Vorteile von Kotlin nutzen zu können, brauchen wir zwei Bibliotheken: Kotlin Reflect und Kotlin Coroutines Reactor. Damit können wir anstatt mit Mono und Flux mit Flow und suspendable Methods arbeiten.

Message model und Repository

Jetzt müssen wir noch das Message-Model anlegen. Wir realisieren das mit einer Kotlin Data Klasse, die einiges an Funktionalität mitbringt, wie z.B. equals() / hashCode() und eine toString()-Methode mit den Klassen-Attributen.

Durch @Id wird das id Feld als das Feld markiert, welches den Primary Key repräsentiert. Ist der Wert 0, weiß Spring Boot Data, dass es sich um ein neues Objekt handelt.

Zum Schluss brauchen wir noch eine Repository-Klasse um die Elemente aus der Datenbank zu holen.

Dafür nutzen wir ein CoroutineCrudRepository aus dem Spring Data Framework. Hier sind alle Methoden bereits suspendable, so dass wir die Vorteile von Kotlin nutzen können.

Rest Controller

Zum Schluss brauchen wir noch den Rest-Controller, der uns die CRUD-Operationen bereitstellt.

Die Methoden sind alle suspendable, aber mehr müssen wir nicht machen. Die gesamte Umwandlung von suspendable Method zu Mono/Flux übernimmt für uns Kotlin Coroutines Reactor und das reaktive Anbinden an den Netty Webserver übernimmt Spring Boot Webflux.

Fazit

Nie war es einfacher einen reaktiven Webserver mit Java bzw. Kotlin aufzusetzen. Allerdings handelt es sich hier aber nur um ein sehr kleines Beispiel. Bringt man mehr Komplexität in das Projekt, dann werden die Schwierigkeiten, die ein reaktives Framework mit sich bringen, erst wirklich deutlich. Wer sich dafür interessiert, sollte einfach mal dieses Projekt von Github clonen und selbst erweitern.

Falls es Fragen oder Anregungen gibt, dann schreibt uns gerne eine Mail an: info@youniverse.com.

blog

Vergleich React Native vs Native App-Entwicklung

Wir sehen uns beide Konzepte hinsichtlich der Aspekte Lernkurve, Programmieraufwand, Performance, Wartung/Pflege und Dokumentation genauer an.


Welcher Software-Entwickler kennt es nicht? Es steht ein neues App-Projekt an, und wieder einmal stellt sich die Frage des zu wählenden Umsetzungskonzepts. In diesem Artikel ignorieren wir vorsätzlich die üblichen Abhängigkeiten (Kundenwunsch, ggf. Strategie der Vorgesetzten, Personalkapazitäten etc.) und fokussieren uns ausschließlich auf die technischen Aspekte beim Vergleich der zwei wesentlichen Programmierkonzepte für die Erstellung von Mobile Apps: Native Programmierung einerseits und hybride Entwicklung am Beispiel von „React Native“ andererseits.

Wir wollen beide Konzepte hinsichtlich verschiedener Parameter wie Programmieraufwand, Performance, Wartung und Pflege, Dokumentation etc. miteinander vergleichen und versuchen, Handlungsanleitungen zu geben, in welchem Kontext welches Konzept am meisten Sinn hat.

Wir werden dies jeweils anhand einer simplen Beispiel-Applikation durchführen. Die App berechnet auf Basis von Nutzereingaben den Benzinverbrauch pro 100 km sowie die Kosten für 100 km. Das Ergebnis des Verbrauchs soll zusätzlich in Form eines Tachometer-Diagramms dargestellt werden, der Code für das Diagramm soll dabei idealerweise aus einer externen Library der jeweiligen Plattform kommen.

Los geht’s!

Native Programmierung

Bekanntermaßen bedeutet native Programmierung, dass die originären Programmiersprachen der jeweiligen Plattformen iOS bzw. Android verwendet werden - und zwar ausschließlich. Auf der iOS-Seite weicht dabei gute alte Objective-C seit einigen Jahren immer mehr Apples Sprache Swift.

Der folgende Screenshot zeigt eine Vorschau unserer App im iOS-Emulator:

Vorschau im iOS-Emulator

Im Folgenden ist der Quellcode zu sehen, welcher die Berechnung in Swift durchführt sowie die Benutzeroberfläche mittels SwiftUI realisiert.


Sämtliche Code-Beispiele können selbstverständlich auch von unserer Webseite heruntergeladen werden, Download-Links werden am Ende dieses Artikels bereitgestellt.

Bei Android gab es eine vergleichbare Transition vom klassischen Java-Code hin zu Kotlin. Unser Beispiel würde in Kotlin mit Nutzung von Jetpack Compose, ungefähr so aussehen:


Der folgende Screnshot zeigt die Anwendung im Android-Emulator:

Vorschau im Android-Emulator

React Native

React Native basiert auf React wurde ab der 2010er Jahre von Facebook entwickelt und auch für deren eigene Facebook-App verwendet. Es verfolgt die Idee des Code-Once-Run-Anywhere, also der Arbeit auf einer Quellcodebasis, aus welcher dann die Applikationen für die jeweiligen Plattformen generiert werden. Die React-UI-Komponenten werden dabei direkt auf die nativen UI-Elemente der jew. Plattform gemappt. React bzw. ReactNative verwendet seit jeher ebenfalls ein deklaratives Konzept für die Programmierung der Nutzeroberflächen. Das Weiteren haben wir das Erweiterungs-Framework Expo verwendet, welches insb. beim Thema Build und Deployment die Arbeit vereinfacht.

Der Quellcode unserer Demo-Applikation sieht folgendermaßen aus:


Im folgenden ein Screenshot der Applikation, umgesetzt im React-Native-Ökosystem:

Die App umgesetzt mit React Native

Vergleich der Konzepte

Wir werden nun die beiden Konzepte hinsichtlich verschiedener Eigenschaften untersuchen und einander gegenüberstellen. Es werden die folgenden Parameter untersucht und bewertet:

  • die Lernkurve bzw. der notwendige Einarbeitungsaufwand
  • die vorhandene Dokumentation
  • der eigentliche Aufwand bei der Umsetzung des Projekts
  • die Performance der fertigen Applikation
  • die Komplexität des Deployment-Prozesses
  • Wartung und Pflege der App
  • der Themenkomplex Weiterentwicklung der Frameworks

1.) Einarbeitungsaufwand

Ein nicht von der Hand zu weisender Faktor ist, dass bei React Native lediglich eine Programmiersprache erlernt und verwendet werden muss, um gleichermaßen auf Android und iOS dabei sein zu können, wohingegen die native Entwicklung Kenntnisse in zwei komplett unterschiedlichen Ökosystemen voraussetzt. Im Hinblick auf den Einarbeitungsaufwand beziehungsweise den Bedarf an entsprechend ausgebildeten Programmierern stellt dies einen eindeutigen Vorteil für React Native dar. Zu berücksichtigen ist dabei allerdings, dass bei intensiver Nutzung von React Native früher oder später ggf. auch die Notwendigkeit bestehen wird, in den nativen Source-Code einzugreifen, um, z. B. eigene Komponenten hinzuzufügen oder bestehende anzupassen.

2.) Dokumentation

Hinsichtlich der Dokumentation der untersuchten Programmierkonzepte lassen sich kaum Unterschiede feststellen, sowohl die Dokumentation von Android/Kotlin bzw. iOS/Swift und auch die von React Native / Javascript lassen sich als gut gepflegt, vollständig und verständlich bezeichnen.

3.) Aufwand für die Projektumsetzung

Kommen wir nun zu einem sehr wichtigen Punkt und vergleichen den jeweiligen Umsetzungsaufwand anhand unseres Beispielprojekts. Ein halbwegs erfahrener Programmierer ist sicherlich in der Lage, unser simples iOS-Projekt mit Swift unter Verwendung von SwiftUI und inklusive der Einbindung einer externen Library innerhalb von 2-3 Stunden fertig zu stellen. Ganz ähnlich sieht es bei Android aus: Die Programmierung von Kotlin inklusive Programmierung der deklarativen UI mittels Compose und der Einbindung einer externen Bibliothek ist in ca. 3 Stunden zu schaffen. Positiv zu erwähnen bleibt hier, dass mit Android Studio eine etwas umfangreichere und an Features reichere IDE zur Verfügung steht als bei Apple mit Xcode. In beiden nativen Programmiersystemen stehen mit Swift UI auf der einen und Android Studio bzw. Compose auf der anderen Seite sehr mächtige und ausgereifte Tools zur Verfügung, um Oberflächen zu erstellen.

Bei React bzw. React Native kann prinzipiell jede IDE verwendet werden, mit der Javascript-Entwicklung möglich ist. Die Fertigstellung des Projekts inkl. Konfiguration des Erweiterungs-Framework Expo dauert ebenfalls ca. 3 Stunden.

Insofern lässt sich festhalten, dass der Programmieraufwand bei der nativen Programmierung nahezu doppelt so hoch ist wie bei React Native, um eine simple App zu erstellen, die auf beiden Plattformen lauffähig ist.

Bei React Native können wir des Weiteren als Vorteil den „Fast Refresh“ erwähnen: Änderungen am Quellcode sind in der Regel unmittelbar in der Web-Vorschau zu sehen und beschleunigen so den Implementierungs-prozess, wohingegen bei iOS und Android nur teilweise UI-Vorschauen möglich sind und üblicherweise jeweils ein entsprechender neuer Bild angestoßen werden muss, welcher bekanntermaßen je nach Projektgröße durchaus einige Zeit dauern kann.

Bei unserer Untersuchung zum Thema Programmieraufwand hat also ganz klar React Native die Nase vorn.

4.) Performance:

Bei unserer simplen Test-Applikation waren auf echten Geräten keinerlei Unterschiede in Hinblick auf die Geschwindigkeit beim Rendering der Seite oder bei Reaktionen auf Nutzerinteraktionen festzustellen. Lediglich beim initialen Starten der zuvor geschlossenen App schneiden die nativen Frameworks (etwas) besser ab ab.

Allgemein betrachtet besteht die Erwartung, dass React Native schlechter abschneidet beim Thema Performance, zumindest sofern komplexe UI-Animationen verwendet werden oder CPU-intensive Aufgaben durchgeführt werden sollen. Dies liegt daran, dass die nativen Apps direkteren Zugriff haben auf die plattform-spezifischen APIs.

Um dies ein wenig näher zu untersuchen, haben wir unsere App dahingehend erweitert, dass nun statt nur einem Chart ganze 100 Chart-UI-Komponenten in einem ScrollView untereinander gerendert werden. Folgender Screenshot verdeutlicht den Aufbau der App in diesem Szenario:

Die App erweitert auf 100 Chart-Komponenten

Interessanterweise lassen sich auch bei diesem Szenario sowohl auf dem iOS-Simulator/Android-Emulator als auch auf den echten Geräten nur sehr geringe Unterschiede zu den nativen Apps bezüglich der Performance ausmachen. Sowohl beim zügigen Scrollen durch die 100 Ui-Komponenten als auch beim Setzen eines Zeigerwertes reagieren die mit React Native erzeugten Apps nur unwesentlich langsamer als die nativ programmierten Apps. Selbstverständlich könnte man ein noch komplexeres Beispiel aufsetzen, um das Performance-Gefälle deutlicher darzustellen, aber dies würde den Rahmen dieses Artikels springen.

5.) Deployment:

Der Deploymentprozess bei Apple wurde in den vergangenen Jahre deutlich vereinfacht, so dass üblicherweise direkt aus Xcode heraus die fertige Application hochgeladen werden kann. Bei der Erstellung des Store-Eintrags fällt dann der übliche Aufwand an für das Hochladen der Screenshots, Einstellen der Texte usw. Bei Android sieht es ganz ähnlich aus. Üblicherweise erstellt man aus dem Android Studio heraus eine Datei, welche dann in der Play Store Developer Konsole hochgeladen werden kann. Dort können dann auch alle weiteren Einträge für den Store hinterlegt werden. Normalerweise sind beide Apps nach einer Prüfung dann im jeweiligen App Store verfügbar.

Das Deployment ist eine Schwäche von React Native, da letztlich die erzeugten Applikationen eweils über die individuellen Deployment-Wege der beiden nativen Plattformen hochgeladen werden müssen und somit doch wieder plattformspezifisches Knowhow notwendig wird. Dieses Problem wird teilweise durch die Verwendung von Expo abgemildert, da hier z. b. Builds auf einfachere Art und Weise durchgeführt werden können.

Letztlich gibt es hier keinen eindeutigen Sieger.

6.) Wartung und Pflege

Bei diesem Punkt geht es in der Regel um das Aktualisieren einer bereits im Store befindlichen App, also um das Deployen eines Updates zu einem bestehenden Projekt. Bei iOS und auch bei Android erfolgt dies nahezu über den identischen Weg wie der initiale Upload, d.h. es wird auch wieder eine Prüfung nötig, welche unter Umständen einige Tage dauern kann (und somit im Falle eines kritischen Bugfixes zu ernsthaften ungewollten Verzögerungen führen kann). Bei React Native hingegen ist es möglich, mittels Erweiterungsframeworks den „Over the Air“-Mechanismus zu verwenden und auf diese Weise den Nutzern ein Update unmittelbar zur Verfügung zu stellen und somit das zeitraubende Review zu umgehen. Dies ist ohne Zweifel ein großer Vorteil bei der Programmierung mit React Native ggü. der nativen Entwicklung.

7.) Aktualisierungen der Entwicklungsplattformen

Nicht verschwiegen werden soll der Nachteil, dass React Native (und analog dazu auch auch jedes andere System, das mehrere Plattformen auf einmal ansprecht) immer das Problem hat, bei Updates des iOS- oder Android-Betriebssystems „nachziehen“ zu müssen und das eigene Framework entsprechend anzupassen. So entsteht zumindest eine greringe Verzögerung, bis neueste Features aus den zugrunde liegenden nativen Frameworks verwendet werden können. Des Weiteren ist eine in Entwicklerkreisen bekannte Tatsache, dass jede zusätzlich verwendete Technologie weitere Komplexität und somit auch eine erhöhte Fehleranfälligkeit mit sich bringt. Der Punkt in dieser Kategorie geht somit an die native Programmierung.

Fazit

Folgende Übersicht fasst sämtliche Ergebnisse der Untersuchungen des letzten Abschnitts zusammen, dabei vergeben wir pro Plattform für jeden untersuchten Aspekt zwischen einem und drei Punkte:

 

iOS Swift     Android Kotlin    React Native   
Einarbeitungsaufwand + + ++
Dokumentation +++ +++ +++
Projektumsetzungsaufwand + + +++
Performance +++ +++ ++
Deployment ++ +++ ++
Wartung + + +++
Aktualisierung der Frameworks     +++ +++ +
Summe 14 15 16

  

Es lässt sich also (leider) kein eindeutiger Sieger feststellen. Stattdessen erhalten wir eindeutiges Sowohl-Als-Auch! Fazit: Je nach Anwendungsfall ist also manchmal die native Programmierung besser geeignet und manchmal React Native.

Selbstverständlich kann es den Sonderfall geben, dass gezielt ausschließlich nur für eine der beiden großen Plattformen entwickelt werden soll, dann würde man in der Regel zur nativen Programmiersprache der jeweiligen Plattform greifen. Dies ist aber erfahrungsgemäß nicht der Normalfall - üblicherweise soll natürlich für beide Plattformen entwickelt werden.

React Native hat ganz eindeutige Vorteile beim Aufwand der Projekt-umsetzung und bei der Aktualisierung durch das Over-the-Air-Prinzip. Die nativen Programmiersprachen haben hingegen bei der Aktualität der zur Verfügung stehenden Features sowie auch in einigen komplexen Szenarien beim Thema Performance Vorteile.
Als Faustregel lässt sich festhalten: Sofern Performance und die Verwendung von der allerneusten Plattform-Features keine kritische Rolle spielt, schlägt das Pendel tendenziell eher in Richtung React Native aus. Dennoch sollte man von Projekt zu Projekt neu entscheiden und die Vor- und Nachteile sehr genau abwägen.

Wir hoffen, wir konnten mit diesem Artikel ein wenig dabei helfen, die Technologien für Ihr nächstes Projekt einzuschätzen. Sollten Sie derzeit ein Projekt planen und sich gerade in der Entscheidungsfindung befinden, so zögern Sie bitte nicht, uns unter info@youniverse.com zu kontaktieren. Wir helfen Ihnen gern!

Materialien

Download sämtlicher Projektdateien dieses Artikels (iOS-App, Android-App und React-Native-App, jeweils als One-Chart- sowie also MultiChart-Version).

blog