Softwarearchitektur verstehen und entscheiden

Aaron KreisÜber mich
Integration

Backend for Frontend

Ein eigenes Backend je Oberfläche

Die Idee und ihr Nutzen

Eine Versicherung hat eine Kunden-App für das Smartphone und eine Makler-Webseite, zwei Oberflächen, die Menschen sehen und bedienen. Beide zeigen Daten aus denselben internen Programmen, dem Vertragsdienst und dem Schadendienst, brauchen davon aber sehr unterschiedlich viel: Die Kunden-App zeigt auf ihrer Startseite nur Name, Zahl der Verträge und offene Schäden, die Makler-Webseite zusätzlich Beiträge, Provisionen und die ganze Schadenhistorie. Deshalb bekommt jede der beiden Oberflächen ein eigenes Programm auf dem Server, das die benötigten Daten bei den internen Diensten abholt und genau so zusammenstellt, wie diese Oberfläche sie anzeigt. Es sind zwei verschiedene Programme, weil die beiden Oberflächen verschiedene Daten brauchen. Das Team jeder Oberfläche kann so seine Oberfläche ändern, ohne dass die andere Oberfläche davon betroffen ist. Ein solches Programm heißt Backend for Frontend, kurz BFF, auf Deutsch etwa „Serverprogramm für eine Oberfläche“. Frontend ist das englische Wort für die Oberfläche, Backend das Wort für ein Programm auf dem Server, das Daten liefert.

Bausteine: Kunden-App: zeigt Name, Verträge, offene Schäden; Makler-Webseite: zeigt auch Beiträge, Provisionen, Historie; App-Backend: stellt ein kleines Datenpaket zusammen; Makler-Backend: stellt ein großes Datenpaket zusammen; Vertragsdienst: liefert Name, Verträge, Beiträge; Schadendienst: liefert Schäden. Verbindungen: Kunden-App — App-Backend; Makler-Webseite — Makler-Backend; App-Backend — Vertragsdienst; Makler-Backend — Schadendienst; App-Backend — Schadendienst; Makler-Backend — Vertragsdienst. Jede Oberfläche hat ihr eigenes Backend, das die Daten der internen Dienste für genau diese Oberfläche zusammenstellt.

Wie funktioniert es?

Die Kundin Frau Yilmaz öffnet die Startseite der Kunden-App. Die Kunden-App stellt eine einzige Anfrage „Startseite für Frau Yilmaz“ an das App-Backend, das eigene Serverprogramm der Kunden-App. Das App-Backend fragt den Vertragsdienst und den Schadendienst gleichzeitig, damit die Antwort schneller vorliegt. Der Vertragsdienst liefert den Namen und drei Verträge, der Schadendienst meldet einen offenen Schaden von Frau Yilmaz. Das App-Backend wählt nur aus, was die Startseite zeigt: den Namen, die Zahl der Verträge und den Status „offen“ des Schadens. Dieses kleine Datenpaket schickt das App-Backend an die Kunden-App, die es sofort anzeigt. Zur gleichen Zeit öffnet der Makler von Frau Yilmaz auf der Makler-Webseite die Kundenübersicht von Frau Yilmaz. Die Makler-Webseite fragt das Makler-Backend, ihr eigenes Serverprogramm. Das Makler-Backend fragt denselben Vertragsdienst nach Verträgen, Beiträgen und Provisionen. Denselben Schadendienst fragt das Makler-Backend nach allen Schäden der letzten zehn Jahre; so lange bewahrt der Schadendienst abgeschlossene Schäden auf. Das Makler-Backend schickt der Makler-Webseite ein deutlich größeres Datenpaket. Das App-Team baut die Kunden-App. Einige Wochen später möchte das App-Team auf der Startseite zusätzlich das Datum der nächsten Beitragszahlung zeigen. Das App-Team ergänzt dafür nur das App-Backend, und die Makler-Webseite ist davon nicht betroffen.

Vertragsdienst und Schadendienst gehören jeweils einem eigenen Team und werden über das Netz abgefragt. Eine Schnittstelle ist die vereinbarte Form der Anfragen, die ein Dienst annimmt, und der Antworten, die er liefert. Das Team des Vertragsdienstes und das Team des Schadendienstes legen die Schnittstelle ihres Dienstes jeweils für alle Aufrufer gleich fest. Das App-Backend und das Makler-Backend rufen diese Schnittstellen auf, und die beiden Dienste bleiben unverändert. Ein Backend for Frontend gehört meist dem Team, das auch die Oberfläche baut; das App-Backend gehört also dem App-Team. Dieses Team kann sein Backend ändern, wann immer seine Oberfläche neue Daten braucht, ohne andere Teams zu fragen. Fachliche Regeln gehören nicht in ein Backend for Frontend, sondern bleiben in den internen Diensten, damit sie für Kunden-App und Makler-Webseite gleich gelten. Fachliche Regeln legen zum Beispiel fest, wer eine Auszahlung freigeben darf oder wie ein Beitrag berechnet wird. Schneller oder zuverlässiger macht ein Backend for Frontend die internen Dienste nicht: Ist der Schadendienst gestört, fehlen dem App-Backend und dem Makler-Backend dieselben Schadendaten.

Jedes Team muss für sein Backend vorher festlegen, was die Oberfläche erhält, wenn einer der internen Dienste nicht rechtzeitig antwortet. Das App-Backend kann etwa die Vertragsdaten schicken und für die Schäden den Hinweis „derzeit nicht verfügbar“ mitliefern. Eine fehlende Antwort des Schadendienstes bedeutet nicht, dass Frau Yilmaz keine Schäden hat. Das App-Backend darf die fehlende Antwort deshalb nicht als leere Liste weitergeben.

Backend for Frontend: Kunden-App und Makler-Webseite erhalten passende Daten

Beteiligte: Kunden-App: zeigt Frau Yilmaz ihre Startseite; App-Backend: stellt ein kleines Datenpaket für die App zusammen; Vertragsdienst: liefert Name, Verträge, Beiträge; Schadendienst: liefert Schäden; Makler-Backend: stellt ein großes Datenpaket für Makler zusammen; Makler-Webseite: zeigt dem Makler die Kundenübersicht. Ablauf: 1. Die Kundin Frau Yilmaz öffnet die Kunden-App. Die Kunden-App stellt eine einzige Anfrage „Startseite für Frau Yilmaz“ an das App-Backend. 2. Das App-Backend fragt den Vertragsdienst. 3. Der Vertragsdienst liefert den Namen und drei Verträge. 4. Gleichzeitig fragt das App-Backend den Schadendienst. 5. Der Schadendienst meldet einen offenen Schaden von Frau Yilmaz. 6. Das App-Backend wählt nur aus, was die Startseite zeigt, und schickt dieses kleine Paket an die Kunden-App. 7. Der Makler öffnet auf der Makler-Webseite die Kundenübersicht von Frau Yilmaz. Die Makler-Webseite fragt das Makler-Backend. 8. Das Makler-Backend fragt denselben Vertragsdienst nach Verträgen, Beiträgen und Provisionen. 9. Das Makler-Backend fragt denselben Schadendienst nach allen Schäden der letzten zehn Jahre. 10. Das Makler-Backend schickt der Makler-Webseite ein deutlich größeres Paket. Ändert das App-Team sein Backend, ist die Makler-Webseite nicht betroffen.

Wann ist es sinnvoll und wann nicht?

Ein Backend for Frontend lohnt sich

  • Mehrere Oberflächen nutzen dieselben internen Dienste, brauchen aber deutlich unterschiedliche Daten oder Datenmengen. Ohne Backend for Frontend bieten die internen Dienste nur eine gemeinsame Schnittstelle für alle Oberflächen an. Liefert diese gemeinsame Schnittstelle bei jeder Anfrage alle Details, lädt die Kunden-App viel mehr Daten als nötig und wird langsam. Liefert sie nur wenig, muss die Makler-Webseite viele einzelne Anfragen an verschiedene Dienste stellen und die Ergebnisse selbst zusammensetzen.
  • Eine Oberfläche läuft über eine langsame Netzverbindung und soll eine Bildschirmseite mit einer einzigen Anfrage füllen können, statt mehrere Dienste einzeln zu fragen. Die Kunden-App läuft zum Beispiel oft über eine langsame Mobilfunkverbindung, die Makler-Webseite dagegen im Büro am großen Bildschirm. Ohne Backend for Frontend müsste die Kunden-App Vertragsdienst und Schadendienst einzeln fragen, und über die Mobilfunkverbindung verlängert jede zusätzliche Anfrage die Wartezeit, bis die Startseite erscheint.
  • Die Teams der Oberflächen wollen ihre Oberflächen unabhängig voneinander ändern und ausliefern, jedes in seinem eigenen Rhythmus. Ohne Backend for Frontend muss sich das App-Team bei jeder Änderung an der gemeinsamen Schnittstelle mit dem Team der Makler-Webseite abstimmen, weil jede Änderung beide Oberflächen trifft.

Ein Backend for Frontend ist nicht das Richtige

  • Kunden-App und Makler-Webseite brauchen fast dieselben Daten. App-Backend und Makler-Backend würden dann dieselben Daten auf dieselbe Weise zusammenstellen, und derselbe Code entstünde zweimal. Stattdessen baut ein Team ein einziges gemeinsames Backend, das die Daten aus Vertragsdienst und Schadendienst für beide Oberflächen zusammenstellt. Ein zweites Backend, das gebaut, ausgeliefert und mit Sicherheitsupdates versorgt werden muss, entfällt.
  • Weder das App-Team noch das Team der Makler-Webseite kann ein eigenes Backend betreiben, und die beiden Oberflächen unterscheiden sich vor allem darin, welche einzelnen Angaben sie anzeigen. Dann betreibt ein einziges Team für alle Oberflächen eine gemeinsame Schnittstelle mit der Abfragesprache GraphQL. Bei GraphQL legt jede Oberfläche in ihrer Anfrage selbst fest, welche Angaben sie erhalten will. Statt eines Backends je Oberfläche muss dieses Team nur ein Programm betreiben.
  • Die Oberfläche braucht die Daten der internen Dienste ohnehin fast unverändert. Dann ruft die Oberfläche die internen Dienste selbst auf, etwa über ein gemeinsames API Gateway, einen einzigen Eingang, der jede Anfrage von außen annimmt und an den zuständigen internen Dienst weiterleitet. Ein Backend for Frontend würde die Antworten nur weiterreichen. Der Umweg jeder Anfrage über dieses zusätzliche Programm entfällt, und niemand muss das Programm betreiben.

Nachteile und typische Fehler

Jedes Backend for Frontend ist ein weiteres Programm, das gebaut, ausgeliefert, überwacht und mit Sicherheitsupdates versorgt werden muss. Brauchen zwei Oberflächen teilweise dieselben Zusammenstellungen, wird derselbe Code in zwei Backends geschrieben und gepflegt. Gemeinsamer Code kann in eine Programmbibliothek ausgelagert werden, doch dann müssen sich die Teams über diese Bibliothek wieder abstimmen. Jede Anfrage läuft über einen zusätzlichen Zwischenschritt. Das Zusammenfassen mehrerer Anfragen spart meist mehr Zeit, als der Zwischenschritt braucht, aber nicht in jedem Fall. Die Abhängigkeit von den internen Diensten bleibt bestehen: Ändert das Team des Vertragsdienstes seine Schnittstelle, müssen beide Backends prüfen, ob sie angepasst werden müssen. Aufgaben, die alle Oberflächen betreffen, gehören in ein gemeinsames API Gateway, an das jede Anfrage der Oberflächen zuerst geht und das sie danach an das zuständige Backend weiterleitet, damit nicht jedes Team sie in seinem Backend noch einmal bauen muss. Solche Aufgaben sind zum Beispiel die Anmeldung und die Begrenzung der Anfragen.

Typische Fehler und woran man sie erkennt:

  • Fachliche Regeln im Backend: Die Teams bauen fachliche Regeln in die Backends ein, etwa weil ein Team eine Änderung im eigenen Backend ohne Absprache mit einem anderen Team machen kann. Das App-Team baut zum Beispiel eine Rabattregel für den Beitrag in das App-Backend ein. Das Makler-Backend kennt diese Regel nicht. Die Kunden-App zeigt dann einen anderen Beitrag als die Makler-Webseite. Erkennbar ist das an Fällen, in denen Kunden-App und Makler-Webseite für dieselbe Kundin verschiedene Ergebnisse anzeigen, etwa einen anderen Beitrag.
  • Fehlende Antwort als leere Liste: Antwortet der Schadendienst nicht, gibt das App-Backend eine leere Schadenliste weiter. Frau Yilmaz sieht dann keinen offenen Schaden, obwohl einer besteht. Erkennbar ist das an Meldungen von Kunden über verschwundene Schäden, die zeitlich mit Störungen des Schadendienstes zusammenfallen.
  • Nacheinander statt gleichzeitig: Das App-Backend fragt Vertragsdienst und Schadendienst nacheinander statt gleichzeitig ab. Das App-Backend wartet erst auf die Antwort des Vertragsdienstes und fragt erst danach den Schadendienst. Die Wartezeiten beider Dienste addieren sich, und die Startseite erscheint entsprechend später in der Kunden-App. Erkennbar ist das an Antwortzeiten des App-Backends, die ungefähr der Summe der Antwortzeiten beider Dienste entsprechen.
  • Ein Backend für alle: Weitere Oberflächen werden an das bestehende App-Backend angehängt, zum Beispiel eine Tablet-App. Das App-Backend wird wieder zur gemeinsamen Schnittstelle, und die Teams müssen sich erneut abstimmen. Erkennbar ist das an Änderungswünschen mehrerer Teams an dasselbe Backend.

Weiterführend

Verwandte Ansätze

  • Facade: fasst viele einzelne Aufrufe hinter einem einzigen Aufruf zusammen; ein Backend for Frontend tut das für genau eine Oberfläche.
  • Scatter Gather: beschreibt, wie eine Anfrage an mehrere Dienste gleichzeitig verteilt und die Antworten eingesammelt werden, so wie das App-Backend Vertragsdienst und Schadendienst gleichzeitig fragt.
  • Microservices: Bauweise mit vielen kleinen Diensten. Bei dieser Bauweise müssen Oberflächen Daten aus vielen Diensten zusammensetzen, deshalb kommen Backends for Frontend bei Microservices häufig vor.

Werkzeuge und Umsetzungen

Ein Backend for Frontend ist meist ein selbst geschriebenes Programm. Diese Projekte können als Grundlage dienen:

  • Apollo Server: Server für die Abfragesprache GraphQL, mit der eine Oberfläche genau die gewünschten Angaben anfordern kann. Das Team der Oberfläche programmiert dazu, aus welchem internen Dienst die einzelnen Angaben kommen.
  • KrakenD: Gateway, das Antworten mehrerer Dienste über Einstellungen zusammenführt und auf bestimmte Angaben kürzt. Backends for Frontend, die nur Antworten zusammenführen und kürzen, lassen sich so ohne eigenen Code bauen.
  • Spring Cloud Gateway: Gateway für Java, das sich als eigenes Backend je Oberfläche betreiben und mit eigenem Java-Code erweitern lässt.

Quellen

  • Sam Newman: Pattern: Backends For Frontends: ursprüngliche Beschreibung des Musters mit einem Backend je Oberfläche, Besitz durch das Oberflächenteam, paralleler Abfrage der Dienste und dem Umgang mit doppeltem Code.
  • Microsoft: Backends for Frontends pattern: beschreibt Einsatz, Grenzen und Betriebsaufwand des Musters und nennt GraphQL und ein API Gateway als Möglichkeiten, die ein eigenes Backend je Oberfläche überflüssig machen können.