Jak deprecjonować API, nie tracąc programistów
5 min czytania
Deprecjonowanie API to ogłoszenie, że coś nadal działa dzisiaj i przestanie działać w zadeklarowanej dacie, a potem dotrzymanie obu połówek tej obietnicy. Większość deprecacji zawodzi na drugiej połowie: data cicho się przesuwa, albo nadchodzi, a wywołujący, którzy nigdy nie widzieli powiadomienia, dowiadują się o tym z błędu. Deprecacja jest zakończona, gdy każdy dotknięty wywołujący albo zmigrował, albo indywidualnie usłyszał, że tego nie zrobił.
Czym jest deprecacja API?
Deprecacja to okres między ogłoszeniem, że endpoint, pole lub wersja znikną, a faktycznym ich usunięciem. W tym okresie stare zachowanie nadal działa, dokumentacja mówi, że odchodzi, a każda odpowiedź niesie ostrzeżenie czytelne dla maszyny. Usunięcie to oddzielne, późniejsze wydarzenie, często nazywane sunset. Te dwie rzeczy się mylą, a to mylenie jest tam, gdzie dzieje się szkoda: “deprecated” zaczyna znaczyć “może już zniknęło”, a wywołujący przestają ufać obu słowom.
| Termin | Znaczenie | Na co mogą liczyć wywołujący |
|---|---|---|
| Deprecated | Ogłoszone jako odchodzące, nadal działa | Pełne zachowanie do daty sunset |
| Sunset | Data, w której przestaje działać | Nic po tej dacie |
| Retired / usunięte | Zniknęło; żądania zawodzą | Błąd, idealnie taki, który wskazuje zamiennik |
| Legacy | Niezdefiniowane. Unikajcie tego słowa | Nic, co jest problemem |
Jak długi powinien być okres deprecacji?
Wystarczająco długi, by wywołujący się dowiedział i wykonał pracę, mierzony od chwili, gdy powiadomienie do niego dotarło, a nie od chwili, gdy je napisaliście. Dziewięćdziesiąt dni to powszechna dolna granica dla publicznego API webowego. Dwanaście miesięcy jest normalne dla wszystkiego, co jest osadzone w oprogramowaniu instalowanym przez użytkowników końcowych, ponieważ poprawka musi też przejść przez ich proces wydania. Wytyczne Google dotyczące wersjonowania, AIP-185, wymagają rozsądnego okresu przejściowego i zalecają 180 dni nawet przed usunięciem funkcjonalności beta, a Kubernetes dokumentuje swoją politykę deprecacji w liczbie wydań zamiast miesięcy, co jest właściwą jednostką, gdy wasi wywołujący aktualizują się według wersji.
Wybierzcie okres, zapiszcie go jako politykę, i przestańcie decydować o nim przy każdej zmianie. Opublikowana polityka zmienia każdą deprecację z negocjacji w zastosowanie zasady.
Zapisanie polityki deprecacji obejmuje początek okna czasowego; wygaszanie wersji API opisuje oddzielne powiadomienie potrzebne na końcu, gdy okres naprawdę się kończy, a wersja przestaje działać.
Harmonogram deprecacji
Cztery daty, ogłoszone razem pierwszego dnia. Każda to osobny wpis changelogu przy nadejściu, więc historia jest opowiadana czterokrotnie każdemu, kto czyta tylko changelog.
- Ogłoście. Wpis mówi, co jest deprecjonowane, dlaczego, co to zastępuje, i datę sunset. Dokumentacja starej rzeczy zyskuje baner linkujący do migracji. Odpowiedzi zyskują nagłówki opisane poniżej.
- Przypomnijcie, w połowie drogi. Drugi wpis, i bezpośrednia wiadomość do każdego wywołującego wciąż używającego starego zachowania. To krok, który potrzebuje danych o użyciu: jeśli nie możecie wymienić, kto wciąż wywołuje zdeprecjonowany endpoint, nie możecie tego zrobić, i warto to naprawić przed następną deprecacją.
- Brownout, krótko przed datą. Zwracajcie błędy dla starego zachowania przez krótkie okno, godzinę lub dzień, potem przywróćcie. Wywołujący, którzy przegapili każde powiadomienie, dowiadują się teraz, gdy jeszcze jest czas. GitHub użył zaplanowanych brownoutów przed wycofaniem uwierzytelniania hasłem dla API, i to najskuteczniejszy pojedynczy krok na tej liście.
- Sunset. Usuńcie to. Błąd, który to zastępuje, nazywa zamiennik i linkuje przewodnik migracji. Trzymajcie błąd na miejscu przez długi czas; 404 nic nie mówi wywołującemu.
Co powinno mówić powiadomienie o deprecacji?
Powiadomienie o deprecacji mówi, co odchodzi, kiedy się zatrzymuje, czego użyć zamiast tego, i kogo dotyczy. Oto forma, wypełniona:
GET /v1/reports/dailyjest zdeprecjonowany i przestaje działać 1 marca 2027. Jest zastępowany przezGET /v2/reports?granularity=day, który zwraca te same dane ze stabilnym schematem i paginacją. Dotyczy 214 integracji, które wywołały endpoint v1 w ciągu ostatnich 30 dni; jeśli wasza jest jedną z nich, otrzymacie też to powiadomienie e-mailem. Przewodnik migracji: [link]. Nic się nie zmienia do 1 marca 2027. Od tej daty endpoint v1 zwraca410 Gonez linkiem do tego wpisu.
Każde zdanie niesie coś, czego potrzebuje czytelniczka. Liczba dotkniętych integracji mówi każdej czytelniczce, czy powinna czytać dalej. “Nic się nie zmienia do” to zdanie, które pozwala tym niedotkniętym zamknąć kartę. Strona przykłady changelogu zbiera wpisy zespołów, które piszą tę formę konsekwentnie, i warto przeczytać trzy przed napisaniem swojego pierwszego.
Jakie nagłówki powinien wysyłać zdeprecjonowany endpoint?
Wysyłajcie Deprecation, Sunset i Link do następcy, w każdej odpowiedzi ze zdeprecjonowanego
endpointu, od dnia ogłoszenia. Nagłówek Deprecation
niesie datę, kiedy deprecacja weszła w życie; nagłówek Sunset
niesie datę, kiedy endpoint przestaje odpowiadać; Link: <url>; rel="successor-version" wskazuje,
czego użyć zamiast tego.
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"
Większość wywołujących nigdy sama nie przeczyta nagłówków. Ich wartość polega na tym, że klient HTTP, brama lub monitoring wywołującego mogą, co zamienia waszą deprecację w alert po ich stronie zamiast strony po waszej. SDK, które dostarczacie, powinny logować ostrzeżenie, gdy je zobaczą.
Kto został poinformowany, i skąd to wiecie?
To krok, który decyduje, czy sunset jest spokojny, czy staje się incydentem wsparcia, i jest najtrudniejszy do zrobienia samym changelogiem. Wpis changelogu informuje każdego, kto czyta changelog. Deprecacja musi dotrzeć do konkretnych ludzi, których kod zawiedzie, a zwykłym sposobem ich znalezienia są te same dane o użyciu, których potrzebuje przypomnienie w połowie drogi: klucze API, aplikacje lub konta, które ostatnio wywołały zdeprecjonowane zachowanie.
Pętla, którą prowadzimy: wpis jest przygotowywany z pull requesta dodającego deprecację, osoba recenzuje sformułowanie i datę, a po opublikowaniu sam wpis jest powiadomieniem. Każdy, czyja opinia z widżetu o tym problemie lub prośba o zamiennik stała się issue na GitHubie zamykanym przez ten pull request, dostaje w tym issue komentarz mówiący, że to zostało wydane, z linkiem do wpisu. Kanał i widget obsługują ten sam wpis dla wszystkich innych, wraz z każdym innym wpisem w changelogu API. Czego nie robimy, to pozwalanie, by deprecacja stała się “wydana”, zanim osoba ją opublikowała; powiadomienie z niewłaściwą datą jest gorsze niż brak powiadomienia.
Niezależnie od waszych narzędzi, pytanie, na które musicie umieć odpowiedzieć w dniu sunset, brzmi: którzy wywołujący wciąż tego używali w zeszłym tygodniu, i którym z nich powiedzieliśmy bezpośrednio? Jeśli odpowiedź to “opublikowaliśmy coś na ten temat”, sunset nie jest gotowy.
Jaka jest różnica między deprecjonowaniem a wersjonowaniem?
Wersjonowanie to sposób, w jaki utrzymujecie stare zachowanie dostępne, podczas gdy nowe istnieje; deprecacja to sposób, w jaki wysyłacie stare na emeryturę. Nowa wersja API bez polityki deprecacji dla poprzedniej to zobowiązanie do prowadzenia obu na zawsze. Deprecacja bez wersjonowania to zmiana łamiąca kompatybilność z opóźnieniem. Potrzebujecie obu, a wersja jest łatwiejszą połową. GraphQL to wyjątek wart wymienienia: zwykle w ogóle nie ma numeru wersji do podniesienia, a deprecacja schematu GraphQL ujmuje, jak jeden wspólny schemat wysyła pole na emeryturę dyrektywą zamiast tego.
FAQ
Czy zdeprecjonowany endpoint powinien nadal działać dokładnie jak wcześniej? Tak, do daty sunset. Jedyne dozwolone zmiany to dodane nagłówki i, bliżej końca, zaplanowany brownout, który ogłosiliście z wyprzedzeniem.
Jaki kod statusu powinien zwracać endpoint na emeryturze?
410 Gone, z treścią i nagłówkiem Link wskazującym na zamiennik i wpis changelogu. 404
mówi, że URL nigdy nie istniał, co jest fałszywe i nieprzydatne.
Czy okres deprecacji można skrócić? Tylko z powodów bezpieczeństwa. Jeśli stare zachowanie jest podatne na wykorzystanie, powiedzcie to, skróćcie okres, i powiedzcie każdemu dotkniętemu wywołującemu bezpośrednio, zamiast polegać na changelogu.
Czy muszę deprecjonować pole, czy tylko całe endpointy? Pola, parametry, wartości enum, wartości domyślne i nagłówki wszystkie potrzebują tego samego traktowania, ponieważ każde z nich może złamać poprawnego wywołującego. Usunięte pole to najczęstsza deprecacja i najczęściej pomijana.
Twierdzenia techniczne w tym artykule nie zostały niezależnie zweryfikowane. Jeśli coś się nie zgadza, daj nam znać, a poprawimy to.