Prinzipien zur Entwicklung moderner Anwendungen aus NGINX. Teil 1

Hallo Freunde. Im Vorgriff auf den Start des Kurses „Backend PHP Developer“ teilen wir Ihnen traditionell die Übersetzung nützlichen Materials mit.

Die Software löst immer mehr alltägliche Aufgaben und wird dabei immer schwieriger. Wie Mark Andressen einmal sagte, verschluckt es die Welt.



Infolgedessen haben sich die Ansätze für die Entwicklung und Bereitstellung von Anwendungen in den letzten Jahren dramatisch verändert. Dies waren Verschiebungen einer tektonischen Skala, die zur Entstehung einer Reihe von Prinzipien führten. Diese Prinzipien haben sich bei der Teambildung, dem Design, der Entwicklung und der Bereitstellung Ihrer Anwendung für Endbenutzer als nützlich erwiesen.

Die Prinzipien lassen sich wie folgt zusammenfassen: Die Anwendung sollte klein, vernetzt und entwicklerorientiert sein . Basierend auf diesen drei Prinzipien können Sie eine zuverlässige, umfassende Anwendung erstellen, die schnell und sicher an den Endbenutzer geliefert und einfach skaliert und erweitert werden kann.



Jedes der vorgeschlagenen Prinzipien hat eine Reihe von Aspekten, die wir diskutieren werden, um zu zeigen, wie jedes Prinzip zur Erreichung des Endziels beiträgt, 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 klären, was es bedeutet: "Stellen Sie sicher, dass Sie das Prinzip der Kleinheit anwenden ."

Wir hoffen, dass dieser Artikel Sie dazu ermutigt, die vorgeschlagenen Prinzipien für die Erstellung moderner Anwendungen zu verwenden, die einen einheitlichen Ansatz für das Design im Kontext eines ständig wachsenden Technologie-Stacks bieten.

Wenn Sie diese Prinzipien anwenden, werden Sie die neuesten Softwareentwicklungstrends nutzen, einschließlich des DevOps- Ansatzes für die Entwicklung und Bereitstellung von Anwendungen unter Verwendung von Containern (wie Docker ) und Frameworks für die Container-Orchestrierung (wie Kubernetes ) unter Verwendung von Microservices (einschließlich NGINX Microservice Architecture). und Netzwerkkommunikationsarchitektur für Microservice-Anwendungen.

Was ist eine moderne Anwendung?

Moderne Anwendungen? Moderner Stapel? Was genau bedeutet "modern"?

Die meisten Entwickler haben nur eine allgemeine Vorstellung davon, woraus eine moderne Anwendung besteht. Daher müssen Sie dieses Konzept klar definieren.

Eine moderne Anwendung unterstützt mehrere Clients, sei es eine Benutzeroberfläche in der JavaScript React-Bibliothek, eine mobile Anwendung für Android oder iOS oder eine Anwendung, die über die API eine Verbindung zu einer anderen herstellt. Eine moderne Anwendung impliziert die Anwesenheit einer unbestimmten Anzahl von Kunden, für die sie Daten oder Dienste bereitstellt.

Eine moderne Anwendung bietet eine API für den Zugriff auf die angeforderten Daten und Dienste. Die API sollte unveränderlich und konstant sein und nicht speziell für eine bestimmte Anforderung eines bestimmten Clients geschrieben werden. Die API ist über HTTP (S) zugänglich und bietet Zugriff auf alle Funktionen der GUI oder CLI.

Auf Daten muss in einem allgemein akzeptierten, kompatiblen Format wie JSON zugegriffen werden können. Die API bietet Objekte und Dienste auf übersichtliche, organisierte Weise. Beispielsweise bietet die RESTful-API oder GraphQL eine anständige Schnittstelle.

Moderne Anwendungen bauen auf einem modernen Stapel auf, und ein moderner Stapel ist der Stapel, der solche Anwendungen unterstützt. Mit einem solchen Stapel kann der Entwickler auf einfache Weise eine Anwendung mit einer HTTP-Schnittstelle erstellen und API-Endpunkte löschen. Mit dem gewählten Ansatz kann Ihre Anwendung problemlos Daten im JSON-Format empfangen und senden. Mit anderen Worten, der moderne Stapel entspricht den Elementen der Zwölf-Faktoren-Anwendung für Mikrodienste .

Beliebte Versionen dieses Stapeltyps basieren auf Java , Python , Node , Ruby , PHP und Go . Die NGINX Microservice Architecture ist ein Beispiel für einen modernen Stack, der in jeder der genannten Sprachen implementiert ist.

Bitte beachten Sie, dass wir nicht ausschließlich einen Microservice-Ansatz befürworten. Viele von Ihnen arbeiten mit Monolithen, die sich weiterentwickeln müssen, während andere sich mit SOA-Anwendungen befassen, die sich zu Mikroservice-Anwendungen erweitern und weiterentwickeln. Wieder andere bewegen sich in Richtung serverloser Anwendungen, und einige führen Kombinationen der oben genannten ein. Die im Artikel dargelegten Grundsätze gelten mit nur wenigen geringfügigen Änderungen für jedes dieser Systeme.

Prinzipien

Nachdem wir ein gemeinsames Verständnis für eine moderne Anwendung und einen modernen Stack haben, ist es an der Zeit, sich mit den Prinzipien der Architektur und Entwicklung zu befassen, die Ihnen bei der Entwicklung, Implementierung und Unterstützung einer modernen Anwendung gute Dienste leisten.

Eines der Prinzipien ist „kleine Anwendungen erstellen“. Nennen wir es einfach das Prinzip der Kleinheit . Es gibt unglaublich komplexe Anwendungen, die aus einer großen Anzahl beweglicher Komponenten bestehen. Das Erstellen einer Anwendung aus kleinen diskreten Komponenten vereinfacht wiederum das Design, die Wartung und die Arbeit damit insgesamt. (Beachten Sie, wir sagten "vereinfacht", nicht "macht es einfach".)

Das zweite Prinzip ist, dass wir die Produktivität von Entwicklern steigern können, indem wir ihnen helfen, sich auf die von ihnen entwickelten Funktionen zu konzentrieren, und sie gleichzeitig von Sorgen um die Infrastruktur und CI / CD während der Implementierung befreien. Kurz gesagt, unser Ansatz konzentriert sich auf Entwickler .

Schließlich sollte alles an Ihrer Anwendung mit dem Netzwerk verbunden sein. In den letzten 20 Jahren haben wir große Fortschritte in Richtung einer vernetzten Zukunft gemacht, da Netzwerke schneller und Anwendungen komplexer sind. Wie wir bereits herausgefunden haben, sollte eine moderne Anwendung von vielen verschiedenen Clients über das Netzwerk verwendet werden. Die Verwendung des Netzwerkdenkens in der Architektur hat erhebliche Vorteile, die gut zum Prinzip der Kleinheit und zum Konzept eines entwicklerorientierten Ansatzes passen.

Wenn Sie sich während der Entwicklung und Implementierung der Anwendung an diese Grundsätze erinnern, haben Sie einen unbestreitbaren Vorteil bei der Entwicklung und Lieferung Ihres Produkts.

Schauen wir uns diese drei Prinzipien genauer an.

Prinzip der Kleinheit

Für das menschliche Gehirn ist es schwierig, gleichzeitig eine große Menge an Informationen wahrzunehmen. In der Psychologie bedeutet der Begriff kognitive Belastung die Gesamtmenge an geistiger Anstrengung, die erforderlich ist, um Informationen im Gedächtnis zu speichern. Die Reduzierung der kognitiven Belastung der Entwickler hat Priorität, da sie sich in diesem Fall auf die Lösung des Problems konzentrieren können, anstatt das derzeitige komplexe Modell der gesamten Anwendung und die zu entwickelnden Funktionen zu berücksichtigen.



Anwendungen werden aus folgenden Gründen zerlegt:

  • Verringerung der kognitiven Belastung der Entwickler;
  • Beschleunigen und vereinfachen Sie das Testen.
  • Schnelle Übermittlung von Änderungen in der Anwendung.

Es gibt verschiedene Möglichkeiten, die kognitive Belastung der Entwickler zu verringern, und hier kommt das Prinzip der Kleinheit ins Spiel.

Es gibt also drei Möglichkeiten, die kognitive Belastung zu senken:

  1. Reduzieren Sie den Zeitrahmen, den sie bei der Entwicklung einer neuen Funktion berücksichtigen sollten - je kürzer der Zeitrahmen, desto geringer die kognitive Belastung.
  2. Reduzieren Sie die Menge an Code, an der einmalige Arbeiten ausgeführt werden - weniger Code - weniger Last.
  3. Vereinfachen Sie das Vornehmen inkrementeller Änderungen an der Anwendung.

Reduzieren Sie die Entwicklungszeiten

Kehren wir zu den Tagen zurück, als die waterfall der Standard für den Entwicklungsprozess war und der Zeitrahmen von sechs Monaten bis zwei Jahren für die Entwicklung oder Aktualisierung der Anwendung gängige Praxis war. In der Regel lesen die Ingenieure zuerst die relevanten Dokumente wie Produktanforderungen (PRD), Systemreferenzdokument (SRD) und Architekturplan und beginnen, all diese Dinge zu einem kognitiven Modell zusammenzufassen, nach dem sie den Code geschrieben haben. Da sich die Anforderungen und dementsprechend die Architektur änderten, mussten ernsthafte Anstrengungen unternommen werden, um das gesamte Team über Aktualisierungen des kognitiven Modells zu informieren. Im schlimmsten Fall könnte ein solcher Ansatz die Arbeit einfach lähmen.

Die größte Änderung im Anwendungsentwicklungsprozess war die Einführung der agilen Methodik. Eines der Hauptmerkmale der agile Methodik ist die iterative Entwicklung. Dies führt wiederum zu einer Verringerung der kognitiven Belastung der Ingenieure. Anstatt dass das Entwicklungsteam die Anwendung in einem langen Zyklus implementieren muss, können Sie sich mit dem agile Ansatz auf kleine Codemengen konzentrieren, die schnell getestet und bereitgestellt werden können, und gleichzeitig Feedback erhalten. Die kognitive Belastung der Anwendung hat sich vom Zeitrahmen von sechs Monaten auf zwei Jahre verschoben, unter Berücksichtigung der Vielzahl von Spezifikationen für eine zweiwöchige Ergänzung oder Funktionsänderung, die auf ein vageres Verständnis einer großen Anwendung abzielen.

Die Verlagerung des Fokus von einer massiven Anwendung auf bestimmte kleine Funktionen, die in einem zweiwöchigen Sprint ausgeführt werden können, mit Blick auf nicht mehr als eine Funktion vom nächsten Sprint im Kopf, ist eine bedeutende Änderung. Dies ermöglichte es uns, die Produktivität der Entwicklung zu steigern und gleichzeitig die kognitive Belastung zu reduzieren, die ständig schwankte.

Die agile Methodik geht davon aus, dass die endgültige Anwendung eine leicht modifizierte Version des ursprünglichen Konzepts ist, sodass der endgültige Entwicklungspunkt notwendigerweise nicht eindeutig ist. Nur die Ergebnisse jedes einzelnen Sprints können klar und präzise sein.

Kleine Codebasen

Der nächste Schritt zur Reduzierung der kognitiven Belastung besteht darin, die Codebasis zu reduzieren. Moderne Anwendungen sind in der Regel riesig - eine zuverlässige Unternehmensanwendung kann aus Tausenden von Dateien und Hunderttausenden von Codezeilen bestehen. Abhängig von der Organisation der Kommunikationsdateien und den Abhängigkeiten des Codes und der Dateien können sie offensichtlich sein oder umgekehrt. Selbst das Debuggen des Codes selbst kann Probleme verursachen, abhängig von den verwendeten Bibliotheken und davon, wie gut die Debugging-Tools zwischen Bibliotheken / Paketen / Modulen und Benutzercode unterscheiden.

Das Erstellen eines funktionierenden mentalen Modells des Anwendungscodes kann beeindruckend viel Zeit in Anspruch nehmen und den Entwickler erneut stark kognitiv belasten. Dies gilt insbesondere für monolithische Codebasen, bei denen eine große Menge an Code vorhanden ist, deren Wechselwirkung zwischen den Funktionskomponenten nicht klar definiert ist und deren Trennung von Aufmerksamkeitsobjekten häufig unscharf ist, da die Funktionsgrenzen nicht eingehalten werden.

Eine der effektiven Möglichkeiten, die kognitive Belastung von Ingenieuren zu verringern, ist der Übergang zu einer Microservice-Architektur. Beim Microservice-Ansatz konzentriert sich jeder Service auf einen Satz von Funktionen. Die Bedeutung des Dienstes ist normalerweise definiert und verständlich. Die Grenzen des Dienstes sind ebenfalls klar. Denken Sie daran, dass die Kommunikation mit dem Dienst über die API erfolgt, sodass die von einem Dienst generierten Daten problemlos auf einen anderen übertragen werden können.

Die Interaktion mit anderen Diensten ist normalerweise auf mehrere Benutzerdienste und mehrere Anbieterdienste beschränkt, die einfache und saubere API-Aufrufe verwenden, z. B. REST. Dies bedeutet, dass die kognitive Belastung des Ingenieurs erheblich reduziert wird. Die schwierigste Aufgabe besteht darin, das Modell der Interaktion zwischen Diensten zu verstehen und zu verstehen, wie beispielsweise Transaktionen in mehreren Diensten ablaufen. Infolgedessen reduziert die Verwendung von Microservices die kognitive Belastung, reduziert die Codemenge, zeigt klare Grenzen des Dienstes auf und vermittelt ein Verständnis der Beziehung zwischen Benutzern und Anbietern.

Kleine inkrementelle Änderungen

Das letzte Element des Prinzips der Kleinheit ist das Änderungsmanagement. Es ist eine besondere Versuchung für Entwickler, sich die Codebasis (vielleicht sogar ihren eigenen, älteren Code) anzusehen und zu sagen: "Das ist Mist, wir müssen alles neu schreiben." Manchmal ist dies die richtige Entscheidung und manchmal nicht. Dies belastet das Entwicklungsteam mit globalen Modelländerungen, was wiederum zu einer massiven kognitiven Belastung führt. Für Ingenieure ist es besser, sich auf die Änderungen zu konzentrieren, die sie während des Sprints vornehmen können, um die erforderlichen Funktionen später, wenn auch schrittweise, rechtzeitig einzuführen. Das Endprodukt sollte an ein vorgeplantes erinnern, jedoch mit einigen Modifikationen und Tests, um den Kundenanforderungen gerecht zu werden.

Beim Umschreiben großer Teile des Codes ist es manchmal unmöglich, Änderungen schnell zu liefern, da hier andere Systemabhängigkeiten ins Spiel kommen. Um den Änderungsfluss zu steuern, können Sie die Funktion zum Ausblenden verwenden. Im Prinzip bedeutet dies, dass die Funktionalität in Produktion ist, jedoch nicht über die Einstellungen von Umgebungsvariablen (env-var) oder einen anderen Konfigurationsmechanismus verfügbar ist. Wenn der Code alle Qualitätskontrollprozesse bestanden hat, befindet er sich möglicherweise in einem verborgenen Zustand in der Produktion. Diese Strategie funktioniert jedoch nur, wenn die Funktion letztendlich aktiviert ist. Andernfalls wird nur der Code verschmutzt und die kognitive Belastung erhöht, mit der der Entwickler für produktive Arbeit fertig werden muss. Änderungsmanagement und inkrementelle Änderungen an und für sich tragen dazu bei, die kognitive Belastung der Entwickler auf einem erschwinglichen Niveau zu halten.

Ingenieure müssen selbst mit der einfachen Implementierung zusätzlicher Funktionen viele Schwierigkeiten überwinden. Seitens des Managements wäre es sinnvoll, die zusätzliche Belastung des Teams zu reduzieren, damit es sich auf die Schlüsselelemente der Funktion konzentrieren kann. Sie können Ihrem Entwicklungsteam drei Dinge helfen:

  1. Verwenden Sie eine agile Methode, um den Zeitrahmen zu begrenzen, innerhalb dessen sich ein Team auf Schlüsselfunktionen konzentrieren sollte.
  2. Implementieren Sie Ihre Anwendung als mehrere Microservices. Dies begrenzt die Anzahl der implementierten Funktionen und stärkt die Grenzen, die die kognitive Belastung während der Arbeit halten.
  3. Bevorzugen Sie inkrementelle Änderungen gegenüber großen und sperrigen, ändern Sie kleine Codeteile. Verwenden Sie das Ausblenden von Funktionen, um Änderungen zu implementieren, auch wenn sie nicht unmittelbar nach dem Hinzufügen sichtbar sind.

Wenn Sie das Prinzip der Kleinheit in Ihrer Arbeit anwenden, wird Ihr Team viel glücklicher, konzentriert sich besser auf die Implementierung der erforderlichen Funktionen und führt mit größerer Wahrscheinlichkeit qualitative Änderungen schneller durch. Dies bedeutet jedoch nicht, dass die Arbeit nicht kompliziert sein kann, manchmal im Gegenteil, die Einführung neuer Funktionen erfordert die Modifikation mehrerer Dienste, und dieser Prozess kann komplizierter sein als der ähnliche in einer monolithischen Architektur. In jedem Fall lohnen sich die Vorteile eines kleinen Ansatzes.

Das Ende des ersten Teils.

In Kürze werden wir den zweiten Teil der Übersetzung veröffentlichen. Jetzt warten wir auf Ihre Kommentare und laden Sie zum Tag der offenen Tür ein , der heute um 20.00 Uhr stattfindet.

Source: https://habr.com/ru/post/de452748/


All Articles