Bewährte Praktiken für die Versionierung von RESTful APIs: Warum v1 die Nummer 1 ist

Bewährte Praktiken für die Versionierung von RESTful APIs: Warum v1 die Nummer 1 ist

Bewährte Praktiken für die Versionierung von RESTful APIs: Warum v1 die Nummer 1 ist

May 24, 2017

Herausgegeben von

Herausgegeben von

Chris McFadden

Chris McFadden

-

Kategorie:

Kategorie:

E-Mail

E-Mail

Ready to see Bird
in action?

Ready to see Bird
in action?

RESTful API Versioning Best Practices: Why v1 is #1

Breaking Changes Bad!  API Versioning Good!

Wie jeder, der eine API entwickelt hat oder regelmäßig nutzt, früher oder später feststellen wird, sind abbrechende Änderungen sehr schlecht und können eine ansonsten nützliche API sehr stark beeinträchtigen. Eine einschneidende Änderung ist eine Änderung des Verhaltens einer API, die die Integration eines Benutzers unterbrechen und zu einer Menge Frustration und einem Vertrauensverlust zwischen dem API-Anbieter und dem Benutzer führen kann. Einschneidende Änderungen erfordern, dass die Benutzer im Voraus benachrichtigt werden (mit begleitenden Entschuldigungen), im Gegensatz zu einer Änderung, die einfach auftaucht, wie z. B. eine erfreuliche neue Funktion. Der Weg, diese Frustration zu vermeiden, ist die Versionierung einer API mit der Zusicherung des API-Eigentümers, dass innerhalb einer einzigen Version keine überraschenden Änderungen eingeführt werden.


Wie schwer kann es also sein, eine API zu versionieren? Die Wahrheit ist, dass es nicht schwer ist. Was jedoch schwer ist, ist die Aufrechterhaltung eines gewissen Maßes an Vernunft, indem man sich nicht unnötig in eine schwindelerregende Anzahl von Versionen und Unterversionen verstrickt, die auf Dutzende von API-Endpunkten mit unklarer Kompatibilität angewendet werden.


We introduced v1 of the API three years ago and did not realize that it would be going strong to this day. So how have we continued to provide the best email delivery API for over two years but still maintain the same API version? While there are many unterschiedliche Meinungen on how to version REST APIs, I hope that the story of our humble yet powerful v1 might guide you on your way to API versioning enlightenment.


REST ist am besten

Die SparkPost-API stammt aus der Zeit, als wir noch Message Systems hießen, also vor unseren Abenteuern in der Cloud. Damals waren wir mit den letzten Vorbereitungen für den Beta-Start von Momentum 4 beschäftigt. Dies war ein großes Upgrade der Version 3.x, unserem marktführenden On-Premise-MTA. Momentum 4 enthielt eine völlig neue Benutzeroberfläche, Echtzeit-Analysen und vor allem eine neue Web-API für die Injektion und Generierung von Nachrichten, die Verwaltung von Vorlagen und den Erhalt von E-Mail-Metriken. Unsere Vision war eine API-First-Architektur, bei der sogar die Benutzeroberfläche mit API-Endpunkten interagieren würde.


One of the earliest and best decisions we made was to adopt a RESTful style. Since the late 2000s representational state transfer (REST) based web APIs are the de-facto standard of cloud APIs. Using HTTP and JSON makes it easy for developers, regardless of which programming language they use – PHP, Ruby, and Java – to integrate with our API without knowing or caring about our underlying technology.


Choosing to use the RESTful architecture was easy. Choosing a versioning convention was not so easy. Initially we punted on the question of versioning by not versioning the beta at all. However, within a couple months the beta was in the hands of a few customers and we began building out our cloud service.  Time to version. We evaluated two versioning conventions. Die first was to put the versioning directly in the URI and the second was to use an Accept header. Die first option is more explicit and less complicated, which is easier for developers.  Since we love developers, it was the logical choice.


API-Verwaltung

With a versioning convention selected we had more questions. When would we bump the version? What is a breaking change?  Would we reversion the whole API or just certain endpoints? At SparkPost, we have multiple teams working on different parts of our API. Within those teams, people work on different endpoints at different times. Therefore, it’s very important that our API is consistent in the use of conventions. This was bigger than versioning.


We established a governance group including engineers representing each team, a member of the Product Management team, and our CTO. This group is responsible for establishing, documenting, and enforcing our API conventions across all teams. An API governance Slack channel also comes in handy for lively debates on the topic.


Die Governance-Gruppe hat eine Reihe von Möglichkeiten ermittelt, wie Änderungen an der API vorgenommen werden können, die für den Benutzer von Vorteil sind und keine einschneidenden Änderungen darstellen. Dazu gehören:


  • Eine neue Ressource oder ein neuer API-Endpunkt

  • Ein neuer optionaler Parameter

  • Eine Änderung an einem nicht öffentlichen API-Endpunkt

  • Ein neuer optionaler Schlüssel im JSON-POST-Körper

  • Ein neuer Schlüssel, der im JSON-Antwortkörper zurückgegeben wird


Eine bahnbrechende Änderung ist hingegen alles, was die Integration eines Benutzers stören könnte, wie z. B.:


  • Ein neuer erforderlicher Parameter

  • Ein neuer erforderlicher Schlüssel in POST-Bodies

  • Entfernung eines bestehenden Endpunkts

  • Entfernung eines bestehenden Endpunkts request method

  • Ein wesentlich verändertes internes Verhalten eines API-Aufrufs - z. B. eine Änderung des Standardverhaltens.


Der Große 1.0

Als wir diese Konventionen dokumentierten und diskutierten, kamen wir auch zu dem Schluss, dass es im Interesse aller (einschließlich unseres!) ist, Änderungen an der API zu vermeiden, da die Verwaltung mehrerer Versionen einen erheblichen Mehraufwand bedeutet. Wir beschlossen, dass wir ein paar Dinge an unserer API beheben sollten, bevor wir uns auf "v1" festlegen.


Sending a simple email required way too much effort.  To “keep the simple things simple” we updated the POST body to ensure that both simple and complex use cases are accommodated.  The new format was more future-proof as well.  Secondly we addressed a problem with the Metrics endpoint. This endpoint used a “group_by” parameter that would change the format of the GET response body such that the first key would be the value of the group by parameter. That did not seem very RESTful so we broke each group by into a separate endpoint. Finally we audited each endpoint and made minor changes here and there to ensure they conformed with the standards.


Genaue Dokumentation

It is important to have accurate and usable API documentation to avoid breaking changes, of the deliberate or unintentional kind. We decided to use a simple API documentation approach leveraging a Markdown language called API-Entwurf and unsere Dokumente in Github verwalten. Our community contributes and improves upon these open source docs.  We also maintain a nonpublic set of docs in Github for internal APIs and endpoints.


Initially, we published our docs to Bienenhaus, a great tool for prototyping and publishing API docs. However, embedding Apiary into our website doesn’t work on mobile devices so we now use Jekyll to generate static docs instead.  Our latest SparkPost-API-Dokumente now load quickly and work well on mobile devices which is important for developers who are not always sitting at their computer.


Trennung von Einsatz und Freigabe

Wir haben schon früh den wertvollen Trick gelernt, die Bereitstellung von einer Veröffentlichung zu trennen. Auf diese Weise ist es möglich, Änderungen häufig zu implementieren, wenn sie durch kontinuierliche Lieferung und Bereitstellung bereit sind, aber wir kündigen sie nicht immer gleichzeitig öffentlich an oder dokumentieren sie. Es ist nicht ungewöhnlich, dass wir einen neuen API-Endpunkt oder eine Verbesserung eines bestehenden API-Endpunkts bereitstellen und ihn in der Benutzeroberfläche oder mit internen Tools verwenden, bevor wir ihn öffentlich dokumentieren und unterstützen. Auf diese Weise können wir einige Optimierungen für die Benutzerfreundlichkeit oder die Konformität mit Standards vornehmen, ohne uns Sorgen machen zu müssen, eine gefürchtete Änderung vorzunehmen. Sobald wir mit der Änderung zufrieden sind, fügen wir sie in unsere öffentliche Dokumentation ein.


Oje!

It is only fair to admit that there have been times where we have not lived up to our “no breaking changes” ideals and these are worth learning from. On one occasion we decided it would be better for users if a certain property defaulted to true instead of false. After we deployed the change we received several complaints from users since the behavior had changed unexpectedly.  We reverted the change and added an account level setting – a much more user friendly approach for sure.


Gelegentlich sind wir versucht, im Zuge von Fehlerbehebungen Änderungen vorzunehmen, die zu einem Bruch führen. Wir haben uns jedoch entschlossen, diese Eigenheiten in Ruhe zu lassen, anstatt zu riskieren, dass die Integrationen unserer Kunden um der Konsistenz willen unterbrochen werden.


There are rare cases where we made the serious decision to make a breaking change – such as deprecating an API resource or method – in the interest of the greater user community and only after confirming that there is little to no impact to users. For example, we deliberately made the choice to alter the response behavior of the Suppression API but only after carefully weighing the benefits and impacts zum community and carefully communicating the change to our users. However, we would never introduce a change that has a remote possibility of directly impacting the sending of a user’s production email.

Your new standard in Marketing, Pay & Sales. It's Bird

The right message -> zum right person -> am right time.

By clicking "See Bird" you agree to Bird's Hinweis zum Datenschutz.

Your new standard in Marketing, Pay & Sales. It's Bird

The right message -> to the right person -> am right time.

By clicking "See Bird" you agree to Bird's Hinweis zum Datenschutz.