Im Gespräch: Kacper Nowicki über Best Practices der API-Entwicklung

Kacper Nowicki ist seit Anfang 2015 Chief Technology Officer (CTO) der Reisesuchmaschine GoEuro. In dieser Rolle, aber auch durch seine Arbeiten bei Google zuvor hat er profunde Kenntnisse in der API-Entwicklung.

vorlesen Druckansicht 4 Kommentare lesen
Lesezeit: 10 Min.
Von
  • Alexander Neumann
Inhaltsverzeichnis

Kacper Nowicki ist seit Anfang 2015 Chief Technology Officer (CTO) der Reisesuchmaschine GoEuro. In dieser Rolle, aber auch durch seine Arbeiten bei Google zuvor hat er profunde Kenntnisse in der API-Entwicklung.

heise Developer: Herr Nowicki, Ihr Unternehmen, die Reisesuchmaschine GoEuro.de, nutzt Daten mehrerer hundert APIs. Können Sie uns ein paar architektonische Tricks nennen, wie Sie all diese Daten vereinigen?

Kacper Nowicki: Als wir unsere ersten Anbieter implementierten, hatten wir keine Ahnung, wie man das Kernsystem verallgemeinern kann. Seitdem haben wir jedoch viele architektonische Veränderungen vorgenommen und sind gerade in einem weiteren Umstrukturierungsprozess. Eine vernünftige modulare Architektur und ein gutes Datenmodell – unabhängig von den Anbietern – sorgen dafür, dass der partnerspezifische Code auf ein Minimum reduziert bleibt. Wir iterieren schnell und fügen neue Eigenschaften hinzu, sobald wir die Möglichkeit sehen, die Nutzerfreundlichkeit zu erhöhen.

Mehr Infos

Kacper Nowicki ...

... war bis Anfang 2015 technischer Leiter bei Google und ist seitdem CTO der Reisesuchmaschine GoEuro. Er ist Softwarearchitekt und -Ingenieur mit über zwanzig Jahren Erfahrung in Software-Design und -entwicklung. In den acht Jahren bei Google hat er das polnische Technikteam aufgebaut und bei der Entwicklung des Suchmechanismus sowie bei Infrastruktur- und Cloud-Produkten mitgewirkt.

Wir haben API-Treiber für jeden Anbieter implementiert. Sie exportieren die Struktur allgemeiner Daten wie Verbindungen und Reiseangebote. Es reicht nicht aus, lediglich API-Treiber für jeden Anbieter zu implementieren: Wir fügen zudem Tests hinzu, die sicherstellen, dass der spezifische Treiber API-gerecht funktioniert (es kommt vor, dass Anbieter uns nicht über Veränderungen informieren oder sie Veränderungen durchführen, die unerwartet einen Effekt auf unsere Nutzung haben). Außerdem fügen wir Mock-Objekte für die neuen APIs hinzu, sodass wir das Kernsystem ohne die Live-Verbindung zur API testen können. Auf diesem Wege sind wir unabhängig, falls ein System ausfällt oder unerwartete Ergebnisse liefert.

heise Developer: Auf einer komplett anonymen Basis: Können Sie uns einige Beispiele besonders schwacher APIs nennen? Was muss man Ihrer Meinung nach tun, um wirklich schlechte APIs zu generieren, beziehungsweise was sind hier klassische Anti-Pattern?

Nowicki: Ein schreckliches Beispiel ist die SOAP-basierte API eines gewissen Bahnanbieters. Sie wurde vor langer Zeit für Fahrscheinautomaten entwickelt, und niemand in besagter Firma versteht wirklich das Prinzip, das dahinter steht. In solchen Fällen arbeiten wir eng mit den Anbietern zusammen, debuggen uns durch die API und bauen unseren Service durch das Trial-and-Error-Prinzip auf.

Ein verbreitetes Anti-Pattern ist eine fehlende Dokumentation für eine API. Eine andere Fehlerquelle, die unsere Entwicklung verlangsamt, ist schlicht der Zugang zur Infrastruktur des Anbieters. Sie haben normalerweise Test- und Produktionssysteme; die benötigen aber unterschiedliche Zugangsdaten, IP-Whitelist-Verfahren, VPN et cetera. Wir wissen dann nicht, wo das Problem liegt, und bekommen einfach nur eine kryptische Nachricht.

heise Developer: Was würden Sie Entwicklern empfehlen, die eine API für einen neuen Service entwickeln müssen? Gibt es bestimmte empfehlenswerte Entwurfsmuster?

Nowicki: Vielleicht ein wenig indirekter: Da APIs immer konsumentenfreundlich sein müssen und sich die Ansprüche der Konsumenten häufig ändern, muss man fähig sein, schnell auf Veränderungen zu reagieren. Ein gutes Gerüst nach den SOLID-Prinzipien (Single Responsibility, Open-closed, Liskov Substitution, Interface Segregation and Dependency Inversion; Anm. Red.) ist ausschlaggebend. Eine durchgehende Testabdeckung für alle Unternehmensanforderungen (die der Konsumenten) sind ebenfalls ein Teil der allgemein bewährten Verfahrensweise. Neue Konsumenten können anhand der Tests nachvollziehen, wie die API zu nutzen ist und welche Antworten zu erwarten sind. Im Allgemeinen macht es Sinn, die Modelle so flach wie möglich zu halten und sich an etablierten Standards wie REST oder SOAP zu orientieren.

heise Developer: Aufgrund von Sicherheitsbedenken bieten viele Anbieter ihre API-Dokumentation nur mit sogenannten NDAs (Geheimhaltungsverträgen) an. Ist das Ihrer Meinung nach ein lohnenswerter Prozess?

Nowicki: Meiner persönlichen Meinung nach sollte man sich auf die Öffnung und nicht auf den Schutz konzentrieren. Während mit APIs wertvolle Daten angeboten werden und Nutzer für den Zugang zahlen müssen, ließen sich API-Spezifizierungen, -Dokumentationen und -Beispiele stattdessen öffentlich anbieten. Übrigens ist es auch gut, Feedback zum eigenen Design zu erhalten. Wir verlangen Code-Reviews für allen bei GoEuro geschriebenen Code.

heise Developer: WebSockets und REST-Schnittstellen konkurrieren mit den klassischen Modellen um die dominierende Stellung in der Datentransportsphäre. Denken Sie, dass sie es, trotz des Overheads der "neuen" Kommunikationsmethoden, Wert sind?

Nowicki: Es kommt darauf an. Meiner Meinung nach haben die APIs und Technologien verschiedene Rollen und lassen sich für diverse Integrationstypen nutzen. Wenn viele unterschiedliche Nutzer für eine API erwartet werden, sollte ein Standard genutzt werden, den viele Werkzeuge unterstützen und der einfach für Partner zu implementieren und zu debuggen ist. Gibt es eigene Klienten (Web oder mobile App), sollte auch auf weitverbreitete Netzwerktechniken geachtet werden. Dann lässt sich von der Lastverteilung von HTTP, der Sicherheit von HTTPS et cetera profitieren.

Da beide erwähnten API-Typen WAN-Netzwerk-Latenzzeiten zwischen Klienten und Servern annehmen, ist es das Beste, sie so zu strukturieren, dass Klienten eine kleine Anzahl an Anfragen stellen können und eine Business- in verschiedene Netzwerk-Interaktionen zu übersetzen ist. Für interne Services, wie ein Cluster aus Microservices, die in einer kontrollierten lokalen Netzwerkumgebung eingesetzt werden, sieht die Sache anders aus. Wir würden gern mehrere Anfragen unter einer Millisekunde zwischen den Servern stellen. Für GoEuro evaluieren wir hierzu derzeit unterschiedliche Techniken und ziehen Google Protocol Buffers und gRPC als eine Plattform in Betracht. Ich habe viele Jahre interne Versionen dieser Techniken bei Google verwendet.

heise Developer: Wie wichtig ist es, Beispiel-Code zur Hand zu haben? Ist es die Mühe Wert, einen zu schreiben, oder sollte man seine Zeit lieber in weitere Features und/oder eine bessere Gesamtdokumentation investieren?

Nowicki: Code-Beispiele sind extrem nützlich. Häufig sieht man API-Dokumentationen, in denen bestimmte Begriffe benutzt werden, für die jedoch keine spezifische Dokumentation zu finden ist. Es gibt eine Spezifikation für Datenfelder, aber was sollten die Werte sein? Ein Code-Beispiel würde im Normalfall dafür sorgen, dass keine Verwirrung aufkommt und unnötige Workarounds durch die Trial-and-Error-Methode vermieden werden. Es ist wahrscheinlich das Einfachste, wenn sich der Beispiel-Code in einer Testumgebung ausprobieren lässt und bestimmte Anfrageparameter und die Bedeutung der Antworten ergänzt.