UX

Kolumne: Stropek as a Service

Web-API Design Gotchas: Warum mehr Zeit in das Design von Web-APIs investiert werden sollte
Keine Kommentare

Wer sich heute in Richtung SaaS und Cloud wagt, der hat sich zwangsläufig mit dem Thema Web-APIs beschäftigt. Niemand käme mehr auf die Idee, in einer solchen Umgebung einen Two-Tier Fat Client mit direktem Datenbankzugriff zu entwickeln.

Natürlich braucht es eine Service-Schicht in Form eines Web-API, das idealerweise auch als Ganzes oder teilweise für die öffentliche Nutzung durch Kunden und Partner freigegeben wird. Diese Entscheidung fällt nicht schwer. Auch Designeckpfeiler wie HTTPS, JSON und OpenID Connect als Basis für das Kommunikationsprotokoll liegen auf der Hand. Dann beginnen aber schon die Fragen.

In dieser Ausgabe meiner Kolumne möchte ich keine Implementierungsfragen behandeln. Stattdessen möchte ich auf wichtige Designaspekte in Sachen Web-APIs eingehen, die für Einsteiger in das Thema SaaS und Cloud vielleicht nicht alle offensichtlich sind. Sie tragen aber wesentlich zum Erfolg eines API bei. Verwenden Sie die Punkte als Checkliste, um vielleicht noch Lücken in Ihrem API-Design zu entdecken.

Web-APIs sind UX

Bei grafischen Benutzerschnittstellen ist es keine Frage, dass man auf ein klares, sauberes Design achtet. Eingabefelder sind ordentlich angeordnet, auf Einheitlichkeit und Konsistenz wird geachtet, man beauftragt vielleicht sogar einen Designer für den Feinschliff. Auch Web-APIs sind Benutzerschnittstellen und damit Teil der User Experience (UX). Die Benutzer sind interne oder externe Entwicklerteams. Dementsprechend sollten Sie wie beim UI-Design auch der API-Gestaltung ausreichend Aufmerksamkeit schenken (z. B. Namensgebung, URL-Schema, Einhalten von Best Practices, Konsistenz, Standardkonformität etc.). Dokumentierte API-Design-Guidelines, Designreviews auf API-Ebene und Feedbackrunden mit späteren API-Konsumenten sollten wichtige Bestandteile eines Cloud-basierenden SaaS-Projekts sein.

API-Design, das zu den Szenarien passt

Web-APIs können auf die unterschiedlichsten Arten gestaltet sein. Man kann ein klassisches RESTful Web-API mit CRUD-Operationen für alle Entitäten entwickeln. Das verlagert zwangsläufig Logik in den Client. Die Alternative wären domänenspezifischere API-Endpunkte, die Funktionen auf höherer Abstraktionsebene abbilden. Konzentriert man sich darauf, schränkt man die Cliententwicklungsteams bewusst in ihrer Freiheit ein. OData und GraphQL sind Alternativen, die am anderen Ende des Spektrums sitzen. Sie bieten dem Client sogar eine flexible Abfragesprache, mit der je nach Bedarf selektiert, gefiltert, sortiert, geblättert etc. werden kann.

Eine pauschale Antwort, welcher Designansatz der beste ist, kann ich nicht geben. Die Lösung muss die relevanten Anwendungsszenarien gut abbilden undzur jeweiligen Domäne und zur gewünschten Aufgabenverteilung zwischen Client und Server passen.

Metadaten sind unverzichtbar

Damit die Konsumenten Ihres API wissen, was sie damit anstellen können, braucht es nicht nur Dokumentation, sondern auch maschinenlesbare Metadaten. An Open API (aka Swagger) führt heutzutage kaum ein Weg vorbei. Das Toolökosystem rund um diesen Standard ist unverzichtbar. Inkonsistenzen zwischen API-Metadaten und Implementierung sind nicht akzeptabel. Es ist daher wichtig, dass ihre API-Strategie Metadaten von Anfang an miteinbezieht.

Versionierung

In der heutigen IT gibt es nur einen Fixpunkt: Veränderung. Nicht nur die Tools und Frameworks entwickeln sich weiter, auch die Kommunikationsprotokolle. Nicht wenige meiner Kunden müssen ein Mischmasch aus SOAP, REST, OData und GraphQL gleichzeitig betreiben. Sie haben sich nicht bewusst dafür entschieden, es ist im Lauf der Zeit einfach passiert. Design for Change ist bei öffentlichen APIs daher sehr wichtig. Sie müssen Strategien insbesondere für folgende Fragestellungen entwickeln:

  • Wie identifiziert ein Aufrufer die API-Version, die er verwenden möchte (z. B. Domain, URL-Pfad, URL-Parameter, HTTP-Header)?
  • Wie können Sie mehrere Versionen eines API gleichzeitig betreiben (z. B. wegen SLAs, die Sie zwingen, alte Versionen längere Zeit zur Verfügung zu stellen)?
  • Wie können Sie neue API-Versionen parallel zum Produktivbetrieb testen (z. B. A/B-Testing, als Backend für Previewversionen)?

Wie organisieren und kommunizieren Sie Versionsunterschiede (z. B. Versionsnummerierung entsprechend dem Semantic-Versioning-Standard, klar kommunizierte Verfügbarkeitszeiträume, Release Notes)?

HTTP nicht als Allheilmittel betrachten

HTTP-basierende Web-APIs sind eine nützliche Sache, aber keine Lösung für alle Probleme. Wenn Sie ein API für (potenziell) lange laufende Prozesse brauchen, ist HTTP gefährlich. Es kommt leicht zu Time-outs. Asynchrone Verarbeitung von Anfragen mit Polling APIs oder Benachrichtigungen über WebSockets und Push Messaging sind in diesem Fall eine gute Wahl.

Messagebasierende APIs (z. B. auf Basis des AMQP-Protokolls) sind eine gute Option, wenn man Client und Server stärker entkoppeln möchte. Es könnte sein, dass der Client in gewissen Situationen schneller Abfragen schickt, als der Server verarbeiten kann. Eine Messagequeue kann das Puffern übernehmen. Bei Verwendung eines Messagesystems macht auch ein kurzer Ausfall des Servers weniger Probleme. Der Client kann weiter Anfragen über das Messagesystem schicken und der Server verarbeitet sie, wenn er wieder in Betrieb ist.

Auch wenn HTTP-Web-APIs einfach zu entwickeln und zu betreiben sind, sollte man die Augen nicht vor Alternativen verschließen. Das Mischen von verschiedenen Ansätze je nach Aufgabenstellung ist auch möglich. Übertriebener Drang zur Vereinheitlichung ist oft kontraproduktiv.

WebHooks

Web-APIs sind keine Einbahnstraße. Wenn es um Server-zu-Server-Kommunikation über Web-APIs geht, sind sogenannte WebHooks praktisch. Man registriert einen Web-API-Endpunkt, an den das Gegenüber im Fall gewisser Events HTTP Requests schickt. Durch solche WebHooks kann man Polling APIs vermeiden oder zumindest die Häufigkeit des Pollings reduzieren und dadurch die Systemlast senken.

Logging, Monitoring, Telemetrie

Teilt man ein Gesamtsystem in Services auf, die über Web-APIs kommunizieren, kommt es naturgemäß zu mehr Kommunikationsfehlern als in einem monolithischen Gesamtsystem, in dem Module über Funktionsaufrufe kommunizieren. Dazu kommt, dass die Fehleranalyse ungleich schwieriger ist. War der Fehler im aufgerufenen Service oder drei Service-Ebenen weiter unten? Wo soll man einen Debugger dranhängen, um einem Problem auf die Spur zu kommen? In welchem System durchforstet man die Logs?

In einem Netzwerk von Services nimmt die Bedeutung von zentralem Logging, Monitoring und einer zentralen Telemetrie-DB drastisch zu. Darauf zu verzichten und zu meinen, alle Fehler auch so schnell diagnostizieren und beheben zu können, wäre naiv. Auch das simple Zusammenkopieren von Logdateien aller beteiligten Server oder Container ist nicht ausreichend. Es braucht eine durchgängige Verfolgbarkeit von Benutzeraktionen vom UI bis in den letzten Microservice, damit im Fehlerfall die Ursache rasch identifiziert und behoben werden kann. Das hat Einfluss auf das API-Design.

Throttling

Wenn Benutzer beginnen, mithilfe der angebotenen APIs Aufgaben zu automatisieren, machen sie zwangsläufig irgendwann Fehler. Eine Endlosschleife auf Kundenseite, die Ihr API in kurzer Zeit mit Requests überflutet, ist nur eine Frage der Zeit. Dabei muss es sich nicht einmal um böswillige Absicht handeln.

Wer APIs veröffentlicht und Downtimes wegen (absichtlicher oder unabsichtlicher) DoS-Attacken vermeiden will, braucht Mechanismen zur Begrenzung des API-Zugriffs. Das entsprechende Geschäftsmodell (wer darf welches API wie intensiv nutzen) hat oft Auswirkungen auf das API-Design. Wie erkennt man bei einem API-Aufruf, wer der Aufrufer ist und ob er gerade berechtigt ist, das API aufzurufen? Wie kommuniziert man Fehler durch Übernutzung? Wie gestaltet man Zugangssperren im API-Design?

Multi-Tenancy

Die meisten SaaS-Lösungen, mit denen ich zu tun habe, sind Multi-Tenant-fähig. Das bedeutet, dass eine gemeinsame Cloud-Infrastruktur eine Vielzahl logisch getrennter Kunden (Tenants) bedient. In einer solchen Umgebung muss das API das Tenant-System widerspiegeln. Denkbar wären zum Beispiel Tenant IDs in der Domain, im URL-Pfad oder in HTTP-Headern. Auch das Ableiten der Tenant-Zugehörigkeit aus Authorization-Tokens (z. B. JWT) ist möglich.

Das Multi-Tenancy-Design hat meiner Erfahrung nach eine enge Beziehung mit dem Versionskonzept. Schließlich ist es in vielen Systemen gefordert, dass unterschiedliche Tenants zum gleichen Zeitpunkt unterschiedliche Versionen verwenden. Man strebt an, Updates schrittweise auf alle Tenants ausrollen zu können.

Fazit

Mein Tipp: Lieber etwas mehr Zeit in das API-Design stecken, das Design durch Prototypen und frühes Kundenfeedback prüfen und das Programmieren ein wenig nach hinten verschieben. Ich sehe zu oft Projektteams, die technikverliebt sind und es nicht erwarten können, endlich Code zu schreiben. Man kommt so zwar schneller zu einem Ziel, es ist aber oft nicht das, das man eigentlich erreichen wollte. Interpretieren Sie meine Aussage aber nicht als Plädoyer für das Wasserfallmodell oder Big Design Upfront. Iterative Entwicklung auf Basis agiler Methoden ist meiner Erfahrung nach immer besser als der Versuch, so lange zu planen, bis alles perfekt ist. Aber auch bei agiler Vorgehensweise schadet es nicht, sich vorab Gedanken über die Herausforderungen zu machen, die auf einen warten, bewusste Designentscheidungen zu treffen und offensichtliche Anforderungen von Anfang an zu berücksichtigen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -