Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

Pratiche migliori per la versioning delle API RESTful: perché v1 è il numero 1

Chris McFadden

24 mag 2017

Email

1 min read

Pratiche migliori per la versioning delle API RESTful: perché v1 è il numero 1

Chris McFadden

24 mag 2017

Email

1 min read

Pratiche migliori per la versioning delle API RESTful: perché v1 è il numero 1

Quindi, quanto può essere difficile gestire le versioni di un'API? La verità è che non è così difficile, ma ciò che è complicato è mantenere un po' di sanità mentale evitando di cadere inutilmente in un numero vertiginoso di versioni e sotto-versioni applicate a dozzine di endpoint API con compatibilità poco chiare.

I Cambiamenti Bruschi sono Male! API Versioning Buono!

Come chiunque abbia costruito o utilizzi regolarmente un API si rende conto prima o poi, le modifiche che interrompono sono molto negative e possono essere un difetto molto serio su un API altrimenti utile. Una modifica che interrompe è una modifica al comportamento di un API che può interrompere l'integrazione di un utente e causare molta frustrazione e perdita di fiducia tra il fornitore dell'API e l'utente. Le modifiche che interrompono richiedono che gli utenti vengano notificati in anticipo (con i dovuti mea culpas) piuttosto che una modifica che appare semplicemente, come una nuova funzionalità deliziosa. Il modo per evitare quella frustrazione è creare versioni di un API con la garanzia da parte del proprietario dell'API che non verranno introdotte modifiche sorprendenti in nessuna singola versione.

Quindi quanto può essere difficile creare versioni di un API? La verità è che non lo è, ma ciò che è difficile è mantenere una certa sanità mentale evitando di devolvere inutilmente in un numero vertiginoso di versioni e sottoversioni applicate su dozzine di endpoint API con compatibilità poco chiare.

Abbiamo introdotto v1 dell'API tre anni fa e non ci siamo resi conto che avrebbe continuato a essere forte fino ad oggi. Quindi come abbiamo continuato a fornire la migliore email delivery API per oltre due anni ma mantenendo la stessa versione dell'API? Questa stabilità è cruciale per gli sviluppatori che costruiscono applicazioni con email APIs in infrastruttura cloud, dove l'affidabilità e la coerenza sono fondamentali. Sebbene ci siano molte opinioni diverse su come creare versioni di REST APIs, spero che la storia del nostro umile ma potente v1 possa guidarti nel tuo cammino verso l'illuminazione del versioning di API.

REST È Best

L'API di SparkPost ha origine da quando eravamo Message Systems, prima delle nostre avventure nel cloud. A quel tempo eravamo impegnati con gli ultimi preparativi per il lancio beta di Momentum 4. Questo era un aggiornamento importante alla versione 3.x, il nostro MTA leader di mercato on-premise. Momentum 4 includeva una nuova UI completamente, analisi in tempo reale e, soprattutto, una nuova web API per l'iniezione e la generazione di messaggi, la gestione dei template e l'ottenimento delle metriche e-mail. La nostra visione era di un'architettura API first – dove anche l'interfaccia utente avrebbe interagito con gli endpoint API.

Una delle prime e migliori decisioni che abbiamo preso è stata quella di adottare uno stile RESTful. Dal tardo 2000 il transfer stato rappresentazionale (REST) basato su web API è lo standard de facto delle API cloud. Usare HTTP e JSON rende facile per gli sviluppatori, indipendentemente dal linguaggio di programmazione che usano – PHP, Ruby e Java – integrarsi con la nostra API senza conoscere o preoccuparsi della nostra tecnologia sottostante. Tuttavia, costruire API native per il cloud su larga scala può presentare sfide infrastrutturali inaspettate, come i limiti di scala DNS che abbiamo incontrato in AWS quando gestiamo il traffico API ad alto volume.

Scegliere di utilizzare l'architettura RESTful è stato facile. Scegliere una convenzione di versionamento non è stato altrettanto semplice. Inizialmente abbiamo rimandato la questione del versionamento non versionando affatto la beta. Tuttavia, nel giro di un paio di mesi la beta era nelle mani di alcuni clienti e abbiamo iniziato a sviluppare il nostro servizio cloud. Era ora di versionare. Abbiamo valutato due convenzioni di versionamento. La prima era mettere il versionamento direttamente nell'URI e la seconda era usare un header Accept. La prima opzione è più esplicita e meno complicata, il che è più facile per gli sviluppatori. Poiché amiamo gli sviluppatori, era la scelta logica.

L'API di SparkPost ha origine da quando eravamo Message Systems, prima delle nostre avventure nel cloud. A quel tempo eravamo impegnati con gli ultimi preparativi per il lancio beta di Momentum 4. Questo era un aggiornamento importante alla versione 3.x, il nostro MTA leader di mercato on-premise. Momentum 4 includeva una nuova UI completamente, analisi in tempo reale e, soprattutto, una nuova web API per l'iniezione e la generazione di messaggi, la gestione dei template e l'ottenimento delle metriche e-mail. La nostra visione era di un'architettura API first – dove anche l'interfaccia utente avrebbe interagito con gli endpoint API.

Una delle prime e migliori decisioni che abbiamo preso è stata quella di adottare uno stile RESTful. Dal tardo 2000 il transfer stato rappresentazionale (REST) basato su web API è lo standard de facto delle API cloud. Usare HTTP e JSON rende facile per gli sviluppatori, indipendentemente dal linguaggio di programmazione che usano – PHP, Ruby e Java – integrarsi con la nostra API senza conoscere o preoccuparsi della nostra tecnologia sottostante. Tuttavia, costruire API native per il cloud su larga scala può presentare sfide infrastrutturali inaspettate, come i limiti di scala DNS che abbiamo incontrato in AWS quando gestiamo il traffico API ad alto volume.

Scegliere di utilizzare l'architettura RESTful è stato facile. Scegliere una convenzione di versionamento non è stato altrettanto semplice. Inizialmente abbiamo rimandato la questione del versionamento non versionando affatto la beta. Tuttavia, nel giro di un paio di mesi la beta era nelle mani di alcuni clienti e abbiamo iniziato a sviluppare il nostro servizio cloud. Era ora di versionare. Abbiamo valutato due convenzioni di versionamento. La prima era mettere il versionamento direttamente nell'URI e la seconda era usare un header Accept. La prima opzione è più esplicita e meno complicata, il che è più facile per gli sviluppatori. Poiché amiamo gli sviluppatori, era la scelta logica.

L'API di SparkPost ha origine da quando eravamo Message Systems, prima delle nostre avventure nel cloud. A quel tempo eravamo impegnati con gli ultimi preparativi per il lancio beta di Momentum 4. Questo era un aggiornamento importante alla versione 3.x, il nostro MTA leader di mercato on-premise. Momentum 4 includeva una nuova UI completamente, analisi in tempo reale e, soprattutto, una nuova web API per l'iniezione e la generazione di messaggi, la gestione dei template e l'ottenimento delle metriche e-mail. La nostra visione era di un'architettura API first – dove anche l'interfaccia utente avrebbe interagito con gli endpoint API.

Una delle prime e migliori decisioni che abbiamo preso è stata quella di adottare uno stile RESTful. Dal tardo 2000 il transfer stato rappresentazionale (REST) basato su web API è lo standard de facto delle API cloud. Usare HTTP e JSON rende facile per gli sviluppatori, indipendentemente dal linguaggio di programmazione che usano – PHP, Ruby e Java – integrarsi con la nostra API senza conoscere o preoccuparsi della nostra tecnologia sottostante. Tuttavia, costruire API native per il cloud su larga scala può presentare sfide infrastrutturali inaspettate, come i limiti di scala DNS che abbiamo incontrato in AWS quando gestiamo il traffico API ad alto volume.

Scegliere di utilizzare l'architettura RESTful è stato facile. Scegliere una convenzione di versionamento non è stato altrettanto semplice. Inizialmente abbiamo rimandato la questione del versionamento non versionando affatto la beta. Tuttavia, nel giro di un paio di mesi la beta era nelle mani di alcuni clienti e abbiamo iniziato a sviluppare il nostro servizio cloud. Era ora di versionare. Abbiamo valutato due convenzioni di versionamento. La prima era mettere il versionamento direttamente nell'URI e la seconda era usare un header Accept. La prima opzione è più esplicita e meno complicata, il che è più facile per gli sviluppatori. Poiché amiamo gli sviluppatori, era la scelta logica.

API Governance

Con una convenzione di versioning selezionata, avevamo più domande. Quando avremmo incrementato la versione? Che cos'è un cambiamento determinante?  Reviseremmo l'intero API o solo alcuni endpoint? In SparkPost, abbiamo più team che lavorano su diverse parti del nostro API. All'interno di questi team, le persone lavorano su diversi endpoint in tempi diversi. Pertanto, è molto importante che il nostro API sia coerente nell'uso delle convenzioni. Questo era più grande del versioning.

Abbiamo istituito un gruppo di governance includendo ingegneri rappresentanti ogni team, un membro del team di Product Management e il nostro CTO. Questo gruppo è responsabile dell'istituzione, documentazione e applicazione delle nostre convenzioni API tra tutti i team. Un canale Slack di governance delle API è anche utile per dibattiti animati sull'argomento.

Il gruppo di governance ha identificato una serie di modi in cui le modifiche possono essere introdotte nell'API che sono vantaggiose per l'utente e non costituiscono un cambiamento determinante. Questi includono:

  • Una nuova risorsa o endpoint API

  • Un nuovo parametro opzionale

  • Una modifica a un endpoint API non pubblico

  • Una nuova chiave opzionale nel corpo POST JSON

  • Una nuova chiave restituita nel corpo di risposta JSON


Al contrario, un cambiamento determinante includeva qualsiasi cosa che potesse interrompere un'integrazione dell'utente come:

  • Un nuovo parametro obbligatorio

  • Una nuova chiave obbligatoria nei corpi POST

  • Rimozione di un endpoint esistente

  • Rimozione di un metodo di richiesta endpoint esistente

  • Un comportamento interno materialmente diverso di una chiamata API – come un cambiamento al comportamento predefinito.

The Big 1.0

Come abbiamo documentato e discusso queste convenzioni, siamo anche giunti alla conclusione che fosse nell'interesse di tutti (incluso il nostro!) evitare di apportare cambiamenti dirompenti all'API poiché la gestione di più versioni aggiunge un bel po' di impegno. Abbiamo deciso che c'erano alcune cose che avremmo dovuto sistemare con la nostra API prima di impegnarci nel “v1”.

Inviare una semplice email richiedeva troppo sforzo. Per “mantenere le cose semplici”, abbiamo aggiornato il corpo del POST per garantire che entrambi i casi d'uso, semplici e complessi, siano accomodati. Il nuovo formato era anche più a prova di futuro. In secondo luogo, abbiamo affrontato un problema con il Metrics endpoint. Questo endpoint utilizzava un parametro “group_by” che avrebbe modificato il formato del corpo di risposta GET in modo tale che la prima chiave sarebbe stata il valore del parametro di gruppo. Non sembrava molto RESTful, quindi abbiamo suddiviso ogni gruppo in un endpoint separato. Infine, abbiamo controllato ciascun endpoint e apportato alcune modifiche qua e là per garantire che fossero conformi agli standard.

Documentazione Accurata

È importante avere documentazione API accurata e utilizzabile per evitare modifiche che interrompono, di tipo deliberato o involontario. Abbiamo deciso di utilizzare un approccio semplice alla documentazione API sfruttando un linguaggio Markdown chiamato API Blueprint e gestire i nostri documenti su Github. La nostra comunità contribuisce e migliora questi documenti open source.  Manteniamo anche un set non pubblico di documenti su Github per API e endpoint interni.

Inizialmente, abbiamo pubblicato i nostri documenti su Apiary, un ottimo strumento per prototipare e pubblicare documenti API. Tuttavia, l'inclusione di Apiary nel nostro sito web non funziona sui dispositivi mobili, quindi ora utilizziamo Jekyll per generare invece documenti statici.  I nostri ultimi SparkPost API docs ora si caricano rapidamente e funzionano bene sui dispositivi mobili, il che è importante per i sviluppatori che non sono sempre seduti al loro computer.

Separare Deployment da Release

Abbiamo imparato presto il prezioso trucco di separare un deployment da un rilascio. In questo modo è possibile distribuire frequentemente modifiche quando sono pronte attraverso consegna e distribuzione continue, ma non le annunciamo sempre pubblicamente o le documentiamo allo stesso tempo. Non è raro per noi distribuire un nuovo endpoint API o un miglioramento a un endpoint API esistente e utilizzarlo dall'interno dell'interfaccia utente o con strumenti interni prima di documentarlo pubblicamente e supportarlo. In questo modo possiamo apportare alcune modifiche per la facilità d'uso o la conformità agli standard senza preoccuparci di creare un temuto cambiamento che rompa. Una volta che siamo soddisfatti del cambiamento, lo aggiungiamo alla nostra documentazione pubblica.

Accidenti!

È giusto ammettere che ci sono stati momenti in cui non siamo stati fedeli ai nostri ideali di “no breaking changes” e vale la pena imparare da questi. In un'occasione abbiamo deciso che sarebbe stato meglio per gli utenti se una determinata proprietà fosse predefinita su true invece che su false. Dopo aver implementato la modifica, abbiamo ricevuto diverse lamentele dagli utenti poiché il comportamento era cambiato inaspettatamente.  Abbiamo annullato la modifica e aggiunto un'impostazione a livello di account, un approccio sicuramente più user-friendly.

Occasionalmente siamo tentati di introdurre breaking changes come risultato di correzioni di bug. Tuttavia, abbiamo deciso di lasciare queste idiosincrasie piuttosto che rischiare di compromettere le integrazioni dei clienti per il bene della coerenza.

Ci sono rari casi in cui abbiamo preso la seria decisione di apportare una modifica che rompe qualcosa, come deprecare una risorsa o un metodo API, nell'interesse della comunità utente più ampia e solo dopo aver confermato che c'è poco o nessun impatto sugli utenti. Ad esempio, abbiamo deliberatamente scelto di modificare il comportamento di risposta della Suppression API, ma solo dopo aver attentamente valutato i benefici e gli impatti per la comunità e comunicato attentamente la modifica ai nostri utenti. Tuttavia, non introduceremmo mai una modifica che abbia una remota possibilità di influenzare direttamente l'invio di un’email di produzione dell’utente.

Connettiamoci con un esperto di Bird.
Scopri tutta la potenza del Bird in 30 minuti.

Inviando, accetti che Bird possa contattarti riguardo ai nostri prodotti e servizi.

Puoi annullare l'iscrizione in qualsiasi momento. Consulta la Informativa sulla Privacy di Bird per i dettagli sul trattamento dei dati.

Azienda

Newsletter

Rimani aggiornato con Bird attraverso aggiornamenti settimanali nella tua inbox.

Connettiamoci con un esperto di Bird.
Scopri tutta la potenza del Bird in 30 minuti.

Inviando, accetti che Bird possa contattarti riguardo ai nostri prodotti e servizi.

Puoi annullare l'iscrizione in qualsiasi momento. Consulta la Informativa sulla Privacy di Bird per i dettagli sul trattamento dei dati.

Azienda

Newsletter

Rimani aggiornato con Bird attraverso aggiornamenti settimanali nella tua inbox.

Connettiamoci con un esperto di Bird.
Scopri tutta la potenza del Bird in 30 minuti.

Inviando, accetti che Bird possa contattarti riguardo ai nostri prodotti e servizi.

Puoi annullare l'iscrizione in qualsiasi momento. Consulta la Informativa sulla Privacy di Bird per i dettagli sul trattamento dei dati.

R

Raggiungi

G

Grow

M

Manage

A

Automate

Azienda

Newsletter

Rimani aggiornato con Bird attraverso aggiornamenti settimanali nella tua inbox.