Single-Page-Anwendungen Framework-unabhängig entwickeln

Datenfluss

Anzeige

In Single-Page Apps ist der State zu berücksichtigen, den es zu verwalten gilt. Zu ihm gehören alle Daten und Informationen, die die Applikation innerhalb der Laufzeit verwendet. In klassischen Architekturen wie MVC und MVVM ist der State in den entsprechenden Controllern und ViewModels verteilt, wodurch er innerhalb der Applikation stark fragmentiert sein kann.

Im Gegensatz dazu gibt es aktuell einen Trend hin zu den One-Way Data Flow Patterns. Während der One-Way Data Flow im Umfeld von React schon immer Bestandteil des Konzepts war, gehen mittlerweile auch Frameworks wie Angular 2.0 konzeptionell in diese Richtung. Das Muster zeichnet sich dadurch aus, dass die Applikation den State zentral verwaltet. Daten fließen in Form von Nachrichten in einer Richtung durch die Applikation.

Ein Vorreiter der One-Way Data Flow Pattern im SPA-Kontext ist Flux. Das Entwurfsmuster ist als die Applikationsarchitektur von Facebook bekannt.

Aktionen sind zentrale Komponente der Flux-Architektur (Abb. 2).

Die Pfeile innerhalb der Darstellung verdeutlichen die Richtung des Datenflusses. Aktionen bewegen sich als Nachrichten durch die Anwendung. Sie sind der Ausgangspunkt der Flux-Architektur und beschreiben allgemein die Intention etwas zu tun. Neben einer eindeutigen Bezeichnung besteht eine Aktion aus allen Daten und Informationen, die für ihre spätere Verarbeitung notwendig sind.

Der Dispatcher nimmt Aktionen entgegen und leitet sie an registrierte Stores weiter. Letztere sind der Kern der Applikation, die sogenannte "Single Source of Truth". Der Applikations-State wird zentral verwaltet, gekapselt und lässt sich nur durch Aktionen explizit verändern. Der Vorgang ist dadurch explizit, dass an der Stelle, wo der State verändert wird, auch der Kontext und somit der Grund für die Änderung bekannt ist.

Immer wenn sich der State ändert, löst die Anwendung ein Event aus, worauf die View durch Anfordern des aktuellen States und seine Darstellung reagiert. Die View ist darüber hinaus der Ort, an dem Aktionen angestoßen werden. Innerhalb von Flux kann es beliebig viele Stores, Actions und Views geben, jedoch nur einen Dispatcher.

Redux ist nach den Prinzipien funktionaler Programmierung gestaltet und stellt die State-Verwaltung ins Zentrum (Abb. 3).

Redux ist ebenfalls den One-Way Data Flow Patterns zuzuordnen. Es handelt sich dabei vereinfacht ausgedrückt um einen State-Container mit dem Ziel, den State zentral und transparent innerhalb der Applikation zu verwalten. Redux ist aus Flux entstanden, seine Entwickler gestalteten es jedoch von Grund auf nach Prinzipien funktionaler Programmierung.

In einer Redux-Applikation gibt es nur einen einzigen Store, in dem der komplette State der Anwendung zentral gespeichert wird. Aktionen stellen (wie bei Flux) die einzige Möglichkeit dar, den State im Store zu verändern. Um zu definieren, wie genau diese Änderungen funktionieren, gibt es das Konzept der Reducer. Sie sind als sogenannte Pure Functions realisiert, JavaScript-Funktionen ohne Seiteneffekte.

Einen weiteren Ansatz stellen die reaktiven Entwurfsmuster dar. Unter reaktiver Programmierung versteht man die Programmierung mit asynchronen Event-Streams. Sie lassen sich beispielsweise mit Bibliotheken wie RX.js oder Bacon.js realisieren. RX.js ist Teil der Reactive Extension. Sie stellt unter der Organisation von ReactiveX die reaktiven Patterns für eine Vielzahl von Programmiersprachen unter einer gemeinsamen API zur Verfügung.

Asynchrone Event-Streams kann man sich vereinfacht als unveränderliche Arrays vorstellen.

[1,2,3,4,5,6].filter(x => x % 2 === 0);
// Result: [2, 4, 6]

Geht man von einem Array mit Zahlen aus, so lässt sich via filter-Funktion beispielsweise nach allen geraden Zahlen suchen. Das Ergebnis ist ein neues Array mit der gefilterten Zahlenmenge.

[2,3,5].map(x => x * 2);
// Result: [4, 6, 10]

Analog dazu ist es mit der map-Funktion möglich, die Werte im Array zu transformieren. Das Ergebnis ist ein neues Array aller Zahlen multipliziert mit 2. Geht man mit dem Wissen über Arrays gedanklich zurück zu den Event-Streams (auch Observables genannt), verhalten sie sich ähnlich.

Event eines Streams lassen sich wie Arrays filtern (Abb. 4).


Betrachtet man einen Event-Stream von Click-Events, lassen sie sich genauso filtern wie Arrays. Das Ergebnis ist ein neuer Event-Stream mit allen Events deren y-Wert im vorliegenden Beispiel kleiner als 100 ist. Neben der filter-Funktion gibt es eine Vielzahlweiterer Funktionen, die sich auf Event-Streams anwenden lassen, beispielsweise um mehrere Streams zu kombinieren.

Umfasst die zu entwickelnde Applikation viel Asynchronität oder sogar Echtzeit-Features, kann die reaktive Programmierung ihre Stärken voll ausspielen.

Anzeige