Hallo, Freunde. Im Vorfeld des Starts des Kurses , teilen wir traditionell mit euch die Übersetzung nützlicher Materialien.
Software löst immer mehr alltägliche Aufgaben und wird dabei immer komplizierter. Wie Marc Andreessen einmal sagte, sie erobert die Welt.

In den letzten Jahren haben sich die Ansätze zur Entwicklung und Bereitstellung von Anwendungen erheblich verändert. Es gab tektonische Verschiebungen, die letztendlich zu einem Set von Prinzipien führten. Diese Prinzipien haben sich als nützlich erwiesen bei der Bildung von Teams, dem Entwurf, der Entwicklung und der Bereitstellung eurer Anwendung an die Endbenutzer.
Die Prinzipien können wie folgt zusammengefasst werden: Die Anwendung muss klein, netzwerkfähig sein und eine entwicklerorientierte Architektur haben.Auf Grundlage dieser drei Prinzipien könnt ihr eine zuverlässige, umfassende Anwendung erstellen, die schnell und sicher an den Endbenutzer ausgeliefert werden kann und sich gleichzeitig leicht skalieren und erweitern lässt.

Jedes der vorgeschlagenen Prinzipien hat eine Reihe von Aspekten, die wir diskutieren werden, um zu zeigen, wie jedes Prinzip dazu beiträgt, das endgültige Ziel zu erreichen, nämlich die schnelle Bereitstellung zuverlässiger Anwendungen, die einfach zu warten und zu verwenden sind. Wir werden die Prinzipien im Vergleich zu ihren Gegensätzen betrachten, um zu verdeutlichen, was es bedeutet, beispielsweise „Stellen Sie sicher, dass Sie den Prinzip der Kleinheit“ verwenden.».
Wir hoffen, dass dieser Artikel euch dazu anregt, die vorgeschlagenen Prinzipien zum Aufbau moderner Anwendungen zu nutzen, die einen kohärenten Ansatz für das Design im Kontext eines kontinuierlich wachsenden Technologie-Stacks gewährleisten.
Wenn ihr diese Prinzipien anwendet, werdet ihr feststellen, dass ihr den neuesten Trends in der Softwareentwicklung folgt, einschließlich des Ansatzes zur Entwicklung und Bereitstellung von Anwendungen, der Nutzung von Containern (zum Beispiel ) und Frameworks zur Orchestrierung von Containern (zum Beispiel ), der Verwendung von Mikroservices (einschließlich der Mikroservice-Architektur und für Mikroservice-Anwendungen.
Was ist eine moderne Anwendung?
Moderne Anwendungen? Moderner Stack? Was genau bedeutet „modern“?
Die meisten Entwickler haben nur eine allgemeine Vorstellung davon, was eine moderne Anwendung ausmacht, deshalb ist es notwendig, eine klare Definition dieses Begriffs zu geben.
Moderne Anwendungen unterstützen mehrere Clients, sei es ein Benutzerinterface auf der JavaScript-Bibliothek React, eine mobile Anwendung für Android oder iOS oder eine Anwendung, die über eine API mit einer anderen verbunden ist. Eine moderne Anwendung impliziert die Existenz einer unbestimmten Anzahl von Clients, für die sie Daten oder Dienste bereitstellt.
Moderne Anwendungen bieten eine API für den Zugriff auf die angeforderten Daten und Dienste. Die API sollte unveränderlich und beständig sein und nicht speziell auf eine Anfrage eines bestimmten Clients zugeschnitten sein. Die API ist über HTTP(S) verfügbar und bietet Zugang zu allen Funktionen, die im GUI oder CLI vorhanden sind.
Daten sollten in einem gebräuchlichen, kompatiblen Format wie JSON verfügbar sein. Die API stellt Objekte und Dienste in einer verständlichen, organisierten Form bereit; beispielsweise bieten RESTful APIs oder GraphQL ein angemessenes Interface.
Moderne Anwendungen basieren auf einem modernen Stack, und ein moderner Stack ist ein solcher, der solche Anwendungen entsprechend unterstützt. Ein solcher Stack ermöglicht es Entwicklern, problemlos Anwendungen mit HTTP-Interfaces und klaren API-Endpunkten zu erstellen. Der gewählte Ansatz ermöglicht es Ihrer Anwendung, Daten einfach im JSON-Format zu empfangen und zu senden. Mit anderen Worten, ein moderner Stack entspricht den Elementen einer Twelve-Factor-Anwendung für .
Beliebte Versionen dieses Stacks basieren auf , , , , und . Mikrosservice-Architektur stellt ein Beispiel für einen modernen Stack dar, der in jeder der genannten Sprachen implementiert ist.
Bitte beachten Sie, dass wir keinen ausschließlich mikrosserviceorientierten Ansatz propagieren. Viele von Ihnen arbeiten mit Monolithen, die sich weiterentwickeln müssen, während andere mit SOA-Anwendungen umgehen, die erweitert werden, um mikrosserviceorientierte Anwendungen zu werden. Dritte bewegen sich in Richtung der Implementierung von serverlosen Anwendungen, und einige setzen Kombinationen der oben genannten um. Die in diesem Artikel dargelegten Prinzipien sind auf jede dieser Systeme anwendbar, jedoch mit einigen geringfügigen Änderungen.
Prinzipien
Jetzt, wo wir ein gemeinsames Verständnis darüber haben, was moderne Anwendungen und der moderne Stack sind, ist es an der Zeit, in die Prinzipien der Architektur und Entwicklung einzutauchen, die Ihnen in der Entwicklung, Implementierung und Wartung moderner Anwendungen gute Dienste leisten werden.
Eines der Prinzipien lautet "Erstellen Sie kleine Anwendungen"; nennen wir es einfach das Prinzip der Kleinheit. Es gibt unglaublich komplexe Anwendungen, die aus einer Vielzahl von beweglichen Komponenten bestehen. Der Aufbau einer Anwendung aus kleinen, diskreten Komponenten vereinfacht das Design, die Wartung und die Nutzung insgesamt. (Beachten Sie, dass wir "vereinfacht" und nicht "einfach gemacht" gesagt haben).
Das zweite Prinzip besagt, dass wir die Produktivität der Entwickler steigern können, indem wir ihnen helfen, sich auf die Funktionen zu konzentrieren, die sie entwickeln, während wir sie von den Sorgen um Infrastruktur und CI/CD während der Implementierung befreien. Zusammengefasst bedeutet unser Ansatz entwicklerzentriert.
Schließlich sollte alles, was mit Ihrer Anwendung zu tun hat, mit dem Netzwerk verbunden sein. In den letzten 20 Jahren haben wir erhebliche Fortschritte in Richtung einer vernetzten Zukunft gemacht, da Netzwerke schneller und Anwendungen komplexer geworden sind. Wie bereits festgestellt, sollte eine moderne Anwendung von vielen verschiedenen Clients über das Netzwerk verwendet werden. Die Anwendung des Netzwerkdenkens in der Architektur bietet erhebliche Vorteile, die gut zu das Prinzip der Kleinheit und dem konzeptionellen Ansatz passen, entwicklerzentriert.
Wenn Sie bei der Entwicklung und Implementierung einer Anwendung die genannten Prinzipien im Hinterkopf behalten, haben Sie einen unbestreitbaren Vorteil bei der Entwicklung und Lieferung Ihres Produkts.
Lassen Sie uns diese drei Prinzipien genauer betrachten.
Prinzip der Kleinheit
Es ist schwierig für das menschliche Gehirn, gleichzeitig eine große Menge an Informationen zu verarbeiten. In der Psychologie bezeichnet der Begriff kognitive Belastung die Gesamtmenge an mentalem Aufwand, die erforderlich ist, um Informationen im Gedächtnis zu behalten. Eine Verringerung der kognitiven Belastung der Entwickler hat Priorität, da sie sich so auf die Problemlösung konzentrieren können, anstatt das aktuelle komplexe Modell der gesamten Anwendung und der entwickelten Funktionen im Kopf zu behalten.

Anwendungen werden aus folgenden Gründen dekomponiert:
- Verringerung der kognitiven Belastung der Entwickler;
- Beschleunigung und Vereinfachung der Tests;
- Schnelle Bereitstellung von Änderungen in der Anwendung.
Es gibt mehrere Möglichkeiten, die kognitive Belastung der Entwickler zu reduzieren, und hier kommt das Prinzip der Kleinheit ins Spiel.
Also, drei Möglichkeiten, die kognitive Belastung zu senken:
- Die Zeitrahmen reduzieren, die sie bei der Entwicklung einer neuen Funktion berücksichtigen müssen – je kürzer der Zeitrahmen, desto geringer die kognitive Belastung.
- Die Menge an Code reduzieren, an dem gleichzeitig gearbeitet wird – weniger Code – weniger Belastung.
- Den Prozess der inkrementellen Änderungen an der Anwendung vereinfachen.
Reduzierung der Entwicklungszeiträume
Lassen Sie uns in die Zeiten zurückkehren, als die Methodik Wasserfall der Standard für den Entwicklungsprozess war und Zeitrahmen von sechs Monaten bis zwei Jahren für die Entwicklung oder Aktualisierung einer Anwendung verbreitete Praxis waren. In der Regel lasen Ingenieure zuerst die entsprechenden Dokumente wie die Produktanforderungen (PRD), das Systemreferenzdokument (SRD), den Architekturplan und begannen, all diese Dinge in ein kognitives Modell zusammenzuführen, gemäß dem sie den Code schrieben. Als sich die Anforderungen und damit die Architektur änderten, mussten große Anstrengungen unternommen werden, um das gesamte Team über die Aktualisierungen des kognitiven Modells zu informieren. Ein solcher Ansatz konnte im schlimmsten Fall die Arbeit einfach lähmen.
Die größte Veränderung im Prozess der Anwendungsentwicklung war die Einführung der Methodik Agile. Eine der Hauptmerkmale der Methodik Agil ist die iterative Entwicklung. Dies führt wiederum zu einer Verringerung der kognitiven Belastung der Ingenieure. Anstatt von der Entwicklerteam zu verlangen, die Anwendung in einem langen Zyklus zu realisieren, Agil ermöglicht dieser Ansatz, sich auf kleine Codeabschnitte zu konzentrieren, die schnell getestet und bereitgestellt werden können, wobei gleichzeitig auch Rückmeldungen eingeholt werden. Die kognitive Belastung der Anwendung hat sich von einem Zeitrahmen von sechs Monaten bis zwei Jahren mit einer großen Menge an Spezifikationen auf zweiwöchige Funktionen oder Änderungen verschoben, die auf ein verschwommenes Verständnis eines großen Projekts ausgerichtet sind.
Die Verschiebung des Fokus von umfangreichen Anwendungen hin zu konkreten kleinen Funktionen, die in einem zweiwöchigen Sprint abgeschlossen werden können, mit einem Blick in die Zukunft, der nicht mehr als eine Funktion aus dem nächsten Sprint umfasst, stellt einen bedeutenden Wandel dar. Dies hat die Produktivität der Entwicklung gesteigert und gleichzeitig die kognitive Belastung reduziert, die ständig schwankte.
In der Methodik Agil wird davon ausgegangen, dass die endgültige Anwendung eine etwas veränderte Version des ursprünglichen Konzepts sein wird, weshalb der endgültige Entwicklungsstand unbedingt mehrdeutig ist. Nur die Ergebnisse jedes einzelnen Sprints können klar und eindeutig sein.
Kleine Codebasen
Der nächste Schritt zur Verringerung der kognitiven Belastung besteht darin, die Codebasis zu verkleinern. Modern Anwendungen sind in der Regel umfangreich – eine zuverlässige, unternehmensweite Anwendung kann aus Tausenden von Dateien und Hunderttausenden von Codezeilen bestehen. Je nach Organisation der Dateien können die Verbindungen und Abhängigkeiten zwischen dem Code und den Dateien offensichtlich oder umgekehrt sein. Selbst das Debuggen der Ausführung des Codes kann Probleme verursachen, je nachdem, welche Bibliotheken verwendet werden und wie gut die Debugging-Tools zwischen Bibliotheken/Paketen/Modulen und benutzerdefiniertem Code unterscheiden.
Der Aufbau eines funktionierenden mentalen Modells des Codes einer Anwendung kann erheblich Zeit in Anspruch nehmen und erneut eine hohe kognitive Belastung für die Entwickler mit sich bringen. Dies ist besonders typisch für monolithische Codebasen, in denen eine große Menge an Code vorhanden ist, dessen Interaktionen zwischen den funktionalen Komponenten nicht klar definiert sind und die Trennung der Aufmerksamkeitsobjekte oft verschwommen ist, da die funktionalen Grenzen nicht eingehalten werden.
Eine effektive Möglichkeit, die kognitive Belastung für Ingenieure zu reduzieren, besteht darin, auf eine Microservices-Architektur umzusteigen. Im Microservices-Ansatz konzentriert sich jeder Dienst auf einen bestimmten Funktionsbereich; dabei ist der Sinn des Dienstes in der Regel klar und verständlich definiert. Die Grenzen des Dienstes sind ebenfalls klar – erinnern Sie sich daran, dass die Kommunikation mit dem Dienst über APIs erfolgt, sodass Daten, die von einem Dienst erzeugt werden, leicht an einen anderen übergeben werden können.
Die Interaktion mit anderen Diensten ist normalerweise auf einige Benutzer- und Anbieter-Dienste beschränkt, die einfache und klare API-Aufrufe nutzen, beispielsweise über REST. Das heißt, die kognitive Last für den Ingenieur wird erheblich reduziert. Die größte Herausforderung bleibt das Verständnis des Modells der Interaktion zwischen den Diensten und wie Dinge wie Transaktionen in mehreren Diensten ablaufen. Insgesamt verringert die Nutzung von Mikrodiensten die kognitive Belastung, indem sie die Menge an Code reduziert, klare Servicegrenzen festlegt und das Verständnis der Beziehungen zwischen Benutzern und Anbietern fördert.
Kleine inkrementelle Änderungen
Das letzte Element des Prinzips Kleinigkeit – ist das Management von Änderungen. Ein besonderes Verlangen für Entwickler ist es, sich den Code anzuzeigen ( vielleicht sogar ihren eigenen, älteren Code) und zu sagen: „Das ist Mist, wir müssen alles neu schreiben.“ Manchmal ist das die richtige Entscheidung, manchmal nicht. Es legt das Gewicht eines globalen Änderungsmodells auf das Team der Entwickler, was wiederum zu einer erheblichen kognitiven Belastung führt. Es ist besser, wenn Ingenieure sich auf die Änderungen konzentrieren, die sie während eines Sprints umsetzen können, um dann pünktlich die benötigte Funktionalität bereitstellen zu können, auch wenn dies schrittweise geschieht. Das Endprodukt sollte dem geplanten entsprechen, jedoch mit einigen Änderungen und Tests, um den Anforderungen des Kunden gerecht zu werden.
Beim Umschreiben großer Codeabschnitte kann es manchmal unmöglich sein, Änderungen schnell bereitzustellen, da dabei andere Abhängigkeiten des Systems ins Spiel kommen. Um den Fluss der Änderungen zu kontrollieren, kann das Deaktivieren von Funktionen (Feature-Hiding) verwendet werden. Im Grunde bedeutet das, dass eine Funktion in der Produktion vorhanden ist, aber über Umgebungsvariablen (env-var) oder irgendeinen anderen Konfigurationsmechanismus nicht verfügbar ist. Wenn der Code alle Qualitätssicherungsprozesse durchlaufen hat, kann er versteckt in der Produktion landen. Diese Strategie funktioniert jedoch nur, wenn die Funktion letztendlich aktiviert wird. Andernfalls wird sie nur den Code überladen und die kognitive Belastung erhöhen, mit der der Entwickler für produktives Arbeiten umgehen muss. Das Management von Änderungen und inkrementelle Änderungen helfen von sich aus, die kognitive Belastung der Entwickler auf einem angemessenen Niveau zu halten.
Ingenieuren begegnen viele Herausforderungen selbst bei der einfachen Implementierung zusätzlicher Funktionen. Von der Führungsebene wäre es sinnvoll, die zusätzliche Belastung des Teams zu verringern, damit es sich auf die Schlüsselfunktionen konzentrieren kann. Es gibt drei Dinge, die Sie tun können, um Ihrem Entwicklungsteam zu helfen:
- Die Methodik nutzen
Agil, um den Zeitrahmen zu begrenzen, in dem sich das Team auf die wesentlichen Funktionen konzentrieren muss. - Ihre Anwendung als mehrere Mikrodienste implementieren. Dies wird die Anzahl der implementierten Funktionen begrenzen und die Grenzen stärken, die die kognitive Belastung während der Arbeit aufrechterhalten.
- Bevorzugen Sie inkrementelle Änderungen gegenüber großen und klobigen, und ändern Sie kleine Codeabschnitte. Verwenden Sie Features-Hiding, um Änderungen umzusetzen, selbst wenn sie nach der Hinzufügung nicht sofort sichtbar sind.
Wenn Sie in Ihrer Arbeit das Prinzip der Kleinheit anwenden, wird Ihr Team viel glücklicher, besser auf die Umsetzung der notwendigen Funktionen fokussieren und mit größerer Wahrscheinlichkeit schneller qualitativ hochwertige Änderungen umsetzen. Aber das bedeutet nicht, dass die Arbeit nicht komplexer werden kann; manchmal erfordert die Implementierung neuer Funktionen die Modifizierung mehrerer Services, und dieser Prozess kann komplizierter sein als der entsprechende in einer monolithischen Architektur. In jedem Fall sind die Vorteile des Ansatzes der Kleinheit die Mühe wert.
Ende des ersten Teils.
In Kürze werden wir den zweiten Teil der Übersetzung veröffentlichen, und jetzt freuen wir uns auf Ihre Kommentare und laden Sie zu , der heute um 20:00 Uhr stattfinden wird.
Quelle: habr.com
