Jetzt mal ganz unter uns: Du gehst voll mit dem Trend, öffnest dein System „nach außen“ mit einer RESTful-HTTP-Schnittstelle, das Ganze auch noch im agilen Ansatz – und dann das! Die Consumer beschweren sich. Dabei hast du deine Schnittstelle sogar dokumentiert und passt sie zeitnah an neue Anforderungen und Feedback an! WARUM also hasst jemand deine API?
Vielleicht haben die Consumer einfach keine Ahnung. Vielleicht hilft dir aber auch unser nicht zu ernst gemeinter Hass-Katalog. Dafür nehmen wir nachfolgend die Ich-Perspektive deines (ziemlich motzenden) API Consumers ein.
Ich bin dein Consumer – und ich hasse deine API, weil …
… meine Anwendung alle paar Wochen unerwartet abbricht, da deine API plötzlich anders reagiert
Es ist ja schön, dass du mit jedem Sprint „Verbesserungen“ und neue Features einbaust. Allerdings bin ich schon überrascht, wenn plötzlich mehr Informationen (z.B. neue Attribute) in der Response geliefert werden. Und ja, es ist toll, dass du sogar deine API-Beschreibung entsprechend angepasst hast. Aber ich habe eigentlich kein Monitoring darauf aufgesetzt. Und wenn du dann evtl. noch neue bzw. andere Fehlercodes zurückschickst oder Pagination einbaust, dann sind das für mich wirklich „breaking changes“!
Also ein Vorschlag zur Güte: Für mich ist es total okay, wenn ich in meinem Request (z.B. in der URL) eine Versionsnummer angebe – und von Zeit zu Zeit aktiv umschalten muss, weil du eine alte Version abschaltest. Aber bitte – versioniere deine API und halte zumindest eine Zeit lang alte Versionen parallel am Leben. Dann kann ich in Ruhe umbauen und testen und mich dann sogar über neue Features freuen. Ach so: Und vielleicht könntest du mich sogar aktiv über neue Versionen und Sundowns benachrichtigen, z.B. auf dem Portal, auf dem du deine API publiziert hast, in der API Response oder ganz traditionell per Newsletter (siehe auch How to Smartly Sunset and Deprecate APIs)?
… deine API immer mit HTTP Response Code 200 antwortet
HTTP Response Codes sind doch keine hohe Wissenschaft [Anmerkung der Autorin: im Detail manchmal schon 😉]. Ich mach es mal ganz einfach und begrenze mich zumindest auf drei Hauptgruppen und ein paar Beispiele aus jeder Gruppe:
OK, auch ich bin nicht unfehlbar. Dabei wäre es schön, wenn du mir hilfst meinen Fehler zu erkennen. Es darf gern etwas detaillierter sein als immer nur HTTP Status Code 400.
Ich weiß, dass das unangenehm ist, aber falls das Problem bei dir bekannt ist, wären ein paar Details schon schön – und damit meine ich nicht deinen internen Stacktrace!
… meine Requests ewig brauchen bis zur Antwort
Wenn du die Anfrage (nach Ausschöpfen von anderen Performanz-Verbesserungen durch Caching o.ä.) wirklich nicht so schnell verarbeiten kannst, dann ist vielleicht eine asynchrone Verarbeitung besser – ggf. mit HTTP Response 202 (ACCEPTED). Gib mir eine Referenz zurück und ich kann ggf. periodisch nach dem Status fragen.
… ich schon mehrfach durch hohe Last einen Crash deiner API verursacht habe
Wenn du mir deine SLAs (Service Level Agreements) mitteilst, kann ich das zumindest auch auf meiner Seite berücksichtigen.
Schutzmechanismen wie Circuit Breaker, Spike Arrests und Quotas sollten das auf deiner Seite jedoch zusätzlich sicherstellen.
… ich dich erst anschreiben muss, um dir zu sagen, dass deine API gerade nicht funktioniert
So ein providerseitiges Monitoring ist eine feine Sache – aber ich verstehe, dass consumer-driven Alerting die einfachere Variante ist. Aber nur für dich als Provider und ganz bestimmt nicht für mich.
… deine API unvollständig dokumentiert ist und ich daher HTTP-Response-400-Pingpong spielen muss
Ich erkenne keine Unterscheidung von optionalen und Pflichtfeldern, Attribute mit nur zwei möglichen Werten sind nur als String (statt Enumeration – siehe auch OpenAPI Spec: Enums) definiert und sämtliche Fehlerfälle fehlen in deiner Dokumentation komplett. Um diese Informationen zumindest für Request-Objekte zu bekommen, schicke ich alle möglichen Request-Kombinationen gegen deine API und schaue, wann ich HTTP Response 400 bekomme. Statt dessen wäre sowas schön:
paths:
/persons:
get:
parameters:
- in: query
name: surname
required: true
description: surename of the person you are searching for
schema:
type: string
- in: query
name: sort
description: alphabetical sort order of persons by surname
schema:
type: string
enum: [asc, desc]
Außerdem ist keine Beschreibung deiner SLAs enthalten (gibt es z.B. Quota-Restriktionen) und die Security ist auch nicht definiert (ja, auch falls es nur ein API Key ist). Dass die Endpunkte für alle Umgebungen fehlen (für Produktion und – wünschenswerterweise auch – Test oder Tryout), ist dabei dann das kleinste Problem.
… ich deine API nicht testen kann
Ich baue eine super Anwendung und binde deine API ein. Kompiliert, fertig. Für Testzwecke generiere ich mir aus deiner API-Dokumentation (OpenAPI und Swagger Tools sei Dank) sogar einen Mock Server, gegen den ich teste. So weit, so gut. Aber irgendwie möchte ich schon noch ein paar wirkliche Integrationstests durchführen. Aber leider hast du keinen Test- bzw. Tryout-Endpunkt, auf den ich zugreifen kann. Vielleicht hast du den aber sogar, ich kann jedoch nicht testen, weil ich selbst kein Resource Owner bin. D.h. mir gehören keine Daten und aufgrund der Autorisierung darf ich auf keinerlei Daten zugreifen – ich kann z.B. Fahrzeugdaten nicht auslesen, weil ich selbst kein Testfahrzeug bei dir habe.
Darum …
Stell dir vor, du wärst ein Consumer und wünschst dir eine gute API. Und dann versuche diese Wünsche auch als Provider umzusetzen. Vielleicht helfen dir folgende Guidelines dabei:
- Erstelle ein consumerfreundliches API Design – vergiss die Fehlerfälle nicht!
- Versioniere deine API
- Implementiere eine robuste und stabile Anwendung
- Monitore deine API selbst und reagiere proaktiv auf Probleme
- Dokumentiere so, als würdest du deine API nicht kennen
- Ermögliche Tests
- Informiere deine Consumer über Änderungen und auch Probleme
Vielleicht werden deine API Consumer dich trotzdem nicht lieben – aber hoffentlich deine API 😉Und wenn du ein Consumer bist und kräftig in jeder Zeile genickt hast: Stell dir vor, DU wärst der API Provider.