Bereik

Grow

Manage

Automate

Bereik

Grow

Manage

Automate

RESTful API Versievormings Best Practices: Waarom v1 de #1 is

Chris McFadden

24 mei 2017

E-mail

1 min read

RESTful API Versievormings Best Practices: Waarom v1 de #1 is

Chris McFadden

24 mei 2017

E-mail

1 min read

RESTful API Versievormings Best Practices: Waarom v1 de #1 is

Dus hoe moeilijk kan het zijn om een API te versies? De waarheid is dat het niet moeilijk is, maar wat wel moeilijk is, is het behouden van enige gezond verstand door niet onnodig te vervallen in een duizelingwekkend aantal versies en subversies die worden toegepast over tientallen API-eindpunten met onduidelijke compatibiliteiten.

Breaking Changes Slecht! API Versioning Goed!

Zoals iedereen die een API heeft gebouwd of regelmatig gebruikt, vroeg of laat beseft, zijn breaking changes zeer slecht en kunnen ze een zeer ernstige smet zijn op een anders nuttige API. Een breaking change is een wijziging in het gedrag van een API die de integratie van een gebruiker kan breken en kan resulteren in veel frustratie en verlies van vertrouwen tussen de API-provider en gebruiker. Breaking changes vereisen dat gebruikers vooraf op de hoogte worden gesteld (met bijbehorende mea culpa's) in plaats van een wijziging die gewoon verschijnt, zoals een geweldig nieuwe functie. De manier om die frustratie te voorkomen is door een versie van een API aan te geven met garanties van de API-eigenaar dat er binnen een enkele versie geen verrassende wijzigingen worden geïntroduceerd.

Dus hoe moeilijk kan het zijn om een API te versienummeren? De waarheid is dat het niet moeilijk is, maar wat wel moeilijk is, is enige helderheid te behouden door niet zinloos te vervallen in een duizelingwekkend aantal versies en subversies, toegepast op tientallen API-eindpunten met onduidelijke compatibiliteiten.

We hebben drie jaar geleden v1 van de API geïntroduceerd en hadden niet verwacht dat het tot op de dag van vandaag sterk zou blijven. Dus hoe zijn we erin geslaagd om al meer dan twee jaar de beste e-mailbezorgings-API te bieden, maar nog steeds dezelfde API-versie te behouden? Deze stabiliteit is cruciaal voor ontwikkelaars die applicaties bouwen met e-mail-API's in cloudinfrastructuur, waar betrouwbaarheid en consistentie van het grootste belang zijn. Hoewel er veel verschillende meningen zijn over hoe REST-API's te versienummeren, hoop ik dat het verhaal van onze bescheiden maar krachtige v1 je kan begeleiden op weg naar verlichting in API-versienummering.

REST Is Best

De SparkPost API komt voort uit de tijd dat we Message Systems waren, voordat we onze avonturen in de cloud begonnen. Destijds waren we bezig met de laatste voorbereidingen voor de bètalancering van Momentum 4. Dit was een grote upgrade naar versie 3.x, onze marktleidende on-premise MTA. Momentum 4 bevatte een geheel nieuwe UI, realtime-analyse en, het belangrijkst, een nieuwe web API voor het injecteren en genereren van berichten, het beheren van sjablonen en het verkrijgen van e-mailstatistieken. Onze visie was een API-first architectuur – waarbij zelfs de UI met API-eindpunten zou communiceren.

Een van de vroegste en beste beslissingen die we namen, was het aannemen van een RESTful stijl. Sinds eind 2000 is representational state transfer (REST) gebaseerd op web APIs de de-facto standaard van cloud APIs. Het gebruik van HTTP en JSON maakt het makkelijk voor ontwikkelaars, ongeacht welke programmeertaal ze gebruiken – PHP, Ruby en Java – om met onze API te integreren zonder kennis of zorg over onze onderliggende technologie. Het bouwen van cloud-native APIs op schaal kan echter onverwachte infrastructurele uitdagingen met zich meebrengen, zoals de DNS-schaalbeperkingen die we tegenkwamen in AWS bij het verwerken van API-verkeer met groot volume.

Kiezen voor het gebruik van de RESTful architectuur was makkelijk. Het kiezen van een versieconventie was niet zo makkelijk. Aanvankelijk hebben we de kwestie van versiebeheer genegeerd door de bèta helemaal niet te versienummeren. Binnen een paar maanden was de bèta echter in handen van een paar klanten en begonnen we met de uitbreiding van onze clouddienst. Tijd om te versienummeren. We hebben twee versieconventies geëvalueerd. De eerste was om de versie direct in de URI te plaatsen en de tweede was om een Accept-header te gebruiken. De eerste optie is explicieter en minder ingewikkeld, wat het gemakkelijker maakt voor ontwikkelaars. Aangezien we dol zijn op ontwikkelaars, was het de logische keuze.

De SparkPost API komt voort uit de tijd dat we Message Systems waren, voordat we onze avonturen in de cloud begonnen. Destijds waren we bezig met de laatste voorbereidingen voor de bètalancering van Momentum 4. Dit was een grote upgrade naar versie 3.x, onze marktleidende on-premise MTA. Momentum 4 bevatte een geheel nieuwe UI, realtime-analyse en, het belangrijkst, een nieuwe web API voor het injecteren en genereren van berichten, het beheren van sjablonen en het verkrijgen van e-mailstatistieken. Onze visie was een API-first architectuur – waarbij zelfs de UI met API-eindpunten zou communiceren.

Een van de vroegste en beste beslissingen die we namen, was het aannemen van een RESTful stijl. Sinds eind 2000 is representational state transfer (REST) gebaseerd op web APIs de de-facto standaard van cloud APIs. Het gebruik van HTTP en JSON maakt het makkelijk voor ontwikkelaars, ongeacht welke programmeertaal ze gebruiken – PHP, Ruby en Java – om met onze API te integreren zonder kennis of zorg over onze onderliggende technologie. Het bouwen van cloud-native APIs op schaal kan echter onverwachte infrastructurele uitdagingen met zich meebrengen, zoals de DNS-schaalbeperkingen die we tegenkwamen in AWS bij het verwerken van API-verkeer met groot volume.

Kiezen voor het gebruik van de RESTful architectuur was makkelijk. Het kiezen van een versieconventie was niet zo makkelijk. Aanvankelijk hebben we de kwestie van versiebeheer genegeerd door de bèta helemaal niet te versienummeren. Binnen een paar maanden was de bèta echter in handen van een paar klanten en begonnen we met de uitbreiding van onze clouddienst. Tijd om te versienummeren. We hebben twee versieconventies geëvalueerd. De eerste was om de versie direct in de URI te plaatsen en de tweede was om een Accept-header te gebruiken. De eerste optie is explicieter en minder ingewikkeld, wat het gemakkelijker maakt voor ontwikkelaars. Aangezien we dol zijn op ontwikkelaars, was het de logische keuze.

De SparkPost API komt voort uit de tijd dat we Message Systems waren, voordat we onze avonturen in de cloud begonnen. Destijds waren we bezig met de laatste voorbereidingen voor de bètalancering van Momentum 4. Dit was een grote upgrade naar versie 3.x, onze marktleidende on-premise MTA. Momentum 4 bevatte een geheel nieuwe UI, realtime-analyse en, het belangrijkst, een nieuwe web API voor het injecteren en genereren van berichten, het beheren van sjablonen en het verkrijgen van e-mailstatistieken. Onze visie was een API-first architectuur – waarbij zelfs de UI met API-eindpunten zou communiceren.

Een van de vroegste en beste beslissingen die we namen, was het aannemen van een RESTful stijl. Sinds eind 2000 is representational state transfer (REST) gebaseerd op web APIs de de-facto standaard van cloud APIs. Het gebruik van HTTP en JSON maakt het makkelijk voor ontwikkelaars, ongeacht welke programmeertaal ze gebruiken – PHP, Ruby en Java – om met onze API te integreren zonder kennis of zorg over onze onderliggende technologie. Het bouwen van cloud-native APIs op schaal kan echter onverwachte infrastructurele uitdagingen met zich meebrengen, zoals de DNS-schaalbeperkingen die we tegenkwamen in AWS bij het verwerken van API-verkeer met groot volume.

Kiezen voor het gebruik van de RESTful architectuur was makkelijk. Het kiezen van een versieconventie was niet zo makkelijk. Aanvankelijk hebben we de kwestie van versiebeheer genegeerd door de bèta helemaal niet te versienummeren. Binnen een paar maanden was de bèta echter in handen van een paar klanten en begonnen we met de uitbreiding van onze clouddienst. Tijd om te versienummeren. We hebben twee versieconventies geëvalueerd. De eerste was om de versie direct in de URI te plaatsen en de tweede was om een Accept-header te gebruiken. De eerste optie is explicieter en minder ingewikkeld, wat het gemakkelijker maakt voor ontwikkelaars. Aangezien we dol zijn op ontwikkelaars, was het de logische keuze.

API Governance

Met een gekozen versieconventie hadden we meer vragen. Wanneer zouden we de versie aanpassen? Wat is een breaking change? Zouden we de hele API opnieuw versie nummeren of alleen bepaalde endpoints? Bij SparkPost werken we met meerdere teams aan verschillende delen van onze API. Binnen die teams werken mensen op verschillende momenten aan verschillende endpoints. Daarom is het erg belangrijk dat onze API consistent is in het gebruik van conventies. Dit was groter dan alleen versiebeheer.

We hebben een bestuursgroep opgericht met daarin ingenieurs die elk team vertegenwoordigen, een lid van het Product Management team en onze CTO. Deze groep is verantwoordelijk voor het opstellen, documenteren en handhaven van onze API-conventies over alle teams heen. Een API-governance Slack-kanaal is ook handig voor levendige discussies over dit onderwerp.

De bestuursgroep identificeerde een aantal manieren waarop wijzigingen in de API kunnen worden doorgevoerd die nuttig zijn voor de gebruiker en geen breaking change vormen. Deze omvatten:

  • Een nieuwe resource of API-endpoint

  • Een nieuwe optionele parameter

  • Een wijziging in een niet-openbare API-endpoint

  • Een nieuwe optionele sleutel in de JSON POST-body

  • Een nieuwe sleutel geretourneerd in de JSON-respons body


Omgekeerd omvatte een breaking change alles wat de integratie van een gebruiker zou kunnen verstoren, zoals:

  • Een nieuwe vereiste parameter

  • Een nieuwe vereiste sleutel in POST-bodies

  • Verwijdering van een bestaand endpoint

  • Verwijdering van een bestaand endpoint-aanvraagmethode

  • Een materieel ander intern gedrag van een API-aanroep – zoals een wijziging in het standaardgedrag.

The Big 1.0

Terwijl we deze conventies documenteerden en bespraken, kwamen we ook tot de conclusie dat het in ieders belang (inclusief het onze!) was om te voorkomen dat er wijzigingen in de API zouden worden aangebracht, aangezien het beheren van meerdere versies behoorlijk wat overhead met zich meebrengt. We besloten dat er een paar dingen waren die we moesten oplossen met onze API voordat we ons committeerden aan “v1”.

Het verzenden van een eenvoudige e-mail vergde veel te veel moeite. Om “de simpele dingen simpel te houden” hebben we de POST-body bijgewerkt om ervoor te zorgen dat zowel eenvoudige als complexe gebruiksscenario’s mogelijk zijn. Het nieuwe formaat was ook toekomstbestendiger. Ten tweede hebben we een probleem met het Metrics endpoint aangepakt. Dit endpoint gebruikte een “group_by” parameter die het formaat van de GET-responsbody zou wijzigen, zodat de eerste sleutel de waarde van de parameter group by zou zijn. Dat leek niet erg RESTful, dus hebben we elke group by in een apart endpoint gesplitst. Ten slotte hebben we elk endpoint gecontroleerd en hier en daar kleine wijzigingen aangebracht om ervoor te zorgen dat ze voldeden aan de standaarden.

Nauwkeurige Documentatie

Het is belangrijk om nauwkeurige en bruikbare API-documentatie te hebben om breaking changes te vermijden, of ze nu opzettelijk of onbedoeld zijn. We hebben besloten om een eenvoudige benadering van API-documentatie te gebruiken door gebruik te maken van een Markdown-taal genaamd API Blueprint en onze documentatie in Github beheren. Onze gemeenschap draagt bij aan en verbetert deze open source documenten. We onderhouden ook een niet-openbare set documenten in Github voor interne API's en endpoints.

Aanvankelijk publiceerden we onze documenten op Apiary, een geweldig hulpmiddel voor prototyping en publiceren van API-documentatie. Echter, het inbedden van Apiary in onze website werkt niet goed op mobiele apparaten, daarom gebruiken we nu Jekyll om in plaats daarvan statische documenten te genereren. Onze nieuwste SparkPost API-documentatie laadt nu snel en werkt goed op mobiele apparaten, wat belangrijk is voor ontwikkelaars die niet altijd achter hun computer zitten.

Deployment scheiden van Release

We leerden al vroeg de waardevolle truc van het scheiden van een implementatie van een release. Op deze manier is het mogelijk om vaak veranderingen door te voeren wanneer ze klaar zijn via continue levering en implementatie, maar we kondigen ze niet altijd publiekelijk aan of documenteren ze niet altijd tegelijkertijd. Het is niet ongewoon voor ons om een nieuwe API-endpoint te implementeren of een verbetering aan een bestaand API-endpoint te doen en deze te gebruiken binnen de UI of met interne tools voordat we het publiekelijk documenteren en ondersteunen. Op die manier kunnen we enkele aanpassingen doen voor bruikbaarheid of naleving van standaarden zonder ons zorgen te maken over het maken van een gevreesde breaking change. Zodra we tevreden zijn met de verandering voegen we het toe aan onze openbare documentatie.

Doh!

Het is alleen eerlijk om toe te geven dat er momenten zijn geweest waarop we onze “geen breaking changes”-idealen niet hebben waargemaakt, en het is de moeite waard om hiervan te leren. Op een gegeven moment besloten we dat het beter zou zijn voor gebruikers als een bepaalde instelling standaard op true stond in plaats van false. Nadat we de wijziging hadden doorgevoerd, ontvingen we verschillende klachten van gebruikers omdat het gedrag onverwachts was veranderd.  We draaiden de wijziging terug en voegden een accountniveau-instelling toe – een veel gebruiksvriendelijkere benadering, dat is zeker.

Soms worden we verleid om breaking changes door te voeren als gevolg van bugfixes. Echter, we besloten deze eigenaardigheden met rust te laten in plaats van het riskeren van het verbreken van klantintegraties voor het behoud van consistentie.

Er zijn zeldzame gevallen waarin we de serieuze beslissing namen om een breaking change door te voeren – zoals het afschaffen van een API-resource of -methode – in het belang van de bredere gebruikersgemeenschap en pas na bevestiging dat er weinig tot geen impact is op gebruikers. Bijvoorbeeld, we maakten bewust de keuze om het reactiegedrag van de Suppression API te wijzigen, maar alleen na zorgvuldig afwegen van de voordelen en nadelen voor de gemeenschap en het zorgvuldig communiceren van de wijziging naar onze gebruikers. Echter, we zouden nooit een wijziging introduceren die zelfs maar een geringe mogelijkheid heeft om direct invloed te hebben op het verzenden van een productie-e-mail van een gebruiker.

Laten we je in contact brengen met een Bird-expert.
Bekijk de volledige kracht van de Bird in 30 minuten.

Door te verzenden, ga je ermee akkoord dat Bird contact met je mag opnemen over onze producten en diensten.

U kunt zich op elk moment afmelden. Zie Bird's Privacyverklaring voor details over gegevensverwerking.

Nieuwsbrief

Blijf op de hoogte met Bird via wekelijkse updates in je inbox.

Laten we je in contact brengen met een Bird-expert.
Bekijk de volledige kracht van de Bird in 30 minuten.

Door te verzenden, ga je ermee akkoord dat Bird contact met je mag opnemen over onze producten en diensten.

U kunt zich op elk moment afmelden. Zie Bird's Privacyverklaring voor details over gegevensverwerking.

Nieuwsbrief

Blijf op de hoogte met Bird via wekelijkse updates in je inbox.

Laten we je in contact brengen met een Bird-expert.
Bekijk de volledige kracht van de Bird in 30 minuten.

Door te verzenden, ga je ermee akkoord dat Bird contact met je mag opnemen over onze producten en diensten.

U kunt zich op elk moment afmelden. Zie Bird's Privacyverklaring voor details over gegevensverwerking.

R

Bereik

G

Grow

M

Manage

A

Automate

Nieuwsbrief

Blijf op de hoogte met Bird via wekelijkse updates in je inbox.