Najlepsze praktyki wersjonowania RESTful API: Dlaczego v1 jest numerem 1
Chris McFadden
24 maj 2017
1 min read

Kluczowe Wnioski
Versionowanie API zapobiega wprowadzaniu zmian niszczących i zachowuje zaufanie między dostawcami API a deweloperami.
Jasne konwencje wersjonowania pomagają uniknąć chaotycznej mieszanki wersji w różnych punktach końcowych.
RESTful API w połączeniu z prostymi, jednoznacznymi URI wersji utrzymują integracje intuicyjne dla deweloperów.
Grupy zarządcze zapewniają spójność w zespołach, zapobiegając przypadkowemu wprowadzaniu zmian niszczących.
Nie wszystkie zmiany wymagają nowej wersji — tylko te, które niszczą istniejące integracje.
Dobra dokumentacja jest niezbędna, aby uniknąć zamieszania i zapobiec nieumyślnemu wprowadzaniu zmian niszczących.
Oddzielenie wdrażania od wydania pozwala zespołom bezpiecznie testować i doskonalić punkty końcowe przed ich ogłoszeniem.
Gdy zmiany niszczące są nieuniknione, muszą być starannie ocenić i przekazane.
Q&A Highlights
Dlaczego wersjonowanie API jest ważne?
Zapobiega niespodziewanym zmianom dla programistów integrujących się z Twoim API, chroni zaufanie i zapewnia długoterminową stabilność dla aplikacji, które polegają na spójnym działaniu.
Jakie są breaking changes w API?
Jakakolwiek modyfikacja, która zmienia sposób działania istniejących integracji — na przykład usuwanie punktów końcowych, zmiana wartości domyślnych, dodawanie wymaganych pól lub modyfikowanie formatów odpowiedzi.
Dlaczego SparkPost wybrał REST jako podstawę dla ich API?
Wykorzystanie protokołu HTTP i JSON przez REST ułatwia programistom różnych języków (PHP, Ruby, Java, itp.) integrację bez potrzeby posiadania specjalistycznej wiedzy o systemach podstawowych.
Jak SparkPost zdecydował o swojej metodzie wersjonowania?
Oni ocenili wersjonowanie nagłówka Accept w porównaniu z wersjonowaniem URI i wybrali wersjonowanie URI, ponieważ jest ono jednoznaczne, proste i bardziej przyjazne dla deweloperów.
Jaką rolę odgrywa grupa ds. zarządzania API?
Ustanawia standardy, zapewnia spójność i zapobiega wprowadzaniu przez zespoły zmian, które są sprzeczne z konwencjami lub łamią kompatybilność.
Jakie rodzaje zmian nie są uznawane za breaking?
Dodawanie nowych opcjonalnych parametrów, wprowadzanie nowych punktów końcowych, dodawanie nowych kluczy w ładunkach JSON lub zmiana punktów końcowych niepublicznych — wszystko, co nie zakłóca istniejącego działania.
Jakie zmiany są uważane za breaking?
Dodawanie wymaganych parametrów, usuwanie punktów końcowych, zmiana domyślnych zachowań, zmiana struktury odpowiedzi lub wprowadzanie wymaganych pól JSON.
Dlaczego dokładna dokumentacja jest niezbędna?
Zapobiega niezamierzonym zmianom, które mogłyby zerwać kompatybilność, pomaga programistom zrozumieć zachowanie oraz zapewnia, że zespoły aktualizują API w sposób niezawodny. SparkPost użył Markdown (API Blueprint) i GitHub do utrzymania przejrzystości i otwartości.
Jaka jest korzyść z oddzielenia wdrożenia od release?
Zespoły mogą ciągle wdrażać nowe punkty końcowe lub ulepszenia wewnętrznie, testować je w rzeczywistych przepływach pracy, doskonalić zachowania i publikować, gdy są stabilne — unikając przedwczesnego i potencjalnie problematycznego ujawnienia.
Co się dzieje, jeśli konieczna staje się zmiana przełamująca?
Musi to być rzadkie, uzasadnione wyraźnymi korzyściami, starannie ocenione pod kątem wpływu na użytkownika i dokładnie zakomunikowane. Przykład: dostosowanie Suppression API dopiero po potwierdzeniu minimalnego efektu i zapewnieniu powiadomienia.
Jak trudne może być wersjonowanie API? Prawda jest taka, że nie jest to trudne, ale to, co jest trudne, to utrzymanie pewnej zdroworozsądkowej perspektywy, aby nie bezsensownie zbaczać w oszałamiającą liczbę wersji i podwersji stosowanych w dziesiątkach punktów końcowych API o niejasnych kompatybilnościach.
Złe zmiany! API Versioning dobre!
Każdy, kto budował lub regularnie używa API, prędzej czy później zdaje sobie sprawę, że zmiany łamiące są bardzo złe i mogą być bardzo poważnym krzyżem dla użytecznego API. Zmiana łamiąca to zmiana w funkcjonowaniu API, która może zepsuć integrację użytkownika i spowodować wiele frustracji oraz utratę zaufania między dostawcą a użytkownikiem API. Zmiany łamiące wymagają, aby użytkownicy byli powiadamiani z wyprzedzeniem (z towarzyszącymi przeprosinami), zamiast zmian, które po prostu się pojawiają, jak na przykład przyjemna nowa funkcja. Sposobem uniknięcia tej frustracji jest wprowadzenie wersji API z zapewnieniem od właściciela API, że nie będą wprowadzane żadne zaskakujące zmiany w obrębie jednej wersji.
Więc jak trudne może być wersjonowanie API? Prawda jest taka, że to nie jest trudne, ale trudne jest utrzymanie zdrowia psychicznego poprzez niepotrzebne rozwijanie się w zawrotną liczbę wersji i podwersji stosowanych na dziesiątkach punktów końcowych API z niejasnymi zgodnościami.
Wprowadziliśmy v1 API trzy lata temu i nie zdawaliśmy sobie sprawy, że będzie ono tak silne do dziś. Jak więc udało nam się dalej zapewniać najlepsze API do dostarczania e-maili od ponad dwóch lat, ale wciąż utrzymując tę samą wersję API? Ta stabilność jest kluczowa dla deweloperów budujących aplikacje z email APIs w infrastrukturze chmurowej, gdzie niezawodność i spójność są najważniejsze. Mimo że istnieje wiele różnych opinii na temat wersjonowania REST API, mam nadzieję, że historia naszego skromnego, ale potężnego v1 może Cię prowadzić na drodze do oświecenia w wersjonowaniu API.
REST Is Best
API Governance
Po wybraniu konwencji wersjonowania pojawiło się więcej pytań. Kiedy będziemy zwiększać wersję? Co to jest zmiana łamiąca? Czy będziemy wersjonować całe API, czy tylko niektóre punkty końcowe? W SparkPost mamy wiele zespołów pracujących nad różnymi częściami naszego API. W ramach tych zespołów, ludzie pracują nad różnymi punktami końcowymi w różnym czasie. Dlatego bardzo ważne jest, aby nasze API było spójne w stosowaniu konwencji. To było coś więcej niż wersjonowanie.
Ustanowiliśmy grupę ds. zarządzania, w skład której wchodzą inżynierowie reprezentujący każdy zespół, członek zespołu Zarządzania Produktem oraz nasz CTO. Grupa ta jest odpowiedzialna za ustanawianie, dokumentowanie i egzekwowanie naszych konwencji API w całej organizacji. Kanał Slack ds. zarządzania API również przydaje się do żywych dyskusji na ten temat.
Grupa ds. zarządzania zidentyfikowała szereg sposobów wprowadzania zmian do API, które są korzystne dla użytkownika i nie stanowią zmiany łamiącej. Obejmują one:
Nowy zasób lub punkt końcowy API
Nowy opcjonalny parametr
Zmiana w niepublicznym punkcie końcowym API
Nowy opcjonalny klucz w treści JSON POST
Nowy klucz zwracany w treści odpowiedzi JSON
Przeciwnie, zmiana łamiąca obejmowała wszystko, co mogłoby złamać integrację użytkownika, takie jak:
Nowy wymagany parametr
Nowy wymagany klucz w treściach POST
Usunięcie istniejącego punktu końcowego
Usunięcie istniejącej metody żądania punktu końcowego
Radykalnie inna wewnętrzna logika działania wywołania API - na przykład zmiana domyślnego zachowania.
The Big 1.0
W trakcie dokumentowania i omawiania tych konwencji doszliśmy również do wniosku, że w naszym, a także wszystkich innych interesie leży unikanie wprowadzania zmian powodujących problemy z API, ponieważ zarządzanie wieloma wersjami wymaga dużo dodatkowej pracy. Zdecydowaliśmy, że jest kilka rzeczy, które powinniśmy naprawić w naszym API przed zatwierdzeniem do „v1”.
Wysłanie prostego e-maila wymagało zbyt wiele wysiłku. Aby „zachować prostotę”, zaktualizowaliśmy treść POST, aby zapewnić, że zarówno proste, jak i złożone przypadki użycia są uwzględnione. Nowy format był również bardziej odporny na przyszłe zmiany. Po drugie, zajęliśmy się problemem z punktem końcowym Metrics. Ten punkt końcowy używał parametru „group_by”, który zmieniał format treści odpowiedzi GET, tak że pierwszym kluczem była wartość parametru group_by. Nie wydawało się to zgodne z REST, więc podzieliliśmy każde group_by na osobny punkt końcowy. Na koniec przeprowadziliśmy audyt każdego punktu końcowego i wprowadziliśmy drobne zmiany tu i tam, aby zapewnić ich zgodność ze standardami.
Dokumentacja Accurate
Ważne jest posiadanie dokładnej i użytecznej dokumentacji API, aby unikać wprowadzania niezamierzonych lub zamierzonych zmian, które mogą ją zepsuć. Zdecydowaliśmy się na proste podejście do dokumentacji API, wykorzystując język Markdown zwany API Blueprint i manage our docs in Github. Nasza społeczność przyczynia się do ulepszania tych otwartych dokumentów. Utrzymujemy również niepubliczny zestaw dokumentów w Github dla wewnętrznych API i punktów końcowych.
Początkowo publikowaliśmy nasze dokumenty w Apiary, świetnym narzędziu do prototypowania i publikowania dokumentacji API. Jednak osadzanie Apiary na naszej stronie internetowej nie działa na urządzeniach mobilnych, dlatego teraz używamy Jekyll do generowania dokumentacji statycznej. Nasze najnowsze SparkPost API docs ładują się szybko i działają dobrze na urządzeniach mobilnych, co jest ważne dla developerów, którzy nie zawsze siedzą przy komputerze.
Separating Deployment from Release
Na początku nauczyliśmy się cennej sztuczki oddzielania wdrożenia od wydania. Dzięki temu możemy często wdrażać zmiany, gdy są gotowe, za pomocą ciągłego dostarczania i wdrażania, ale nie zawsze ogłaszamy je publicznie lub dokumentujemy w tym samym czasie. Nie jest niczym niezwykłym, że wdrażamy nowy punkt końcowy API lub ulepszenie istniejącego punktu końcowego API i używamy go w interfejsie użytkownika lub za pomocą narzędzi wewnętrznych zanim go publicznie udokumentujemy i wspieramy. W ten sposób możemy wprowadzać do niego drobne poprawki pod kątem użyteczności lub zgodności ze standardami, nie martwiąc się o wprowadzanie niechcianych zmian powodujących problemy. Gdy jesteśmy zadowoleni ze zmiany, dodajemy ją do naszej dokumentacji publicznej.
Cholera!
Jest tylko uczciwie przyznać, że były czasy, kiedy nie sprostaliśmy naszym ideałom „bez zmian łamiących” i warto się z nich uczyć. W jednym przypadku uznaliśmy, że lepiej byłoby dla użytkowników, gdyby pewna właściwość domyślnie wynosiła true zamiast false. Po wprowadzeniu zmiany otrzymaliśmy od użytkowników kilka skarg, ponieważ zachowanie zmieniło się nieoczekiwanie. Cofnęliśmy zmianę i dodaliśmy ustawienie na poziomie konta – zdecydowanie bardziej przyjazne podejście dla użytkownika.
Czasami kusi nas wprowadzanie zmian łamiących w wyniku napraw błędów. Jednak zdecydowaliśmy się pozostawić te idiosynkrazje w spokoju, zamiast ryzykować łamanie integracji klientów dla zachowania spójności.
Są rzadkie przypadki, kiedy podjęliśmy poważną decyzję o wprowadzeniu zmiany łamiącej – na przykład wycofanie zasobu lub metody API – w interesie większej społeczności użytkowników i tylko po potwierdzeniu, że ma to niewielki lub żaden wpływ na użytkowników. Na przykład celowo podjęliśmy decyzję o zmianie zachowania odpowiedzi API Suppression, ale dopiero po dokładnym rozważeniu korzyści i wpływu na społeczność oraz dokładnym komunikowaniu zmiany naszym użytkownikom. Jednak nigdy nie wprowadzilibyśmy zmiany, która ma nawet najmniejsze prawdopodobieństwo bezpośredniego wpływu na wysyłanie emaila produkcyjnego użytkownika.



