5 złotych zasad doskonałego projektowania internetowego interfejsu API
Opublikowany: 2022-03-11Czy kiedykolwiek zastanawiałeś się „co oni myśleli?” podczas integracji usługi internetowej za pośrednictwem jej API? Jeśli nie, miałeś dużo więcej szczęścia niż ja.
Każdy programista wie, jak łatwo jest pozwolić, aby projekt przekształcił się w kod spaghetti, a internetowe interfejsy API są nie mniej podatne na skutkowanie splątanej sieci. Ale nie musi tak być. W rzeczywistości można zaprojektować świetne internetowe interfejsy API, z których ludzie będą korzystać i których tworzenie również sprawi przyjemność. Ale jak? Odpowiedź na to pytanie brzmi o czym jest ten post.
Perspektywiczny
W większości przypadków, gdy tworzysz rozwiązania, projektujesz dla użytkowników końcowych, którzy nie są programistami lub którzy na ogół nie są wyrafinowani technicznie. Dajesz im interfejs graficzny i jeśli dobrze wykonujesz swoją pracę, masz od nich całkiem niezły pomysł na to, do czego ten interfejs jest potrzebny.
Ale rozwój API jest inny. Projektujesz interfejs dla programistów , prawdopodobnie nawet nie wiedząc, kim oni są. I kimkolwiek są, będą mieli techniczne wyrafinowanie (a przynajmniej będą myśleć, że mają techniczne wyrafinowanie), aby wskazać każdą małą wadę w twoim oprogramowaniu. Twoi użytkownicy prawdopodobnie będą tak samo krytyczni wobec Twojego interfejsu API, jak Ty wobec ich i będą bardzo zadowoleni z jego krytyki.
Nawiasem mówiąc, w tym tkwi część ironii. Jeśli ktoś powinien wiedzieć, jak stworzyć łatwy w użyciu internetowy interfejs API, to właśnie Ty . W końcu jesteś inżynierem oprogramowania, tak jak użytkownicy Twojego interfejsu API, więc dzielisz się ich perspektywą. Prawda?
Cóż, chociaż z pewnością rozumiesz ich perspektywę, niekoniecznie podzielasz ich perspektywę. Kiedy tworzysz lub ulepszasz swój interfejs API, masz perspektywę projektanta interfejsu API, podczas gdy oni mają perspektywę użytkownika interfejsu API .
Projektanci API zwykle skupiają się na pytaniach typu „Co ta usługa musi zrobić?” lub „Co ta usługa musi zapewnić?” , podczas gdy użytkownicy interfejsu API koncentrują się na „Jak mogę użyć tego interfejsu API, aby zrobić to, czego potrzebuję?” , a dokładniej: „Jak mogę poświęcić minimum wysiłku, aby uzyskać to, czego potrzebuję, z tego interfejsu API?” .
Te różne pytania prowadzą do dwóch bardzo różnych perspektyw. W rezultacie niezbędnym warunkiem wstępnym do zaprojektowania świetnego interfejsu API jest zmiana perspektywy z perspektywy projektanta interfejsu API na perspektywę użytkownika interfejsu API. Innymi słowy, stale zadawaj sobie pytania, które naturalnie byś zadał, gdybyś był swoim własnym użytkownikiem. Zamiast myśleć o tym, co może zrobić Twój interfejs API, pomyśl o różnych sposobach, jakich może potrzebować lub chcieć używać , a następnie skup się na jak najłatwiejszym wykonaniu tych zadań dla użytkowników Twojego interfejsu API.
Chociaż może to wydawać się proste i oczywiste, zdumiewające jest to, jak rzadko interfejsy API wydają się być projektowane w ten sposób. Pomyśl o interfejsach API, z którymi spotkałeś się w swojej karierze. Jak często wydają się być projektowane z myślą o tej perspektywie? Projektowanie internetowego interfejsu API może być trudne.
Mając to na uwadze, przejdźmy dalej i porozmawiajmy o 5 złotych zasadach projektowania świetnego internetowego interfejsu API , a mianowicie:
- Dokumentacja
- Stabilność i spójność
- Elastyczność
- Bezpieczeństwo
- Łatwość adopcji
Zasada 1: Dokumentacja
Dokumentacja. Tak, zaczynam tutaj.
Nienawidzisz dokumentacji? Cóż, mogę się wczuć, ale załóż czapkę z „perspektywy użytkownika”, a założę się, że jedyną rzeczą, której nienawidzisz bardziej niż konieczności pisania dokumentacji, jest próba użycia nieudokumentowanego interfejsu API. Odpoczywam.
Najważniejsze jest to, że jeśli chcesz, aby ktokolwiek używał Twojego API, niezbędna jest dokumentacja. Po prostu musisz to zrobić dobrze. To pierwsza rzecz, którą zobaczą użytkownicy, więc pod pewnymi względami przypomina opakowanie na prezent. Dobrze się prezentuj, a ludzie chętniej będą korzystać z Twojego interfejsu API i znosić wszelkie dziwactwa.
Jak więc piszemy dobrą dokumentację?
Stosunkowo łatwą częścią jest udokumentowanie samych metod API; tj. przykładowe prośby i odpowiedzi, wraz z opisami każdego z elementów w obu. Na szczęście pojawia się coraz więcej narzędzi programowych, które ułatwiają i upraszczają zadanie generowania dokumentacji. Możesz też samodzielnie napisać coś, co będzie introspekcji Twojego interfejsu API, punktów końcowych i funkcji oraz wygenerowania dla Ciebie odpowiedniej dokumentacji.
Ale tym, co oddziela świetną dokumentację od odpowiedniej dokumentacji, jest włączenie przykładów użycia i, najlepiej, samouczków. To pomaga użytkownikowi zrozumieć Twój interfejs API i od czego zacząć. Ukierunkowuje je i pomaga załadować Twój interfejs API do mózgu.
Na przykład, jeśli twórcy Twilio mieliby wymienić każdą klasę, każdą metodę i każdą możliwą odpowiedź na ich API, ale nie zadawali sobie trudu, aby wspomnieć, że możesz wysłać SMS-a, śledzić połączenie lub kupić numer telefonu za pośrednictwem ich API, znalezienie tych informacji i ich spójne zrozumienie zajęłoby użytkownikowi naprawdę dużo czasu. Czy możesz sobie wyobrazić przeglądanie gigantycznego drzewa klas i metod bez żadnego wglądu w to, do czego były używane, poza ich nazwą? Brzmi okropnie, prawda? Ale to jest dokładnie to, co robi wielu dostawców interfejsów API, przez co ich interfejsy API są nieprzejrzyste dla nikogo poza sobą. Jednym z przykładów jest przewodnik dla programistów i API Rackspace CloudFiles; trudno jest się zorientować, jeśli już nie rozumiesz, co robią i co zapewniają.
Napisz więc zwięzłe samouczki, które pomogą programistom szybko rozpocząć pracę, z przynajmniej szkieletem tego, co próbuje zrobić, a następnie skieruj ich w stronę bardziej szczegółowej, w pełni udokumentowanej listy funkcji, aby mogli się rozwijać na tym, co mają.
Gdy skończysz z dokumentacją, upewnij się, że ma ona sens dla osób innych niż Ty. Wyślij go do innych programistów w swojej sieci, nie udzielaj im żadnych instrukcji poza wskazaniem ich dokumentacji i poproś ich o zapoznanie się z samouczkiem lub zbudowanie czegoś naprawdę podstawowego w około 15 minut. Jeśli nie będą mogli przeprowadzić podstawowej integracji z Twoim API w ciągu 15 minut, masz więcej pracy do wykonania.
Kilka godnych uwagi przykładów doskonałej i szczegółowej dokumentacji znajdziesz w Twilio, Django i MailChimp. Żaden z tych produktów nie jest koniecznie najlepszy na ich rynkach (chociaż wszystkie są dobrymi produktami), jednak wyróżniają się dostarczaniem najlepszej dokumentacji na swoich rynkach, co z pewnością ułatwiło ich szeroką akceptację i udział w rynku.
Zasada 2: Stabilność i spójność
Jeśli kiedykolwiek korzystałeś z API Facebooka, wiesz, jak często deprecjonują i całkowicie przepisują swoje API. Bez względu na to, jak bardzo szanujesz ich kulturę hakerską lub ich produkt, ich perspektywa nie jest przyjazna dla programistów. Powodem, dla którego nadal odnoszą sukcesy, jest to, że mają miliard użytkowników, a nie dlatego, że ich interfejs API jest świetny.
Ale prawdopodobnie nie masz luksusu posiadania tak ogromnej bazy użytkowników i udziału w rynku, więc będziesz potrzebować znacznie mniej zmiennego interfejsu API, utrzymującego stare wersje działające i obsługiwane przez dość długi czas. Może nawet lata. W tym celu oto kilka wskazówek i sztuczek.
Załóżmy na przykład, że Twój interfejs API jest dostępny pod adresem URL http://myapisite.com/api/widgets
i dostarcza odpowiedź w formacie JSON. Chociaż na pierwszy rzut oka może się to wydawać w porządku, co się dzieje, gdy trzeba zmodyfikować format odpowiedzi JSON? Wszyscy, którzy są już z wami zintegrowani, pękną. Ups.
Zrób więc trochę planowania z wyprzedzeniem i stwórz wersję swojego interfejsu API od samego początku, wyraźnie włączając numer wersji do adresu URL (np. http://myapisite.com/api/widgets?version=1
lub http://myapisite.com/api/widgets/v1
), aby ludzie mogli polegać na działającej wersji 1 i mogli uaktualnić do dowolnej kolejnej wersji, gdy będą na to gotowi. Jeśli w pewnym momencie musisz wycofać poprzednią wersję, śmiało, ale daj dużo zawiadomienia i zaproponuj jakiś plan przejścia.
Dobry schemat adresu URL będzie zawierał główne wersje w adresie URL. Wszelkie zmiany w formacie wyjściowym lub obsługiwanych typach danych powinny skutkować przejściem do nowej wersji głównej. Ogólnie rzecz biorąc, dopuszczalne jest utrzymywanie tej samej wersji, jeśli wszystko, co robisz, to dodawanie kluczy lub węzłów do danych wyjściowych, ale na wszelki wypadek, za każdym razem, gdy dane wyjściowe się zmieniają, podbijaj wersję.
Oprócz stabilności w czasie interfejsy API muszą być wewnętrznie spójne. Widziałem wiele interfejsów API, które zmieniają nazwy parametrów lub metody danych POSTingu, w zależności od używanego punktu końcowego. Zamiast tego należy obsługiwać wspólne parametry globalnie w ramach interfejsu API i używać dziedziczenia lub architektury współużytkowanej, aby ponownie używać tych samych konwencji nazewnictwa i spójnej obsługi danych w całym interfejsie API.
Na koniec musisz zarejestrować i opublikować dziennik zmian, aby pokazać różnice między wersjami Twojego API, aby użytkownicy dokładnie wiedzieli, jak dokonać aktualizacji.
Zasada 3: Elastyczność
Garbage in, garbage out (GIGO) to dobrze znana mantra większości programistów. W przypadku projektowania internetowego interfejsu API ta naczelna zasada zwykle narzuca dość sztywne podejście do weryfikacji żądań. Brzmi świetnie, prawda? Bez bałaganu, bez problemu.

Jednak jak we wszystkim, musi być pewna równowaga. Ponieważ nie można przewidzieć wszystkich sposobów, w jakie użytkownicy będą chcieli korzystać z Twojej usługi, a ponieważ nie każda platforma kliencka jest spójna (tj. nie każda platforma ma bardzo dobrą obsługę JSON, przyzwoitą bibliotekę OAuth itp.), dobrze jest mieć przynajmniej pewien stopień elastyczności lub tolerancji w odniesieniu do ograniczeń wejściowych i wyjściowych.
Na przykład wiele interfejsów API obsługuje różne formaty wyjściowe, takie jak JSON, YAML, XML itp. al., ale obsługuje tylko określanie formatu w samym adresie URL. W duchu zachowania elastyczności możesz pozwolić na określenie tego również w adresie URL (np. /api/v1/widgets.json
) lub możesz również przeczytać i rozpoznać nagłówek HTTP Accept: application/json
lub obsługiwać zmienna ciągu zapytania, taka jak ?format=JSON
i tak dalej.
Skoro już przy tym jesteśmy, dlaczego nie pozwolić, aby określony format nie uwzględniał wielkości liter, aby użytkownik mógł również określić ?format=json
? To klasyczny przykład sposobu na złagodzenie niepotrzebnej frustracji użytkownika Twojego API.
Innym przykładem jest dopuszczenie różnych sposobów wprowadzania zmiennych. Tak więc, tak jak masz wiele formatów wyjściowych, zezwól na różne formaty wejściowe (np. zwykłe zmienne POST, JSON, XML itp.). Powinieneś przynajmniej wspierać standardowe zmienne POST, a wiele nowoczesnych aplikacji obsługuje również JSON, więc te dwa są dobrym miejscem do rozpoczęcia.
Chodzi o to, że nie powinieneś zakładać, że wszyscy podzielają twoje preferencje techniczne. Dzięki odrobinie badań nad działaniem innych interfejsów API i dialogowi z innymi programistami możesz zebrać inne cenne alternatywy, które są przydatne i uwzględnić je w swoim interfejsie API.
Zasada 4: Bezpieczeństwo
Bezpieczeństwo jest oczywiście jedną z najważniejszych rzeczy, które należy wbudować w twoją usługę internetową, ale tak wielu programistów sprawia, że korzystanie z niej jest śmiesznie trudne. Jako dostawca interfejsu API powinieneś oferować użyteczne przykłady uwierzytelniania i autoryzacji podczas uzyskiwania dostępu do interfejsu API. Nie powinno to być trudnym problemem, nad którym użytkownik końcowy spędza wiele godzin. Postaw sobie za cel, aby albo nie musieli pisać żadnego kodu, albo napisanie go zajmie im mniej niż 5 minut.
W przypadku większości interfejsów API wolę proste uwierzytelnianie oparte na tokenie, w którym token jest losowym hashem przypisanym do użytkownika i można go zresetować w dowolnym momencie, jeśli został skradziony. Zezwalaj na przekazywanie tokenu przez POST lub nagłówek HTTP. Na przykład użytkownik może (i powinien) wysłać token SHA-1 jako zmienną POST lub jako nagłówek w formacie takim jak „Authorization: da39a3ee5e6b4b0d3255bfef95601890afd80709”.
Wybierz również bezpieczny token, a nie krótki identyfikator numeryczny. Coś nieodwracalnego jest najlepsze. Na przykład stosunkowo łatwo jest po prostu wygenerować token SHA podczas tworzenia użytkownika i zapisać go w bazie danych. Następnie możesz po prostu wysłać zapytanie do bazy danych w poszukiwaniu użytkowników pasujących do tego tokena. Możesz również wykonać token wygenerowany z unikalnym identyfikatorem i wartością soli, na przykład SHA(User.ID + "abcd123")
, a następnie zapytać o dowolnego pasującego użytkownika; np. where TokenFromPost = SHA(User.ID + "abcd123")
.
Kolejną bardzo dobrą opcją jest OAuth 2 + SSL. Mimo wszystko powinieneś używać SSL, ale OAuth 2 jest dość prosty do zaimplementowania po stronie serwera, a biblioteki są dostępne dla wielu popularnych języków programowania.
Jeśli utworzony przez Ciebie interfejs API ma być dostępny na publicznej stronie internetowej za pośrednictwem JavaScript, musisz również sprawdzić poprawność listy adresów URL na konto dla tokena. W ten sposób nikt nie może sprawdzać wywołań Twojego interfejsu API, ukraść tokena od użytkownika i używać go dla siebie.
Oto kilka innych ważnych rzeczy, o których należy pamiętać:
Funkcjonalność umieszczania na białej liście. Interfejsy API generalnie umożliwiają wykonywanie podstawowych operacji tworzenia, odczytywania, aktualizowania i usuwania danych. Ale nie chcesz zezwalać na te operacje dla każdej encji, więc upewnij się, że każda ma białą listę dozwolonych działań. Upewnij się na przykład, że tylko autoryzowani użytkownicy mogą uruchamiać polecenia takie jak
/user/delete/<id>
. Podobnie wszystkie przydatne nagłówki, które są wysyłane w żądaniu użytkownika, również muszą zostać zweryfikowane względem białej listy. Jeśli zezwalasz na nagłówki typu zawartości, sprawdź, czy to, co wysyła użytkownik, faktycznie pasuje do listy obsługiwanych typów zawartości. Jeśli tak się nie stanie, odeślij komunikat o błędzie, taki jak odpowiedź 406 Nie do zaakceptowania. Biała lista jest ważna, ponieważ wiele interfejsów API jest generowanych automatycznie lub zamiast tego używaj czarnej listy, co oznacza, że musisz jasno określić, czego nie chcesz. Jednak złotą zasadą bezpieczeństwa jest zaczynanie od absolutnie niczego i zezwalanie tylko na to, czego chcesz .Chroń się przed fałszowaniem żądań między witrynami (CSRF). Jeśli zezwalasz na uwierzytelnianie sesji lub plików cookie, musisz upewnić się, że chronisz się przed atakami CSRF. Projekt Open Web Application Security Project (OWASP) zapewnia przydatne wskazówki dotyczące sposobów zapobiegania tym lukom.
Sprawdź poprawność dostępu do zasobów. W każdym żądaniu musisz sprawdzić, czy użytkownik faktycznie ma dostęp do określonego elementu, do którego się odwołuje. Jeśli więc masz punkt końcowy do przeglądania danych karty kredytowej użytkownika (np.
/account/card/view/152423
), upewnij się, że identyfikator „152423” odwołuje się do zasobu, do którego użytkownik naprawdę ma dostęp.Sprawdź poprawność wszystkich danych wejściowych. Wszystkie dane wejściowe użytkownika muszą być bezpiecznie analizowane, najlepiej przy użyciu dobrze znanej biblioteki, jeśli używasz skomplikowanych danych wejściowych, takich jak XML lub JSON. Nie buduj własnego parsera, bo czeka cię świat bólu.
Zasada 5: Łatwość adopcji
To jest naprawdę najważniejsza zasada z całej grupy i opiera się na wszystkich pozostałych. Jak wspomniałem podczas reguły dokumentacji, wypróbuj to z osobami, które są nowe w Twoim API. Upewnij się, że mogą rozpocząć pracę z przynajmniej podstawową implementacją Twojego interfejsu API, nawet jeśli jest to tylko samouczek, w ciągu kilku minut. Myślę, że 15 minut to dobry cel.
Oto kilka konkretnych zaleceń, które ułatwią i ułatwią adopcję Twojego interfejsu API:
Upewnij się, że ludzie mogą faktycznie korzystać z Twojego interfejsu API i że działa on za pierwszym razem, za każdym razem. Niech nowi ludzie próbują od czasu do czasu zaimplementować Twój interfejs API, aby sprawdzić, czy nie jest on mylący w jakiś sposób, na który jesteś odporny.
Nie komplikuj. Nie rób żadnych wymyślnych uwierzytelniania. Nie rób szalonego niestandardowego schematu adresu URL. Nie wymyślaj na nowo SOAP, JSON, REST ani niczego. Korzystaj ze wszystkich dostępnych narzędzi, które zostały już zaimplementowane i są powszechnie akceptowane, aby programiści musieli nauczyć się tylko Twojego API, a nie Twojego API + 10 ukrytych nowych technologii.
Zapewnij biblioteki specyficzne dla języka, aby połączyć się z Twoją usługą. Istnieje kilka fajnych narzędzi do automatycznego generowania biblioteki, takich jak Alpaca lub Apache Thrift. Obecnie Alpaca obsługuje Node, PHP, Python i Ruby. Thrift obsługuje C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml, Delphi i inne.
Uprość każdą niezbędną rejestrację. Jeśli nie tworzysz interfejsu API typu open source lub istnieje jakikolwiek proces rejestracji, upewnij się, że po rejestracji użytkownik jest bardzo szybko kierowany do samouczka. I spraw, aby proces rejestracji był całkowicie zautomatyzowany, bez potrzeby interakcji człowieka z Twojej strony.
Zapewnij doskonałe wsparcie. Dużą barierą w adopcji jest brak wsparcia. Jak poradzisz sobie i zareagujesz na zgłoszenie błędu? A co z niejasną dokumentacją? Niewyrafinowany użytkownik? Fora, narzędzia do śledzenia błędów i pomoc e-mailowa to fantastyczny początek, ale upewnij się, że gdy ktoś opublikuje błąd, naprawdę się nim zajmiesz. Nikt nie chce oglądać forum miasta duchów ani ogromnej listy błędów, które nie zostały usunięte.
Podsumowanie internetowego interfejsu API
Usługi internetowe i ich interfejsy API są obfite. Niestety zdecydowana większość jest trudna w użyciu. Przyczyny mogą być różne, od złego projektu, przez brak dokumentacji, niestabilność, nierozwiązane błędy lub, w niektórych przypadkach, wszystkie powyższe.
Postępowanie zgodnie ze wskazówkami zawartymi w tym poście pomoże zapewnić, że internetowy interfejs API jest czysty, dobrze udokumentowany i łatwy w użyciu. Takie interfejsy API są naprawdę rzadkie i dlatego są znacznie bardziej prawdopodobne, że będą powszechnie stosowane i używane.