Najlepsze praktyki wersjonowania RESTful API: Dlaczego v1 jest numerem 1

Chris McFadden

24 maj 2017

Email

1 min read

Najlepsze praktyki wersjonowania RESTful API: Dlaczego v1 jest numerem 1

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

The SparkPost API wywodzi się z czasów, gdy byliśmy Message Systems, zanim rozpoczęliśmy nasze przygody w chmurze. W tym czasie byliśmy zajęci finalnymi przygotowaniami do wersji beta Momentum 4. Była to duża aktualizacja do wersji 3.x, naszego wiodącego na rynku, lokalnego MTA. Momentum 4 zawierało całkowicie nowy UI, analitykę w czasie rzeczywistym i co najważniejsze, nowe web API do wstrzykiwania i generowania wiadomości, zarządzania szablonami i uzyskiwania metryk e-mail. Nasza wizja to architektura z API na pierwszym miejscu – gdzie nawet UI będzie współdziałać z punktami końcowymi API.

Jedną z najwcześniejszych i najlepszych decyzji, jakie podjęliśmy, było przyjęcie stylu RESTful. Od końca lat 2000., transfer stanu reprezentacyjnego (REST) oparty na web API stał się de facto standardem dla chmurowych API. Korzystanie z HTTP i JSON sprawia, że łatwo jest programistom, niezależnie od używanego języka programowania – PHP, Ruby czy Java – integrować się z naszym API bez potrzeby poznawania lub dbania o naszą technologię bazową. Jednak budowanie natywnych chmurowych API na dużą skalę może stanowić nieoczekiwane wyzwania infrastrukturalne, takie jak limity skalowania DNS, które napotkaliśmy w AWS podczas obsługi ruchu API o dużej objętości.

Decyzja o zastosowaniu architektury RESTful była łatwa. Wybór konwencji wersjonowania nie był już taki prosty. Początkowo odłożyliśmy kwestię wersjonowania, w ogóle nie wersjonując bety. Jednak w ciągu kilku miesięcy beta trafiła w ręce kilku klientów i zaczęliśmy budować naszą usługę w chmurze. Czas na wersjonowanie. Oceniliśmy dwa konwencje wersjonowania. Pierwszą było umieszczenie wersjonowania bezpośrednio w URI, a drugą użycie nagłówka Accept. Pierwsza opcja jest bardziej wyraźna i mniej skomplikowana, co jest łatwiejsze dla programistów. Ponieważ kochamy programistów, był to logiczny wybór.

The SparkPost API wywodzi się z czasów, gdy byliśmy Message Systems, zanim rozpoczęliśmy nasze przygody w chmurze. W tym czasie byliśmy zajęci finalnymi przygotowaniami do wersji beta Momentum 4. Była to duża aktualizacja do wersji 3.x, naszego wiodącego na rynku, lokalnego MTA. Momentum 4 zawierało całkowicie nowy UI, analitykę w czasie rzeczywistym i co najważniejsze, nowe web API do wstrzykiwania i generowania wiadomości, zarządzania szablonami i uzyskiwania metryk e-mail. Nasza wizja to architektura z API na pierwszym miejscu – gdzie nawet UI będzie współdziałać z punktami końcowymi API.

Jedną z najwcześniejszych i najlepszych decyzji, jakie podjęliśmy, było przyjęcie stylu RESTful. Od końca lat 2000., transfer stanu reprezentacyjnego (REST) oparty na web API stał się de facto standardem dla chmurowych API. Korzystanie z HTTP i JSON sprawia, że łatwo jest programistom, niezależnie od używanego języka programowania – PHP, Ruby czy Java – integrować się z naszym API bez potrzeby poznawania lub dbania o naszą technologię bazową. Jednak budowanie natywnych chmurowych API na dużą skalę może stanowić nieoczekiwane wyzwania infrastrukturalne, takie jak limity skalowania DNS, które napotkaliśmy w AWS podczas obsługi ruchu API o dużej objętości.

Decyzja o zastosowaniu architektury RESTful była łatwa. Wybór konwencji wersjonowania nie był już taki prosty. Początkowo odłożyliśmy kwestię wersjonowania, w ogóle nie wersjonując bety. Jednak w ciągu kilku miesięcy beta trafiła w ręce kilku klientów i zaczęliśmy budować naszą usługę w chmurze. Czas na wersjonowanie. Oceniliśmy dwa konwencje wersjonowania. Pierwszą było umieszczenie wersjonowania bezpośrednio w URI, a drugą użycie nagłówka Accept. Pierwsza opcja jest bardziej wyraźna i mniej skomplikowana, co jest łatwiejsze dla programistów. Ponieważ kochamy programistów, był to logiczny wybór.

The SparkPost API wywodzi się z czasów, gdy byliśmy Message Systems, zanim rozpoczęliśmy nasze przygody w chmurze. W tym czasie byliśmy zajęci finalnymi przygotowaniami do wersji beta Momentum 4. Była to duża aktualizacja do wersji 3.x, naszego wiodącego na rynku, lokalnego MTA. Momentum 4 zawierało całkowicie nowy UI, analitykę w czasie rzeczywistym i co najważniejsze, nowe web API do wstrzykiwania i generowania wiadomości, zarządzania szablonami i uzyskiwania metryk e-mail. Nasza wizja to architektura z API na pierwszym miejscu – gdzie nawet UI będzie współdziałać z punktami końcowymi API.

Jedną z najwcześniejszych i najlepszych decyzji, jakie podjęliśmy, było przyjęcie stylu RESTful. Od końca lat 2000., transfer stanu reprezentacyjnego (REST) oparty na web API stał się de facto standardem dla chmurowych API. Korzystanie z HTTP i JSON sprawia, że łatwo jest programistom, niezależnie od używanego języka programowania – PHP, Ruby czy Java – integrować się z naszym API bez potrzeby poznawania lub dbania o naszą technologię bazową. Jednak budowanie natywnych chmurowych API na dużą skalę może stanowić nieoczekiwane wyzwania infrastrukturalne, takie jak limity skalowania DNS, które napotkaliśmy w AWS podczas obsługi ruchu API o dużej objętości.

Decyzja o zastosowaniu architektury RESTful była łatwa. Wybór konwencji wersjonowania nie był już taki prosty. Początkowo odłożyliśmy kwestię wersjonowania, w ogóle nie wersjonując bety. Jednak w ciągu kilku miesięcy beta trafiła w ręce kilku klientów i zaczęliśmy budować naszą usługę w chmurze. Czas na wersjonowanie. Oceniliśmy dwa konwencje wersjonowania. Pierwszą było umieszczenie wersjonowania bezpośrednio w URI, a drugą użycie nagłówka Accept. Pierwsza opcja jest bardziej wyraźna i mniej skomplikowana, co jest łatwiejsze dla programistów. Ponieważ kochamy programistów, był to logiczny wybór.

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.

Inne wiadomości

Czytaj więcej z tej kategorii

A person is standing at a desk while typing on a laptop.

Kompletna, natywna dla AI platforma, która rośnie wraz z Twoim biznesem.

A person is standing at a desk while typing on a laptop.

Kompletna, natywna dla AI platforma, która rośnie wraz z Twoim biznesem.