Nutzung der deklarativen Programmierung zur Erstellung wartbarer Web-Apps
Veröffentlicht: 2022-03-11In diesem Artikel zeige ich, wie die sinnvolle Einführung deklarativer Programmiertechniken es Teams ermöglichen kann, Webanwendungen zu erstellen, die einfacher zu erweitern und zu warten sind.
„…deklarative Programmierung ist ein Programmierparadigma, das die Logik einer Berechnung ausdrückt, ohne ihren Kontrollfluss zu beschreiben.“ —Remo H. Jansen, Praktische funktionale Programmierung mit TypeScript
Wie bei den meisten Softwareproblemen erfordert die Entscheidung, deklarative Programmiertechniken in Ihren Anwendungen einzusetzen, eine sorgfältige Abwägung der Kompromisse. Schauen Sie sich einen unserer vorherigen Artikel an, um eine ausführliche Diskussion darüber zu erhalten.
Hier liegt der Fokus darauf, wie deklarative Programmiermuster nach und nach sowohl für neue als auch für bestehende Anwendungen übernommen werden können, die in JavaScript geschrieben sind, einer Sprache, die mehrere Paradigmen unterstützt.
Zuerst erörtern wir, wie Sie TypeScript sowohl im Backend als auch im Frontend verwenden können, um Ihren Code ausdrucksstärker und widerstandsfähiger gegen Änderungen zu machen. Anschließend untersuchen wir Finite-State-Maschinen (FSMs), um die Front-End-Entwicklung zu rationalisieren und die Beteiligung der Interessengruppen am Entwicklungsprozess zu erhöhen.
FSMs sind keine neue Technologie. Sie wurden vor fast 50 Jahren entdeckt und sind in Branchen wie der Signalverarbeitung, der Luftfahrt und dem Finanzwesen beliebt, in denen die Korrektheit der Software entscheidend sein kann. Sie eignen sich auch sehr gut für Modellierungsprobleme, die in der modernen Webentwicklung häufig auftreten, wie z. B. die Koordination komplexer asynchroner Zustandsaktualisierungen und Animationen.
Dieser Vorteil ergibt sich aus Einschränkungen bei der Art und Weise, wie der Staat verwaltet wird. Eine Zustandsmaschine kann sich gleichzeitig nur in einem Zustand befinden und hat begrenzte benachbarte Zustände, in die sie als Reaktion auf externe Ereignisse (z. B. Mausklicks oder Abrufantworten) übergehen kann. Das Ergebnis ist meist eine deutlich reduzierte Fehlerquote. Es kann jedoch schwierig sein, FSM-Ansätze zu skalieren, um in großen Anwendungen gut zu funktionieren. Jüngste Erweiterungen von FSMs, die als Zustandsdiagramme bezeichnet werden, ermöglichen die Visualisierung komplexer FSMs und deren Skalierung auf viel größere Anwendungen, auf die sich dieser Artikel konzentriert. Für unsere Demonstration verwenden wir die XState-Bibliothek, die eine der besten Lösungen für FSMs und Zustandsdiagramme in JavaScript ist.
Deklarativ im Backend mit Node.js
Die Programmierung eines Webserver-Backends mit deklarativen Ansätzen ist ein umfangreiches Thema und beginnt normalerweise mit der Evaluierung einer geeigneten serverseitigen funktionalen Programmiersprache. Nehmen wir stattdessen an, Sie lesen dies zu einem Zeitpunkt, an dem Sie Node.js bereits für Ihr Backend ausgewählt haben (oder in Betracht ziehen).
Dieser Abschnitt beschreibt einen Ansatz zur Modellierung von Entitäten am Backend, der die folgenden Vorteile bietet:
- Verbesserte Lesbarkeit des Codes
- Sichereres Refactoring
- Potenzial für eine verbesserte Leistung aufgrund der Garantien, die die Modellierung bietet
Verhaltensgarantien durch Typmodellierung
JavaScript
Betrachten Sie die Aufgabe, einen bestimmten Benutzer über seine E-Mail-Adresse in JavaScript zu suchen:
function validateEmail(email) { if (typeof email !== "string") return false; return isWellFormedEmailAddress(email); } function lookupUser(validatedEmail) { // Assume a valid email is passed in. // Safe to pass this down to the database for a user lookup.. }
Diese Funktion akzeptiert eine E-Mail-Adresse als Zeichenfolge und gibt bei Übereinstimmung den entsprechenden Benutzer aus der Datenbank zurück.
Die Annahme ist, dass lookupUser()
erst aufgerufen wird, wenn die grundlegende Validierung durchgeführt wurde. Dies ist eine zentrale Annahme. Was ist, wenn einige Wochen später ein Refactoring durchgeführt wird und diese Annahme nicht mehr gilt? Drücken Sie die Daumen, dass die Komponententests den Fehler finden, oder wir senden möglicherweise ungefilterten Text an die Datenbank!
TypeScript (erster Versuch)
Betrachten wir ein TypeScript-Äquivalent der Validierungsfunktion:
function validateEmail(email: string) { // No longer needed the type check (typeof email === "string"). return isWellFormedEmailAddress(email); }
Dies ist eine leichte Verbesserung, da uns der TypeScript-Compiler das Hinzufügen eines zusätzlichen Laufzeitvalidierungsschritts erspart hat.
Die Sicherheitsgarantien, die starkes Tippen mit sich bringen kann, wurden noch nicht wirklich ausgenutzt. Lassen Sie uns das untersuchen.
TypeScript (zweiter Versuch)
Lassen Sie uns die Typsicherheit verbessern und die Weitergabe unverarbeiteter Zeichenfolgen als Eingabe an looukupUser
:
type ValidEmail = { value: string }; function validateEmail(input: string): Email | null { if (!isWellFormedEmailAddress(input)) return null; return { value: email }; } function lookupUser(email: ValidEmail): User { // No need to perform validation. Compiler has already ensured only valid emails have been passed in. return lookupUserInDatabase(email.value); }
Das ist besser, aber umständlich. Alle Verwendungen von ValidEmail
greifen über email.value
auf die tatsächliche Adresse zu. TypeScript verwendet eher die strukturelle Typisierung als die nominale Typisierung, die von Sprachen wie Java und C# verwendet wird.
Dies ist zwar leistungsfähig, bedeutet jedoch, dass jeder andere Typ, der sich an diese Signatur hält, als gleichwertig angesehen wird. Beispielsweise könnte der folgende Passworttyp ohne Beanstandung des Compilers an lookupUser()
werden:
type ValidPassword = { value: string }; const password = { value: "password" }; lookupUser(password); // No error.
TypeScript (dritter Versuch)
Wir können eine nominale Typisierung in TypeScript erreichen, indem wir Schnittmengen verwenden:
type ValidEmail = string & { _: "ValidEmail" }; function validateEmail(input: string): ValidEmail { // Perform email validation checks.. return input as ValidEmail; } type ValidPassword = string & { _: "ValidPassword" }; function validatePassword(input: string): ValidPassword { ... } lookupUser("[email protected]"); // Error: expected type ValidEmail. lookupUser(validatePassword("MyPassword"); // Error: expected type ValidEmail. lookupUser(validateEmail("[email protected]")); // Ok.
Wir haben nun das Ziel erreicht, dass nur validierte E-Mail-Strings an lookupUser()
übergeben werden können.
Profi-Tipp: Wenden Sie dieses Muster einfach mit dem folgenden Hilfstyp an:
type Opaque<K, T> = T & { __TYPE__: K }; type Email = Opaque<"Email", string>; type Password = Opaque<"Password", string>; type UserId = Opaque<"UserId", number>;
Vorteile
Durch die starke Eingabe von Entitäten in Ihrer Domain können wir:
- Reduzieren Sie die Anzahl der zur Laufzeit durchzuführenden Prüfungen, die wertvolle Server-CPU-Zyklen verbrauchen (obwohl es sich um eine sehr kleine Menge handelt, summieren sich diese bei der Verarbeitung von Tausenden von Anfragen pro Minute).
- Pflegen Sie weniger grundlegende Tests aufgrund der Garantien, die der TypeScript-Compiler bietet.
- Profitieren Sie von Editor- und Compiler-gestütztem Refactoring.
- Verbessern Sie die Code-Lesbarkeit durch verbessertes Signal-Rausch-Verhältnis.
Nachteile
Bei der Typmodellierung müssen einige Kompromisse berücksichtigt werden:
- Die Einführung von TypeScript verkompliziert normalerweise die Toolchain, was zu längeren Ausführungszeiten für Builds und Testsuiten führt.
- Wenn es Ihr Ziel ist, ein Feature zu prototypisieren und es den Benutzern so schnell wie möglich zur Verfügung zu stellen, lohnt sich der zusätzliche Aufwand, der erforderlich ist, um die Typen explizit zu modellieren und sie durch die Codebasis zu verbreiten, möglicherweise nicht.
Wir haben gezeigt, wie vorhandener JavaScript-Code auf dem Server oder einer gemeinsam genutzten Back-End-/Front-End-Validierungsschicht mit Typen erweitert werden kann, um die Lesbarkeit des Codes zu verbessern und ein sichereres Refactoring zu ermöglichen – wichtige Anforderungen für Teams.
Deklarative Benutzerschnittstellen
Benutzerschnittstellen, die mit Techniken der deklarativen Programmierung entwickelt wurden, konzentrieren sich auf die Beschreibung des „Was“ statt des „Wie“. Zwei der drei Hauptbestandteile des Webs, CSS und HTML, sind deklarative Programmiersprachen, die sich im Laufe der Zeit und auf mehr als 1 Milliarde Websites bewährt haben.
React wurde 2013 von Facebook als Open Source bereitgestellt und hat den Verlauf der Front-End-Entwicklung erheblich verändert. Als ich es zum ersten Mal benutzte, fand ich es toll, wie ich die GUI als Funktion des Zustands der Anwendung deklarieren konnte. Ich war jetzt in der Lage, große und komplexe UIs aus kleineren Bausteinen zusammenzustellen, ohne mich mit den chaotischen Details der DOM-Manipulation auseinanderzusetzen und nachzuverfolgen, welche Teile der App als Reaktion auf Benutzeraktionen aktualisiert werden müssen. Ich konnte den Zeitaspekt beim Definieren der Benutzeroberfläche weitgehend ignorieren und mich darauf konzentrieren, sicherzustellen, dass meine Anwendung korrekt von einem Zustand in den nächsten übergeht.
Um eine einfachere Möglichkeit zum Entwickeln von Benutzeroberflächen zu erreichen, fügte React eine Abstraktionsschicht zwischen dem Entwickler und dem Computer/Browser ein: das virtuelle DOM .
Andere moderne Web-UI-Frameworks haben diese Lücke ebenfalls geschlossen, wenn auch auf unterschiedliche Weise. Beispielsweise verwendet Vue funktionale Reaktivität entweder durch JavaScript-Getter/Setter (Vue 2) oder Proxys (Vue 3). Svelte bringt Reaktivität durch einen zusätzlichen Quellcode-Kompilierungsschritt (Svelte).
Diese Beispiele scheinen den großen Wunsch in unserer Branche zu demonstrieren, bessere und einfachere Tools für Entwickler bereitzustellen, um das Anwendungsverhalten durch deklarative Ansätze auszudrücken.
Status und Logik der deklarativen Anwendung
Während sich die Präsentationsschicht weiterhin um irgendeine Form von HTML dreht (z. B. JSX in React, HTML-basierte Vorlagen in Vue, Angular und Svelte), vermute ich, dass das Problem, wie man den Zustand einer Anwendung so modelliert, das ist leicht verständlich für andere Entwickler und wartbar, wenn die Anwendung wächst, ist immer noch ungelöst. Beweise dafür sehen wir in einer Vermehrung von Bibliotheken und Ansätzen für die Staatsverwaltung, die bis heute anhält.
Die Situation wird durch die steigenden Erwartungen an moderne Web-Apps kompliziert. Einige aufkommende Herausforderungen, die moderne State-Management-Ansätze unterstützen müssen:
- Offline-First-Anwendungen mit erweiterten Abonnement- und Caching-Techniken
- Prägnanter Code und Wiederverwendung von Code für immer kleiner werdende Anforderungen an die Paketgröße
- Nachfrage nach immer ausgefeilteren Benutzererlebnissen durch High-Fidelity-Animationen und Echtzeit-Updates
(Wieder-)Auftauchen von endlichen Zustandsautomaten und Zustandsdiagrammen
Endliche Automaten werden in großem Umfang für die Softwareentwicklung in bestimmten Branchen eingesetzt, in denen die Anwendungsrobustheit entscheidend ist, wie z. B. in der Luftfahrt und im Finanzwesen. Es gewinnt auch stetig an Popularität für die Front-End-Entwicklung von Web-Apps, beispielsweise durch die hervorragende XState-Bibliothek.
Wikipedia definiert einen endlichen Automaten als:
Eine abstrakte Maschine, die sich zu einem bestimmten Zeitpunkt in genau einem von endlich vielen Zuständen befinden kann. Die FSM kann als Reaktion auf einige externe Eingaben von einem Zustand in einen anderen wechseln; Der Übergang von einem Zustand in einen anderen wird als Übergang bezeichnet. Ein FSM wird durch eine Liste seiner Zustände, seines Anfangszustands und der Bedingungen für jeden Übergang definiert.
Und weiter:
Ein Zustand ist eine Beschreibung des Status eines Systems, das darauf wartet, einen Übergang auszuführen.
FSMs in ihrer Grundform lassen sich aufgrund des Zustandsexplosionsproblems nicht gut auf große Systeme skalieren. Kürzlich wurden UML-Zustandsdiagramme erstellt, um FSMs mit Hierarchie und Parallelität zu erweitern, die eine breite Verwendung von FSMs in kommerziellen Anwendungen ermöglichen.

Deklarieren Sie Ihre Anwendungslogik
Erstens, wie sieht ein FSM als Code aus? Es gibt mehrere Möglichkeiten, einen endlichen Automaten in JavaScript zu implementieren.
- Endlicher Automat als switch-Anweisung
Hier ist eine Maschine, die die möglichen Zustände beschreibt, in denen sich ein JavaScript befinden kann, implementiert mit einer switch-Anweisung:
const initialState = { type: 'idle', error: undefined, result: undefined }; function transition(state = initialState, action) { switch (action) { case 'invoke': return { type: 'pending' }; case 'resolve': return { type: 'completed', result: action.value }; case 'error': return { type: 'completed', error: action.error ; default: return state; } }
Dieser Codestil wird Entwicklern vertraut sein, die die beliebte Redux-Zustandsverwaltungsbibliothek verwendet haben.
- Zustandsmaschine als JavaScript-Objekt
Hier ist dieselbe Maschine, die als JavaScript-Objekt mithilfe der JavaScript-XState-Bibliothek implementiert wurde:
const promiseMachine = Machine({ id: "promise", initial: "idle", context: { result: undefined, error: undefined, }, states: { idle: { on: { INVOKE: "pending", }, }, pending: { on: { RESOLVE: "success", REJECT: "failure", }, }, success: { type: "final", actions: assign({ result: (context, event) => event.data, }), }, failure: { type: "final", actions: assign({ error: (context, event) => event.data, }), }, }, });
Während die XState-Version weniger kompakt ist, hat die Objektdarstellung mehrere Vorteile:
- Die Zustandsmaschine selbst ist einfaches JSON, das leicht beibehalten werden kann.
- Da sie deklarativ ist, kann die Maschine visualisiert werden.
- Bei der Verwendung von TypeScript prüft der Compiler, dass nur gültige Zustandsübergänge durchgeführt werden.
XState unterstützt Zustandsdiagramme und implementiert die SCXML-Spezifikation, wodurch es für den Einsatz in sehr großen Anwendungen geeignet ist.
Statecharts Visualisierung eines Versprechens:
Best Practices für XState
Im Folgenden finden Sie einige Best Practices, die Sie anwenden sollten, wenn Sie XState verwenden, um die Wartbarkeit von Projekten zu gewährleisten.
Nebeneffekte von Logik trennen
XState ermöglicht es, Nebeneffekte (zu denen Aktivitäten wie Protokollierung oder API-Anforderungen gehören) unabhängig von der Logik der Zustandsmaschine zu spezifizieren.
Dies hat folgende Vorteile:
- Unterstützen Sie die Erkennung von Logikfehlern, indem Sie den Zustandsmaschinencode so sauber und einfach wie möglich halten.
- Visualisieren Sie den Zustandsautomaten ganz einfach, ohne zuerst zusätzliche Boilerplates entfernen zu müssen.
- Einfacheres Testen der Zustandsmaschine durch Einfügen von Mock-Services.
const fetchUsersMachine = Machine({ id: "fetchUsers", initial: "idle", context: { users: undefined, error: undefined, nextPage: 0, }, states: { idle: { on: { FETCH: "fetching", }, }, fetching: { invoke: { src: (context) => fetch(`url/to/users?page=${context.nextPage}`).then((response) => response.json() ), onDone: { target: "success", actions: assign({ users: (context, event) => [...context.users, ...event.data], // Data holds the newly fetched users nextPage: (context) => context.nextPage + 1, }), }, onError: { target: "failure", error: (_, event) => event.data, // Data holds the error }, }, }, // success state.. // failure state.. }, });
Während es verlockend ist, Zustandsmaschinen auf diese Weise zu schreiben, während Sie die Dinge noch zum Laufen bringen, wird eine bessere Trennung der Bedenken erreicht, indem Nebeneffekte als Optionen übergeben werden:
const services = { getUsers: (context) => fetch( `url/to/users?page=${context.nextPage}` ).then((response) => response.json()) } const fetchUsersMachine = Machine({ ... states: { ... fetching: { invoke: { // Invoke the side effect at key: 'getUsers' in the supplied services object. src: 'getUsers', } on: { RESOLVE: "success", REJECT: "failure", }, }, ... }, // Supply the side effects to be executed on state transitions. { services } });
Dies ermöglicht auch ein einfaches Komponententesten der Zustandsmaschine, wodurch explizites Mocken von Benutzerabrufen ermöglicht wird:
async function testFetchUsers() { return [{ name: "Peter", location: "New Zealand" }]; } const machine = fetchUsersMachine.withConfig({ services: { getUsers: (context) => testFetchUsers(), }, });
Aufteilen großer Maschinen
Es ist nicht immer sofort ersichtlich, wie man eine Problemdomäne zu Beginn am besten in eine gute endliche Automatenhierarchie strukturieren kann.
Tipp: Verwenden Sie die Hierarchie Ihrer UI-Komponenten, um diesen Prozess zu steuern. Im nächsten Abschnitt erfahren Sie, wie Sie Zustandsmaschinen UI-Komponenten zuordnen.
Ein großer Vorteil der Verwendung von Zustandsautomaten besteht darin, alle Zustände und Übergänge zwischen Zuständen in Ihren Anwendungen explizit zu modellieren, sodass das resultierende Verhalten klar verständlich ist und logische Fehler oder Lücken leicht zu erkennen sind.
Damit das gut funktioniert, müssen Maschinen klein und übersichtlich gehalten werden. Glücklicherweise ist das hierarchische Zusammenstellen von Zustandsmaschinen einfach. Im kanonischen Zustandsdiagramm-Beispiel eines Ampelsystems wird der „rote“ Zustand selbst zu einer untergeordneten Zustandsmaschine. Die übergeordnete „leichte“ Maschine ist sich der internen Zustände von „rot“ nicht bewusst, entscheidet aber, wann sie in „rot“ eintritt und was das beabsichtigte Verhalten beim Verlassen ist:
1-1 Zuordnung von Zustandsmaschinen zu zustandsbehafteten UI-Komponenten
Nehmen Sie zum Beispiel eine stark vereinfachte, fiktive E-Commerce-Site mit den folgenden React-Ansichten:
<App> <SigninForm /> <RegistrationForm /> <Products /> <Cart /> <Admin> <Users /> <Products /> </Admin> </App>
Der Prozess zum Generieren von Zustandsmaschinen, die den obigen Ansichten entsprechen, ist möglicherweise denjenigen bekannt, die die Redux-Zustandsverwaltungsbibliothek verwendet haben:
- Hat die Komponente einen Zustand, der modelliert werden muss? Beispielsweise darf Admin/Products nicht; Ausgelagerte Abrufe zum Server plus eine Caching-Lösung (wie SWR) können ausreichen. Andererseits enthalten Komponenten wie SignInForm oder der Warenkorb in der Regel zu verwaltende Zustände wie in Felder eingetragene Daten oder den aktuellen Warenkorbinhalt.
- Sind lokale Zustandstechniken (z. B.
setState() / useState()
von React) ausreichend, um das Problem zu erfassen? Nachzuverfolgen, ob das Warenkorb-Popup-Modal derzeit geöffnet ist, erfordert kaum die Verwendung einer Finite-State-Maschine. - Ist die resultierende Zustandsmaschine wahrscheinlich zu komplex? Wenn dies der Fall ist, teilen Sie die Maschine in mehrere kleinere auf und identifizieren Sie Möglichkeiten, untergeordnete Maschinen zu erstellen, die an anderer Stelle wiederverwendet werden können. Beispielsweise können die SignInForm- und RegistrationForm-Maschinen Instanzen einer untergeordneten textFieldMachine aufrufen, um die Validierung und den Status für Benutzer-E-Mail-, Namens- und Passwortfelder zu modellieren.
Wann ein endliches Maschinenmodell verwendet werden sollte
Während Zustandsdiagramme und FSMs einige herausfordernde Probleme elegant lösen können, hängt die Entscheidung über die besten Tools und Ansätze für eine bestimmte Anwendung normalerweise von mehreren Faktoren ab.
Einige Situationen, in denen die Verwendung von endlichen Automaten glänzt:
- Ihre Anwendung enthält eine beträchtliche Dateneingabekomponente, bei der die Zugänglichkeit oder Sichtbarkeit von Feldern von komplexen Regeln bestimmt wird: z. B. die Formulareingabe in einer App für Versicherungsansprüche. Hier tragen FSMs dazu bei, dass Geschäftsregeln robust implementiert werden. Darüber hinaus können die Visualisierungsfunktionen von Zustandsdiagrammen verwendet werden, um die Zusammenarbeit mit nicht-technischen Beteiligten zu verbessern und detaillierte Geschäftsanforderungen frühzeitig in der Entwicklung zu identifizieren.
- Um bei langsameren Verbindungen besser zu funktionieren und Benutzern ein Erlebnis mit höherer Wiedergabetreue zu bieten , müssen Web-Apps immer komplexere asynchrone Datenflüsse verwalten. FSMs modellieren explizit alle Zustände, in denen sich eine Anwendung befinden kann, und Zustandsdiagramme können visualisiert werden, um bei der Diagnose und Lösung asynchroner Datenprobleme zu helfen.
- Anwendungen, die eine Menge ausgefeilter, zustandsbasierter Animationen erfordern. Für komplexe Animationen sind Techniken zum Modellieren von Animationen als Ereignisströme durch die Zeit mit RxJS beliebt. Für viele Szenarien funktioniert dies gut, wenn jedoch umfangreiche Animationen mit einer komplexen Reihe bekannter Zustände kombiniert werden, bieten FSMs genau definierte „Ruhepunkte“, zwischen denen die Animationen fließen. FSMs in Kombination mit RxJS scheinen die perfekte Kombination zu sein, um die nächste Welle von High-Fidelity- und ausdrucksstarken Benutzererlebnissen zu liefern.
- Rich-Client-Anwendungen wie Foto- oder Videobearbeitung, Diagrammerstellungstools oder Spiele, bei denen ein Großteil der Geschäftslogik clientseitig liegt. FSMs sind von Natur aus vom UI-Framework oder den Bibliotheken entkoppelt und lassen sich leicht testen, damit qualitativ hochwertige Anwendungen schnell iteriert und sicher ausgeliefert werden können.
Vorbehalte gegen Endlich-Zustands-Maschinen
- Der allgemeine Ansatz, die Best Practices und die API für Statechart-Bibliotheken wie XState sind für die meisten Front-End-Entwickler neu, die Zeit und Ressourcen investieren müssen, um produktiv zu werden, insbesondere für weniger erfahrene Teams.
- Ähnlich wie bei der vorherigen Einschränkung, während die Popularität von XState weiter wächst und gut dokumentiert ist, haben bestehende Zustandsverwaltungsbibliotheken wie Redux, MobX oder React Context eine riesige Anhängerschaft, die eine Fülle von Online-Informationen bietet, mit denen XState noch nicht mithalten kann.
- Für Anwendungen, die einem einfacheren CRUD-Modell folgen, reichen bestehende Zustandsverwaltungstechniken in Kombination mit einer guten Ressourcen-Caching-Bibliothek wie SWR oder React Query aus. Hier können die zusätzlichen Einschränkungen, die FSM bieten, die Entwicklung verlangsamen, obwohl sie in komplexen Apps unglaublich hilfreich sind.
- Die Tools sind weniger ausgereift als andere Zustandsverwaltungsbibliotheken, und es wird noch an verbesserter TypeScript-Unterstützung und Erweiterungen für Browser-Entwicklungstools gearbeitet.
Einpacken
Die Popularität und Akzeptanz deklarativer Programmierung in der Webentwicklungs-Community nimmt weiter zu.
Während die moderne Webentwicklung immer komplexer wird, tauchen immer häufiger Bibliotheken und Frameworks auf, die deklarative Programmieransätze verwenden. Der Grund scheint klar zu sein – es müssen einfachere, aussagekräftigere Ansätze zum Schreiben von Software geschaffen werden.
Durch die Verwendung stark typisierter Sprachen wie TypeScript können Entitäten in der Anwendungsdomäne prägnant und explizit modelliert werden, wodurch die Wahrscheinlichkeit von Fehlern und die Menge an fehleranfälligem Prüfcode, der manipuliert werden muss, verringert werden. Durch den Einsatz von endlichen Zustandsautomaten und Zustandsdiagrammen im Frontend können Entwickler die Geschäftslogik einer Anwendung durch Zustandsübergänge deklarieren, was die Entwicklung umfangreicher Visualisierungstools ermöglicht und die Möglichkeiten für eine enge Zusammenarbeit mit Nicht-Entwicklern erhöht.
Dabei verlagern wir unseren Fokus von den Grundlagen der Funktionsweise der Anwendung auf eine übergeordnete Sichtweise, die es uns ermöglicht, uns noch stärker auf die Bedürfnisse des Kunden zu konzentrieren und dauerhaften Wert zu schaffen.