So trennen Sie Frontend und Backend unter Wahrung des gegenseitigen Verständnisses

Bild


Wie kann die Architektur eines monolithischen Produkts geändert werden, um seine Entwicklung zu beschleunigen, und wie kann ein Team in mehrere aufgeteilt werden, während die Arbeitskonsistenz erhalten bleibt? Für uns war die Antwort auf diese Fragen die Erstellung einer neuen API. Unter dem Schnitt finden Sie eine detaillierte Geschichte über den Weg zu einer solchen Lösung und einen Überblick über die ausgewählten Technologien, aber zunächst einmal - einen kleinen Exkurs.


Vor einigen Jahren habe ich in einem wissenschaftlichen Artikel gelesen, dass immer mehr Zeit für eine vollwertige Ausbildung benötigt wird, und in naher Zukunft wird es achtzig Jahre dauern, um Wissen zu erlangen. Anscheinend ist diese Zukunft in der IT bereits gekommen.


Ich hatte das Glück, in jenen Jahren mit dem Programmieren zu beginnen, in denen es keine Trennung zwischen Backend- und Frontend-Programmierern gab, als die Wörter „Prototyp“, „Produktingenieur“, „UX“ und „Qualitätssicherung“ nicht klangen. Die Welt war einfacher, die Bäume waren höher und grüner, die Luft war sauberer und Kinder spielten auf den Höfen, anstatt Autos zu parken. Egal wie ich zu dieser Zeit zurückkehren möchte, ich muss zugeben, dass dies alles nicht die Absicht des Superschurken ist, sondern die evolutionäre Entwicklung der Gesellschaft. Ja, die Gesellschaft könnte sich anders entwickeln, aber wie Sie wissen, toleriert die Geschichte die Konjunktivstimmung nicht.


Hintergrund


BILLmanager erschien gerade zu einer Zeit, als es keine starre Richtungstrennung gab. Es hatte eine kohärente Architektur, konnte das Benutzerverhalten steuern und sogar mit Plugins erweitert werden. Die Zeit verging, das Team entwickelte das Produkt und alles schien in Ordnung zu sein, aber es wurden merkwürdige Phänomene beobachtet. Wenn sich ein Programmierer beispielsweise mit Geschäftslogik beschäftigte, begann er, Formulare schlecht zu erstellen, was sie unpraktisch und schwer verständlich machte. Oder das Hinzufügen einer scheinbar einfachen Funktionalität dauerte mehrere Wochen: Architektonisch waren die Module eng miteinander verbunden, sodass beim Ändern eines Moduls das andere angepasst werden musste.


Komfort, Ergonomie und globale Produktentwicklung im Allgemeinen können vergessen werden, wenn die Anwendung mit einem unbekannten Fehler abstürzt. Wenn es einem Programmierer früher gelang, in verschiedene Richtungen zu arbeiten, wurde dies mit dem Wachstum des Produkts und den Anforderungen dafür unmöglich. Der Entwickler hat das ganze Bild gesehen und verstanden, dass die Formulare, Schaltflächen, Tests und Werbung nicht helfen, wenn die Funktion nicht richtig und stabil funktioniert. Deshalb verschob er alles und setzte sich, um den unglücklichen Fehler zu korrigieren. Er machte seine kleine Leistung, die von niemandem geschätzt wurde (es gab einfach keine Kraft mehr für die korrekte Lieferung an den Kunden), aber die Funktion begann zu funktionieren. Damit diese kleinen Leistungen die Kunden erreichen, wird das Team Personen umfassen, die für verschiedene Bereiche verantwortlich sind: Frontend und Backend, Testen, Design, Support, Werbung.


Das war aber nur der erste Schritt. Das Team hat sich verändert und die Architektur des Produkts ist technisch stark verwandt geblieben. Aus diesem Grund war es nicht möglich, die Anwendung im erforderlichen Tempo zu entwickeln. Beim Ändern der Schnittstelle musste die Backend-Logik geändert werden, obwohl die Struktur der Daten selbst häufig unverändert blieb. Mit all dem musste etwas getan werden.


Frontend und Backend


In allem professionell zu werden ist lang und teuer, daher ist die moderne Welt der angewandten Programmierer größtenteils in ein Front-End und ein Back-End unterteilt.


Hier scheint alles klar zu sein: Wir rekrutieren Front-End-Programmierer, sie werden für die Benutzeroberfläche verantwortlich sein, und das Backend kann sich endlich auf Geschäftslogik, Datenmodelle und andere Motorhauben konzentrieren. Gleichzeitig bleiben Backend, Frontend, Tester und Designer in einem Team (da sie ein gemeinsames Produkt herstellen, konzentrieren sie sich nur auf verschiedene Teile davon). In einem Team zu sein bedeutet, einen Informations- und vorzugsweise einen territorialen Raum zu haben. Besprechen Sie gemeinsam neue Funktionen und zerlegen Sie die fertigen. koordinieren Sie die Arbeit an einer großen Aufgabe.


Für ein abstraktes neues Projekt wird dies ausreichen, aber wir hatten den Antrag bereits geschrieben, und der Umfang der geplanten Arbeit und der Zeitpunkt ihrer Umsetzung zeigten deutlich, dass ein Team dies nicht tun konnte. Es gibt fünf Leute in der Basketballmannschaft, elf in der Fußballmannschaft, und wir hatten ungefähr 30. Dies passte nicht zum perfekten Scrum-Team von fünf bis neun Leuten. Es war notwendig zu teilen, aber wie kann man die Kohärenz aufrechterhalten? Um sich zu bewegen, mussten die architektonischen und organisatorischen Probleme gelöst werden.


Bild
"Wir werden alles in einem Projekt erledigen, es wird bequemer sein", sagten sie ...


Architektur


Wenn ein Produkt veraltet ist, erscheint es logisch, es aufzugeben und ein neues zu schreiben. Dies ist eine gute Entscheidung, wenn Sie die Zeit vorhersagen können und sie für jeden geeignet ist. Aber in unserem Fall würde die Entwicklung eines neuen Produkts selbst unter idealen Bedingungen Jahre dauern. Darüber hinaus sind die Besonderheiten der Anwendung so, dass es äußerst schwierig wäre, mit vollem Unterschied vom alten zum neuen zu wechseln. Die Abwärtskompatibilität ist für unsere Kunden sehr wichtig. Wenn sie nicht vorhanden ist, lehnen sie ein Upgrade auf die neue Version ab. Die Machbarkeit einer Neuentwicklung ist in diesem Fall zweifelhaft. Aus diesem Grund haben wir uns entschlossen, die Architektur des vorhandenen Produkts unter Beibehaltung der maximalen Abwärtskompatibilität zu aktualisieren.


Unsere Anwendung ist ein Monolith, dessen Schnittstelle auf der Serverseite erstellt wurde. Das Frontend hat nur die von ihm erhaltenen Anweisungen implementiert. Mit anderen Worten, das Backend war nicht für die Benutzeroberfläche verantwortlich . Architektonisch funktionierten das Front-End und das Back-End als eines, daher waren wir gezwungen, das andere zu ändern, da wir eines wechselten. Und das ist nicht das Schlimmste, was viel schlimmer ist - es war unmöglich, eine Benutzeroberfläche zu entwickeln, ohne genau zu wissen, was auf dem Server passiert.


Das Front-End und das Back-End mussten getrennt werden, um separate Softwareanwendungen zu erstellen. Die einzige Möglichkeit, mit der Entwicklung zu beginnen, bestand in der erforderlichen Geschwindigkeit und Lautstärke. Aber wie kann man zwei Projekte parallel durchführen und ihre Struktur ändern, wenn sie stark voneinander abhängig sind?


Die Lösung war ein zusätzliches System - eine Schicht . Die Idee der Zwischenschicht ist äußerst einfach: Sie muss die Arbeit des Backends und des Frontends koordinieren und alle zusätzlichen Kosten übernehmen. Wenn beispielsweise die Zahlungsfunktion auf der Backend-Seite zerlegt wird, kombiniert die Ebene Daten, und auf der Frontend-Seite muss nichts geändert werden. oder damit wir für den Abschluss aller vom Benutzer bestellten Dienste im Dashboard keine zusätzliche Funktion im Backend ausführen, sondern die Daten in der Ebene aggregieren.


Darüber hinaus sollte die Ebene die Sicherheit erhöhen, was vom Server aufgerufen werden kann und was schließlich zurückkehren wird. Ich wollte, dass die Anforderung von Operationen möglich ist, ohne die interne Struktur der Funktionen zu kennen, die sie ausführen.


Bild
Erhöhte Stabilität durch Aufteilung der Verantwortungsbereiche.


Kommunikation


Aufgrund der starken Abhängigkeit zwischen Frontend und Backend war es unmöglich, die Arbeit parallel zu erledigen, was beide Teile des Teams verlangsamte. Durch die programmatische Aufteilung eines großen Projekts in mehrere haben wir in jedem Projekt Handlungsspielraum, aber gleichzeitig mussten wir die Konsistenz in der Arbeit aufrechterhalten.


Jemand wird sagen, dass Konsistenz durch die Verbesserung von Soft Skills erreicht wird. Ja, sie müssen entwickelt werden, aber dies ist kein Allheilmittel. Schauen Sie sich den Verkehr an, es ist auch wichtig, dass die Fahrer höflich sind, wissen, wie man zufällige Hindernisse vermeidet und sich in schwierigen Situationen gegenseitig helfen. Aber! Ohne Verkehrsregeln hätten wir selbst bei bester Kommunikation Unfälle an jeder Kreuzung und das Risiko, den Ort nicht rechtzeitig zu erreichen.


Wir brauchten Regeln, die schwer zu brechen wären. Wie sie sagen, um es einfacher zu machen, zu befolgen als zu verletzen. Die Umsetzung von Gesetzen bringt jedoch nicht nur Vorteile, sondern auch Gemeinkosten mit sich, und wir wollten die Hauptarbeit wirklich nicht verlangsamen und alle in den Prozess einbeziehen. Aus diesem Grund haben wir eine Koordinierungsgruppe und anschließend ein Team gebildet, dessen Ziel es war, die Voraussetzungen für die erfolgreiche Entwicklung verschiedener Teile des Produkts zu schaffen. Sie richtete die Schnittstellen ein, über die verschiedene Projekte als Ganzes funktionieren konnten - genau die Regeln, die leichter zu befolgen sind als zu brechen.


Wir nennen diesen Befehl "API", obwohl die technische Implementierung der neuen API nur einen kleinen Teil ihrer Aufgaben ausmacht. Da allgemeine Codeabschnitte in eine separate Funktion gestellt werden, analysiert das API-Team die allgemeinen Probleme der Produktteams. Hier findet die Verbindung zwischen Frontend und Backend statt, sodass die Mitglieder dieses Teams die Besonderheiten jeder Richtung verstehen müssen.


Vielleicht ist die „API“ nicht der am besten geeignete Name für das Team, etwas über Architektur oder großräumige Vision wäre besser geeignet, aber ich denke, diese Kleinigkeit ändert nichts an der Essenz.


API


Die Funktionszugriffsschnittstelle auf dem Server war in unserer ursprünglichen Anwendung vorhanden, sah für den Verbraucher jedoch chaotisch aus. Die Trennung von Frontend und Backend erforderte mehr Sicherheit.


Die Ziele für die neue API sind aus täglichen Schwierigkeiten bei der Implementierung neuer Produkt- und Designideen hervorgegangen. Wir brauchten:


  1. Schwache Konnektivität von Systemkomponenten, sodass Backend und Frontend parallel entwickelt werden können.
  2. Hohe Skalierbarkeit, damit die neue API die Gebäudefunktionalität nicht beeinträchtigt.
  3. Stabilität und Konsistenz.

Die Suche nach einer Lösung für die API begann nicht mit dem Backend, wie es normalerweise akzeptiert wird, sondern dachte im Gegenteil darüber nach, was Benutzer brauchten.


Am häufigsten sind alle Arten von REST-APIs. In den letzten Jahren wurden ihnen beschreibende Modelle durch Tools wie swagger hinzugefügt, aber Sie müssen verstehen, dass dies der gleiche REST ist. Tatsächlich sind das wichtigste Plus und Minus gleichzeitig die Regeln, die ausschließlich beschreibend sind. Das heißt, niemand verbietet dem Ersteller einer solchen API, bei der Implementierung einzelner Teile von REST-Postulaten abzuweichen.


Eine weitere gängige Lösung ist GraphQL. Es ist auch nicht perfekt, aber im Gegensatz zu REST ist die GraphQL-API nicht nur ein beschreibendes Modell, sondern echte Regeln.


Zuvor habe ich über das System gesprochen, das die Arbeit des Frontends und des Backends koordinieren sollte. Die Zwischenschicht ist genau diese Zwischenstufe. Nachdem wir mögliche Optionen für die Arbeit mit dem Server in Betracht gezogen hatten, entschieden wir uns für GraphQL als API für das Frontend . Da das Backend jedoch in C ++ geschrieben ist, erwies sich die Implementierung des GraphQL-Servers als nicht triviale Aufgabe. Ich werde nicht alle Schwierigkeiten und Tricks beschreiben, die wir unternommen haben, um sie zu überwinden. Es hat kein wirkliches Ergebnis gebracht. Wir haben das Problem von der anderen Seite betrachtet und festgestellt, dass Einfachheit der Schlüssel zum Erfolg ist. Aus diesem Grund haben wir uns für bewährte Lösungen entschieden: einen separaten Node.js-Server mit Express.js und Apollo Server.


Als nächstes mussten Sie entscheiden, wie Sie auf die Backend-API zugreifen möchten. Zuerst haben wir uns mit der Erhöhung der REST-API befasst, dann haben wir versucht, Add-Ons in C ++ für Node.js zu verwenden. Als Ergebnis stellten wir fest, dass dies alles nicht zu uns passte, und nach einer detaillierten Analyse für das Backend entschieden wir uns für eine API, die auf gRPC-Diensten basiert .


Nachdem wir die Erfahrungen mit C ++, TypeScript, GraphQL und gRPC gesammelt haben, haben wir eine Anwendungsarchitektur erhalten, mit der Sie das Backend und das Frontend flexibel entwickeln und gleichzeitig ein einziges Softwareprodukt erstellen können.


Das Ergebnis ist ein Schema, bei dem das Front-End über GraphQL-Abfragen mit einem Zwischenserver kommuniziert (weiß, was zu fragen ist und was es dafür erhält). Der graphQL-Server in Resolvern ruft die API-Funktionen des gRPC-Servers auf und verwendet dazu Protobuf-Schemata für die Kommunikation. Der gRPC-basierte API-Server weiß, von welchem ​​Microservice Daten abgerufen oder an wen die Anforderung gesendet werden sollen. Die Microservices selbst basieren ebenfalls auf gRPC, wodurch die Geschwindigkeit der Abfrageverarbeitung, die Datentypisierung und die Verwendung verschiedener Programmiersprachen für ihre Entwicklung sichergestellt werden.


Bild
Allgemeines Arbeitsschema nach einem Architekturwechsel


Dieser Ansatz hat eine Reihe von Minuspunkten, von denen der Hauptaufwand das zusätzliche Einrichten und Koordinieren von Schaltkreisen sowie das Schreiben von Hilfsfunktionen ist. Diese Kosten zahlen sich jedoch aus, wenn mehr API-Benutzer vorhanden sind.


Ergebnis


Wir sind den evolutionären Weg der Entwicklung eines Produkts und eines Teams gegangen. Erfolgreich oder das Unternehmen ist gescheitert, es ist wahrscheinlich früh zu beurteilen, aber Zwischenergebnisse können zusammengefasst werden. Was wir jetzt haben:


  1. Das Frontend ist für die Anzeige verantwortlich, und das Backend ist für die Daten verantwortlich.
  2. Am Frontend blieb die Flexibilität beim Abfragen und Empfangen von Daten erhalten. Die Schnittstelle weiß, was Sie den Server fragen können und welche Antworten sein sollten.
  3. Das Backend hat die Möglichkeit, den Code mit der Gewissheit zu ändern, dass die Benutzeroberfläche weiterhin funktioniert. Es wurde möglich, auf die Microservice-Architektur umzusteigen, ohne das gesamte Frontend wiederholen zu müssen.
  4. Jetzt können Sie Scheindaten für das Frontend verwenden, wenn das Backend noch nicht bereit ist.
  5. Durch die Erstellung von Kollaborationsschemata wurden Interaktionsprobleme beseitigt, wenn Teams dieselbe Aufgabe unterschiedlich verstanden. Die Anzahl der Iterationen zum Ändern von Datenformaten wurde reduziert: Wir handeln nach dem Prinzip „siebenmal messen, einmal schneiden“.
  6. Jetzt können Sie Sprintarbeiten parallel planen.
  7. Um einzelne Microservices zu implementieren, können Sie jetzt Entwickler einstellen, die mit C ++ nicht vertraut sind.

Aus all dem würde ich die Gelegenheit, das Team und das Projekt bewusst weiterzuentwickeln, als Hauptleistung bezeichnen. Ich denke, wir konnten Bedingungen schaffen, unter denen jeder Teilnehmer seine Kompetenzen gezielter verbessern, sich auf Aufgaben konzentrieren und nicht die Aufmerksamkeit streuen kann. Jeder muss nur an seiner eigenen Site arbeiten, und jetzt ist es mit hohem Engagement und ohne ständigen Wechsel möglich. Es ist unmöglich, in allem ein Profi zu werden, aber jetzt ist es für uns nicht notwendig .


Der Artikel erwies sich als Rezension und sehr allgemein. Ihr Ziel war es, den Weg und die Ergebnisse komplexer Forschungen zum Thema der Änderung der Architektur aus technischer Sicht aufzuzeigen, um die Produktentwicklung fortzusetzen, sowie die organisatorischen Schwierigkeiten bei der Aufteilung eines Teams in vereinbarte Teile aufzuzeigen.


Hier habe ich oberflächlich die Themen Team- und Teamarbeit an einem Produkt, die Wahl der API-Technologie (REST vs GraphQL), die Verbindung von Node.js-Anwendungen mit C ++ usw. angesprochen. Jedes dieser Themen zeichnet einen eigenen Artikel, und wenn Sie interessiert sind, dann wir werden sie schreiben.

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


All Articles