Redux ist ein hervorragendes Tool zum Verwalten des Status komplexer Front-End-Anwendungen. Der Autor des Materials, dessen Übersetzung wir heute veröffentlichen, wird die Antwort auf die Frage finden, ob es möglich ist, die Redux-Funktionen in der Serverumgebung zu nutzen.
Warum brauche ich eine Redux-Bibliothek?
Die
Homepage der Redux-Bibliothek gibt an, dass es sich um einen "vorhersehbaren Statuscontainer für JavaScript-Anwendungen" handelt. Redux wird normalerweise als Tool zum Verwalten des Status einer Anwendung bezeichnet. Obwohl diese Bibliothek hauptsächlich mit React verwendet wird, kann sie in allen JavaScript-basierten Projekten verwendet werden.
Wir haben bereits erwähnt, dass Redux verwendet wird, um den Status einer Anwendung zu steuern. Lassen Sie uns nun darüber sprechen, was eine "Bedingung" ist. Dieses Konzept ist ziemlich schwer zu definieren, aber wir versuchen immer noch, es zu beschreiben.
In Anbetracht des "Zustands" versuchen wir, wenn wir über Menschen oder über die Objekte der materiellen Welt sprechen, tatsächlich ihren Zustand zu dem Zeitpunkt zu beschreiben, zu dem wir über sie sprechen, möglicherweise unter Berücksichtigung eines oder mehrerer Parameter. Zum Beispiel können wir über den See sagen: "Das Wasser ist sehr heiß" oder: "Das Wasser ist gefroren." In diesen Aussagen beschreiben wir den Zustand des Sees anhand seiner Wassertemperatur.
Wenn jemand über sich selbst sagt: „Ich bin auf Grund“, denkt er über den Geldbetrag nach, den er hat. Es ist klar, dass wir in jedem dieser Beispiele nur über einen Aspekt des Zustands von Objekten sprechen. Im Beispiel über Geld kann die Aussage jedoch mehrere Parameter beschreiben: "Ich bin auf Grund, ich habe lange nichts gegessen, aber ich bin glücklich!" Es ist sehr wichtig anzumerken, dass der Staat etwas Unbeständiges ist. Dies bedeutet, dass es sich ändern kann. Wenn wir also den aktuellen Zustand eines bestimmten Objekts kennen, verstehen wir, dass sich sein realer Zustand einige Sekunden oder Minuten nach dem Erlernen ändern kann.
Wenn wir uns mit Programmen befassen, sind einige Funktionen mit dem Konzept des „Zustands“ verbunden. Erstens wird der Status der Anwendung durch Daten dargestellt, die irgendwo gespeichert sind. Diese Daten können beispielsweise im Speicher gespeichert werden (z. B. als JavaScript-Objekt), sie können jedoch in einer Datei, in einer Datenbank und mithilfe eines Caching-Mechanismus wie Redis gespeichert werden. Zweitens ist der Status einer Anwendung normalerweise an ihre spezifische Instanz gebunden. Wenn wir also über den Status der Anwendung sprechen, meinen wir eine bestimmte Instanz dieser Anwendung, einen Prozess, eine Arbeitsumgebung, die in der Anwendung für einen bestimmten Benutzer organisiert ist. Ein Anwendungsstatus kann beispielsweise die folgenden Informationen enthalten:
- Ist der Benutzer angemeldet oder nicht? Wenn ja, wie lange dauert die Sitzung und wann läuft sie ab?
- Wie viele Punkte hat der Benutzer erzielt? Eine solche Frage ist beispielsweise für ein bestimmtes Spiel relevant.
- Wo genau hat der Benutzer das Video angehalten? Diese Frage kann zur Video-Player-Anwendung gestellt werden.
Wenn wir auf einer niedrigeren Ebene über den Status von Anwendungen sprechen, kann dies beispielsweise die folgenden Informationen enthalten:
- Welche Variablen werden in der aktuellen Umgebung festgelegt, in der die Anwendung ausgeführt wird (dies bezieht sich auf die sogenannten "Umgebungsvariablen").
- Welche Dateien verwendet das Programm derzeit?
Wenn wir uns jederzeit den „Snapshot“ (sie werden oft als „Snapshots“ - aus dem Snapshot bezeichnet) des Anwendungsstatus ansehen, können wir die Bedingungen kennen, unter denen die Anwendung zu diesem Zeitpunkt gearbeitet hat, und diese Bedingungen gegebenenfalls neu erstellen, indem wir Anwendung auf den Zustand, in dem sie sich zum Zeitpunkt des Empfangs des Schnappschusses befand.
Der Status kann während der Ausführung bestimmter Aktionen durch den Benutzer geändert werden. Wenn der Benutzer beispielsweise den Spielcharakter in einem einfachen Spiel korrekt bewegt, kann dies die Anzahl der Punkte erhöhen. In ziemlich komplexen Anwendungen kann der Ansatz zum Ändern eines Zustands komplizierter werden, Zustandsänderungen können aus verschiedenen Quellen stammen.
In einem Mehrspielerspiel hängt die Anzahl der Punkte, die ein Benutzer erzielt, nicht nur von seinen Aktionen ab, sondern auch von den Aktionen derjenigen, die mit ihm im selben Team spielen. Und wenn ein computergesteuerter Charakter einen vom Benutzer kontrollierten Spielcharakter erfolgreich angreift, kann der Benutzer eine bestimmte Anzahl von Punkten verlieren.
Stellen Sie sich vor, wir entwickeln eine Front-End-Anwendung wie
PWA Twitter . Dies ist eine einseitige Anwendung, in der es mehrere Registerkarten gibt, z. B. Startseite, Suche, Benachrichtigungen und Nachrichten. Jede dieser Registerkarten verfügt über einen eigenen Arbeitsbereich, in dem sowohl bestimmte Informationen angezeigt als auch geändert werden können. Alle diese Daten bilden den Status der Anwendung. Daher kommen alle paar Sekunden neue Tweets, Benachrichtigungen und Nachrichten in der Anwendung an. Der Benutzer kann mit dem Programm und mit diesen Daten arbeiten. Zum Beispiel kann er einen Tweet erstellen oder löschen, er kann einen Tweet retweeten, er kann Benachrichtigungen lesen, Nachrichten an jemanden senden und so weiter. Alles, was gerade besprochen wurde, ändert den Status der Anwendung.
Alle diese Registerkarten verfügen über eigene Benutzeroberflächenkomponenten, mit denen Daten angezeigt und geändert werden. Der Status der Anwendung kann durch Daten von außen und Benutzeraktionen beeinflusst werdenEs ist klar, dass in einer solchen Anwendung die Quellen für Zustandsänderungen unterschiedliche Entitäten sein können, während die von verschiedenen Quellen initiierten Änderungen fast gleichzeitig auftreten können. Wenn wir den Status manuell verwalten, kann es für uns schwierig sein, zu überwachen, was passiert. Diese Schwierigkeiten führen zu Widersprüchen. Beispielsweise kann ein Tweet gelöscht werden, er wird jedoch weiterhin im Tweet-Stream angezeigt. Beispielsweise kann der Benutzer die Benachrichtigung oder Nachricht lesen, sie wird jedoch im Programm weiterhin als nicht angezeigt angezeigt.
Der Benutzer kann einen Tweet mögen, ein Herz wird in der Programmoberfläche angezeigt, aber eine Netzwerkanforderung, die Informationen über ähnliche Dinge an den Server sendet, funktioniert nicht. Infolgedessen unterscheidet sich das, was der Benutzer sieht, von dem, was auf dem Server gespeichert ist. Um solche Situationen zu verhindern, kann Redux erforderlich sein.
Wie funktioniert Redux?
In der Redux-Bibliothek gibt es drei Hauptkonzepte, die darauf abzielen, die Verwaltung des Anwendungsstatus einfach und unkompliziert zu gestalten:
- Lagerung (Laden). Ein Redux-Repository ist ein JavaScript-Objekt, das den Status einer Anwendung darstellt. Es spielt die Rolle der "einzigen Quelle zuverlässiger Daten". Dies bedeutet, dass die gesamte Anwendung auf Speicher als einzige Entität angewiesen sein muss, die für die Darstellung des Staates verantwortlich ist.
- Aktionen Der Statusspeicher ist schreibgeschützt. Dies bedeutet, dass es nicht durch direkten Zugriff geändert werden kann. Die einzige Möglichkeit, den Inhalt des Repositorys zu ändern, besteht in der Verwendung von Aktionen. Jede Komponente, die den Status ändern möchte, sollte die entsprechenden Maßnahmen ergreifen.
- Reduzierstücke (Reduzierstücke), die auch als "Wandler" bezeichnet werden. Ein Reduzierer ist eine reine Funktion, die beschreibt, wie ein Zustand durch Aktionen geändert wird. Der Reduzierer übernimmt den aktuellen Status und die Aktion, deren Ausführung von einer bestimmten Komponente der Anwendung angefordert wurde, und gibt anschließend den transformierten Status zurück.
Die Verwendung dieser drei Konzepte bedeutet, dass die Anwendung Ereignisse, die Quellen für Statusänderungen sind (Benutzeraktionen, API-Antworten, das Auftreten von Ereignissen im Zusammenhang mit dem Empfang bestimmter Daten über das WebSocket-Protokoll usw.), nicht mehr direkt überwachen und Entscheidungen darüber treffen sollte, wie Diese Ereignisse wirken sich auf den Zustand aus.
Mithilfe des Redux-Modells können diese Ereignisse Aktionen auslösen, die den Status ändern. Komponenten, die im Anwendungsstatus gespeicherte Daten verwenden müssen, können einfach Statusänderungen abonnieren und Informationen erhalten, die für sie von Interesse sind. Durch die Verwendung all dieser Mechanismen ist Redux bestrebt, vorhersehbare Änderungen des Anwendungsstatus vorzunehmen.
Hier ist ein schematisches Beispiel, das zeigt, wie Sie mit Redux in unserer fiktiven Anwendung ein einfaches Zustandsverwaltungssystem organisieren können:
import { createStore } from 'redux';
Auf dieser Grundlage können wir unser Anwendungsstatus-Managementsystem mit zusätzlichen Aktionen ausstatten und diese von verschiedenen Stellen der Anwendung senden, ohne das Risiko einer hoffnungslosen Verwirrung einzugehen.
Hier ist das Material, aus dem Sie mehr über die drei Grundprinzipien von Redux erfahren können.
Lassen Sie uns nun über die Verwendung von Redux in einer Serverumgebung sprechen.
Reduzieren von Redux-Prinzipien in die Serverumgebung
Wir haben die Funktionen von Redux untersucht, die bei der Entwicklung von Clientanwendungen verwendet werden. Da Redux jedoch eine JavaScript-Bibliothek ist, kann es theoretisch auch in einer Serverumgebung verwendet werden. Wir werden darüber nachdenken, wie die oben genannten Prinzipien auf den Server angewendet werden können.
Erinnern Sie sich, wie wir darüber gesprochen haben, wie der Status der Clientanwendung aussieht? Es ist zu beachten, dass es einige konzeptionelle Unterschiede zwischen Client- und Serveranwendungen gibt. Daher neigen Clientanwendungen dazu, den Status zwischen verschiedenen Ereignissen aufrechtzuerhalten, beispielsweise zwischen der Ausführung von Anforderungen an den Server. Solche Anwendungen werden als Stateful-Anwendungen bezeichnet.
Wenn sie nicht bestrebt wären, den Status zu speichern, müsste der Benutzer beispielsweise bei der Arbeit mit einem bestimmten Webdienst, für den ein Login und ein Kennwort erforderlich sind, dieses Verfahren ausführen, wenn er zu einer neuen Seite der entsprechenden Weboberfläche wechselt.
Backend-Anwendungen hingegen bemühen sich, den Status nicht zu speichern (sie werden auch als zustandslose Anwendungen bezeichnet). Wenn wir von „Backend-Anwendungen“ sprechen, meinen wir hauptsächlich Projekte, die auf bestimmten APIs basieren, die von Front-End-Anwendungen getrennt sind. Dies bedeutet, dass Informationen über den Status des Systems bei jedem Zugriff ähnlichen Anwendungen zur Verfügung gestellt werden sollten. Beispielsweise überwacht die API nicht, ob der Benutzer angemeldet ist oder nicht. Es ermittelt seinen Status, indem es das Authentifizierungstoken in seinen Anforderungen an diese API analysiert.
Dies führt uns zu einem wichtigen Grund, warum Redux auf Servern in der Form, in der wir seine Funktionen oben beschrieben haben, kaum verwendet wird.
Tatsache ist, dass Redux so konzipiert wurde, dass der temporäre Status der Anwendung gespeichert wird. Der Status der auf dem Server gespeicherten Anwendung sollte jedoch normalerweise lange genug vorhanden sein. Wenn Sie das Redux-Repository in Ihrer serverseitigen Node.js-Anwendung verwenden würden, würde der Status dieser Anwendung jedes Mal gelöscht, wenn der
node
gestoppt wird. Wenn es sich um einen PHP-Server handelt, der ein ähnliches Statusverwaltungsschema implementiert, wird der Status gelöscht, wenn jede neue Anforderung beim Server eintrifft.
Die Situation ist noch komplizierter, wenn wir Serveranwendungen hinsichtlich ihrer Skalierbarkeit betrachten. Wenn Sie die Anwendung horizontal skalieren und die Anzahl der Server erhöhen müssten, würden viele Node.js-Prozesse gleichzeitig ausgeführt, und jeder von ihnen hätte seine eigene Statusoption. Dies bedeutet, dass bei gleichzeitigem Empfang von zwei identischen Anfragen an das Backend durchaus unterschiedliche Antworten gegeben werden könnten.
Wie wende ich die von uns diskutierten Prinzipien der Zustandsverwaltung auf dem Server an? Schauen wir uns die Redux-Konzepte noch einmal an und sehen, wie sie normalerweise in einer Serverumgebung verwendet werden:
- Repository. Im Backend ist „die einzige Quelle für zuverlässige Daten“ normalerweise eine Datenbank. Manchmal kann eine Kopie eines Teils dieser Datenbank erstellt werden, um den Zugriff auf häufig erforderliche Daten zu erleichtern, oder aus einem anderen Grund - in Form eines Caches oder in Form einer Datei. In der Regel sind solche Kopien schreibgeschützt. Die Mechanismen, die sie steuern, werden Änderungen im Hauptrepository abonniert und aktualisieren bei solchen Änderungen den Inhalt der Kopien.
- Aktionen und Reduzierungen. Sie sind die einzigen Mechanismen, mit denen der Zustand geändert werden kann. In den meisten Backend-Anwendungen ist der Code in einem imperativen Stil geschrieben, der der Verwendung von Aktionskonzepten und Reduzierungen nicht besonders förderlich ist.
Stellen Sie sich zwei Entwurfsmuster vor, die ihrer Natur nach den Zielen der Redux-Bibliothek ähneln. Dies sind CQRS und Event Sourcing. Sie sind tatsächlich vor Redux erschienen, ihre Implementierung kann äußerst schwierig sein, daher werden wir sehr kurz darauf eingehen.
CQRS und Event Sourcing
CQRS (Command Query Responsibility Segregation) ist ein Entwurfsmuster, bei dessen Implementierung die Anwendung Daten nur mithilfe von Abfragen aus dem Speicher liest und nur mithilfe von Befehlen schreibt.
Bei Verwendung von CQRS besteht die einzige Möglichkeit, den Status einer Anwendung zu ändern, darin, einen Befehl zu senden. Befehle ähneln Redux-Aktionen. In Redux können Sie beispielsweise Code schreiben, der diesem Schema entspricht:
const action = { type: 'CREATE_NEW_USER', payload: ... }; store.dispatch(action);
Bei Verwendung von CQRS würde so etwas folgendermaßen aussehen:
Abfragen sind Datenlesemechanismen in der CQRS-Vorlage. Sie entsprechen dem Konstrukt
store.getState()
. In einer einfachen CQRS-Implementierung interagieren Abfragen direkt mit der Datenbank und rufen Datensätze aus dieser ab.
Die Ereignisbeschaffungsvorlage dient zum Aufzeichnen aller Änderungen im Anwendungsstatus als Folge von Ereignissen. Diese Vorlage eignet sich am besten für Anwendungen, die nicht nur den aktuellen Status, sondern auch den Verlauf der Änderungen und den aktuellen Status der Anwendung kennen müssen. Als Beispiele können Sie hier die Betriebsgeschichte mit Bankkonten, die Sendungsverfolgung, die Bearbeitung von Bestellungen in Online-Shops, die Organisation des Frachttransports und die Logistik anführen.
Hier ist eine Beispielimplementierung der Event Sourcing-Vorlage:
Was hier passiert, ähnelt auch der Arbeit mit Redux-Aktionen.
Der Ereignisregistrierungsmechanismus organisiert jedoch auch die Langzeitspeicherung von Informationen über jede Zustandsänderung und nicht nur die Speicherung des Zustands selbst. Auf diese Weise können wir diese Änderungen zu dem von uns benötigten Zeitpunkt reproduzieren und so den Inhalt des Anwendungsstatus zu diesem Zeitpunkt wiederherstellen. Wenn wir beispielsweise verstehen müssen, wie viel Geld zu einem bestimmten Zeitpunkt auf dem Bankkonto war, müssen wir nur die Ereignisse reproduzieren, die mit dem Bankkonto passiert sind, bis wir das richtige Datum erreicht haben. Ereignisse werden in diesem Fall durch Geldeingänge auf dem Konto und deren Belastung von diesem, durch Belastung der Bankprovision und anderer ähnlicher Vorgänge dargestellt. Wenn Fehler auftreten (dh wenn Ereignisse mit falschen Daten auftreten), können wir den aktuellen Status der Anwendung ungültig machen, die entsprechenden Daten korrigieren und zum aktuellen Status der Anwendung zurückkehren, der jetzt fehlerfrei erstellt wurde.
CQRS- und Event Sourcing-Vorlagen werden häufig zusammen verwendet. Interessanterweise basiert Redux tatsächlich teilweise auf diesen Vorlagen. Befehle können so geschrieben werden, dass sie beim Aufruf Ereignisse senden. Anschließend interagieren die Ereignisse mit dem Repository (Datenbank) und aktualisieren den Status. In Echtzeitanwendungen können Abfrageobjekte auch Ereignisse abhören und aktualisierte Statusinformationen vom Repository erhalten.
Die Verwendung einer dieser Vorlagen in einer einfachen Anwendung kann dies unnötig komplizieren. Bei Anwendungen, die zur Lösung komplexer Geschäftsprobleme entwickelt wurden, sind CQRS und Event Sourcing leistungsstarke Abstraktionen, mit deren Hilfe der Themenbereich solcher Anwendungen besser modelliert und deren Statusverwaltung verbessert werden kann.
Bitte beachten Sie, dass CQRS- und Event-Sourcing-Muster auf unterschiedliche Weise implementiert werden können, während einige ihrer Implementierungen komplexer sind als andere. Wir haben nur sehr einfache Beispiele für ihre Implementierung betrachtet. Wenn Sie Serveranwendungen in Node.js schreiben, schauen Sie sich
wolkenkit an . Dieses Framework bietet dem Entwickler unter anderem eine der einfachsten Schnittstellen für die Implementierung der CQRS- und Event Sourcing-Vorlagen.
Zusammenfassung
Redux ist ein großartiges Tool zum Verwalten des Status einer Anwendung, um Statusänderungen vorhersehbar zu machen. In diesem Artikel haben wir über die Schlüsselkonzepte dieser Bibliothek gesprochen und festgestellt, dass die Verwendung von Redux in einer Serverumgebung wahrscheinlich keine gute Idee ist, Sie jedoch ähnliche Prinzipien auf einen Server anwenden können, indem Sie die Vorlagen
CQRS und
Event Sourcing verwenden .
Liebe Leser! Wie organisieren Sie die Statusverwaltung von Client- und Serveranwendungen?
