Come deprecare un'API senza perdere gli sviluppatori
7 min di lettura
Deprecare un’API significa annunciare che qualcosa funziona ancora oggi e smetterà di funzionare in una data dichiarata, e poi mantenere entrambe le metà di quella promessa. La maggior parte delle deprecazioni fallisce sulla seconda metà: la data slitta silenziosamente, oppure arriva e i chiamanti che non hanno mai visto l’avviso lo scoprono da un errore. Una deprecazione è finita quando ogni chiamante interessato è migrato o gli è stato detto, individualmente, che non lo è.
Cos’è la deprecazione di un’API?
La deprecazione è il periodo tra l’annuncio che un endpoint, campo o versione sta per sparire e la sua effettiva rimozione. Durante quel periodo il vecchio comportamento continua a funzionare, la documentazione dice che sta per andarsene, e ogni risposta porta un avviso leggibile da macchina. La rimozione è l’evento separato, successivo, spesso chiamato sunset. I due si confondono, e la confusione è dove avviene il danno: “deprecated” inizia a significare “forse è già sparito”, e i chiamanti smettono di fidarsi di entrambe le parole.
| Termine | Significato | Su cosa possono contare i chiamanti |
|---|---|---|
| Deprecated | Annunciato come in via di sparizione, funziona ancora | Comportamento completo fino alla data di sunset |
| Sunset | La data in cui smette di funzionare | Nulla dopo questa data |
| Retired / rimosso | Sparito; le richieste falliscono | Un errore, idealmente uno che nomina il sostituto |
| Legacy | Indefinito. Evitare la parola | Nulla, che è il problema |
Quanto dovrebbe durare un periodo di deprecazione?
Abbastanza perché un chiamante lo scopra e faccia il lavoro, misurato da quando l’avviso lo ha raggiunto piuttosto che da quando l’avete scritto. Novanta giorni è il minimo comune per un’API web pubblica. Dodici mesi è normale per qualsiasi cosa incorporata in software che gli utenti finali installano, perché la correzione deve passare anche attraverso il loro processo di rilascio. Le linee guida di Google sul versioning, AIP-185, chiedono un periodo di transizione ragionevole e raccomandano 180 giorni persino prima di rimuovere funzionalità beta, e Kubernetes documenta la sua politica di deprecazione in conteggio di rilasci piuttosto che mesi, che è l’unità corretta quando i vostri chiamanti aggiornano per versione.
Scegliete un periodo, scrivetelo come politica, e smettete di deciderlo per ogni cambiamento. Una politica pubblicata trasforma ogni deprecazione da una negoziazione in un’applicazione di una regola.
Scrivere la politica di deprecazione copre l’inizio della finestra; ritirare una versione di API copre l’avviso separato necessario alla fine, quando il periodo scade davvero e la versione smette di funzionare.
Il calendario di deprecazione
Quattro date, annunciate insieme il primo giorno. Ciascuna è una voce di changelog separata quando arriva, così la storia viene raccontata quattro volte a chiunque legga solo il changelog.
- Annunciare. La voce dice cosa viene deprecato, perché, cosa lo sostituisce, e la data di sunset. La documentazione della vecchia cosa guadagna un banner che collega alla migrazione. Le risposte guadagnano gli header descritti sotto.
- Ricordare, a metà strada. Una seconda voce, e un messaggio diretto a ogni chiamante che ancora usa il vecchio comportamento. Questo è il passo che ha bisogno di dati di utilizzo: se non potete elencare chi sta ancora chiamando l’endpoint deprecato, non potete farlo, e vale la pena risolverlo prima della prossima deprecazione.
- Brownout, poco prima della data. Restituite errori per il vecchio comportamento per una finestra breve, un’ora o un giorno, poi ripristinatelo. I chiamanti che hanno perso ogni avviso lo scoprono ora, mentre c’è ancora tempo. GitHub ha usato brownout programmati prima di ritirare l’autenticazione con password per l’API, ed è il passo singolo più efficace di questa lista.
- Sunset. Rimuovetelo. L’errore che lo sostituisce nomina il sostituto e collega la guida di migrazione. Mantenete l’errore in posizione a lungo; un 404 non dice nulla a un chiamante.
Cosa dovrebbe dire un avviso di deprecazione?
Un avviso di deprecazione dice cosa sta sparendo, quando smette, cosa usare al suo posto, e chi è interessato. Ecco la forma, compilata:
GET /v1/reports/dailyè deprecato e smette di funzionare il 1° marzo 2027. È sostituito daGET /v2/reports?granularity=day, che restituisce gli stessi dati con uno schema stabile e paginazione. Interessa le 214 integrazioni che hanno chiamato l’endpoint v1 negli ultimi 30 giorni; se la vostra è una di queste, riceverete anche questo avviso via email. Guida di migrazione: [link]. Nulla cambia fino al 1° marzo 2027. Da quella data l’endpoint v1 restituisce410 Gonecon un link a questa voce.
Ogni frase porta qualcosa di cui la lettrice ha bisogno. Il conteggio delle integrazioni interessate dice a ciascuna lettrice se continuare a leggere. “Nulla cambia fino a” è la frase che permette a chi non è interessato di chiudere la scheda. La pagina esempi di changelog raccoglie voci di team che scrivono questa forma con coerenza, e vale la pena leggerne tre prima di scriverne la prima propria.
Quali header dovrebbe inviare un endpoint deprecato?
Inviate Deprecation, Sunset e un Link al successore, su ogni risposta dall’endpoint
deprecato, dal giorno dell’annuncio. L’header Deprecation
porta la data in cui la deprecazione è entrata in vigore; l’
header Sunset porta la data in cui l’endpoint
smette di rispondere; Link: <url>; rel="successor-version" indica cosa usare al suo posto.
HTTP/1.1 200 OK
Deprecation: @1756425600
Sunset: Mon, 01 Mar 2027 00:00:00 GMT
Link: <https://api.example.com/v2/reports>; rel="successor-version"
Link: <https://example.com/changelog/daily-reports>; rel="deprecation"
La maggior parte dei chiamanti non leggerà mai gli header di persona. Il loro valore sta nel fatto che il client HTTP, il gateway o il monitoraggio di un chiamante possono farlo, il che trasforma la vostra deprecazione in un allarme dalla loro parte piuttosto che una pagina dalla vostra. Gli SDK che spedite dovrebbero registrare un avviso quando ne vedono uno.
Chi è stato informato, e come lo sapete?
Questo è il passo che decide se il sunset è tranquillo o un incidente di supporto, ed è il più difficile da fare solo con un changelog. Una voce di changelog informa chiunque legga il changelog. Una deprecazione deve raggiungere le persone specifiche il cui codice sta per fallire, e il modo abituale di trovarle sono gli stessi dati di utilizzo di cui ha bisogno il promemoria a metà strada: le chiavi API, le app o gli account che hanno chiamato il comportamento deprecato recentemente.
Il ciclo che eseguiamo: la voce viene redatta dalla pull request che aggiunge la deprecazione, una persona rivede la formulazione e la data, e una volta pubblicata la voce stessa è la notifica. Chiunque abbia inviato dal widget un feedback sul problema, o una richiesta per il sostituto, diventato un issue GitHub che la pull request chiude, riceve un commento su quell’issue che dice che è stato rilasciato, con un link alla voce. Feed e widget servono la stessa voce a tutti gli altri, insieme a ogni altra voce nel changelog di API. Ciò che non facciamo è lasciare che la deprecazione diventi “rilasciata” prima che una persona l’abbia pubblicata; un avviso con la data sbagliata è peggio di nessun avviso.
Qualunque sia il vostro strumento, la domanda a cui dovete poter rispondere il giorno del sunset è: quali chiamanti stavano ancora usando questo la settimana scorsa, e a quali di loro l’abbiamo detto direttamente? Se la risposta è “abbiamo pubblicato qualcosa a riguardo”, il sunset non è pronto.
Qual è la differenza tra deprecare e versionare?
Versionare è come mantenete disponibile il vecchio comportamento mentre esiste il nuovo; deprecare è come ritirate quello vecchio. Una nuova versione API senza una politica di deprecazione per quella precedente è un impegno a mantenere entrambe per sempre. Una deprecazione senza versionamento è un cambiamento che rompe qualcosa con un ritardo. Vi servono entrambi, e la versione è la metà più facile. GraphQL è l’eccezione che vale la pena nominare: di solito non c’è alcun numero di versione da incrementare, e deprecazione di schema GraphQL copre come uno schema unico condiviso ritira un campo con una direttiva invece.
FAQ
Un endpoint deprecato dovrebbe continuare a funzionare esattamente come prima? Sì, fino alla data di sunset. Gli unici cambiamenti permessi sono gli header aggiunti e, verso la fine, un brownout programmato che avete annunciato in anticipo.
Quale codice di stato dovrebbe restituire un endpoint ritirato?
410 Gone, con un corpo e un header Link che punta al sostituto e alla voce di changelog. 404
dice che l’URL non è mai esistito, il che è falso e inutile.
Un periodo di deprecazione può essere accorciato? Solo per sicurezza. Se il vecchio comportamento è sfruttabile, ditelo, accorciate il periodo, e dite a ogni chiamante interessato direttamente piuttosto che affidarvi al changelog.
Devo deprecare un campo, o solo interi endpoint? Campi, parametri, valori enum, default e header hanno tutti bisogno dello stesso trattamento, perché ciascuno può rompere un chiamante corretto. Un campo rimosso è la deprecazione più comune e quella più spesso saltata.
Le affermazioni tecniche di questo articolo non sono state verificate in modo indipendente. Se qualcosa non è corretto, faccelo sapere e lo correggeremo.