Jak przydatne / ważne jest REST HATEOAS (poziom dojrzałości 3)?

110

Angażuję się w projekt, w którym niektórzy starsi członkowie zespołu uważają, że REST API musi być zgodny z HATEOAS i wdrażać wszystkie poziomy dojrzałości Richardsona ( http://martinfowler.com/articles/richardsonMaturityModel.html )!

AFAIK, większość implementacji REST nie jest zgodna z HATEOAS i powinien być dobry powód, dla którego więcej osób tego nie robi. Przychodzą mi do głowy takie przyczyny, jak dodatkowa złożoność, brak ram (po stronie serwera i klienta), problemy z wydajnością i ...

Co myślisz? Czy miałeś jakieś doświadczenie z HATEOAS w prawdziwym projekcie?

mhdwrk
źródło
Oto dobry artykuł na ten temat: medium.com/@andreasreiser94/… Zasadniczo sposób, w jaki „REST” jest normalnie zaimplementowany, to RPC ...
masterxilo

Odpowiedzi:

213

Nikt w społeczności REST nie mówi, że REST jest łatwy. HATEOAS to tylko jeden z aspektów, który zwiększa trudności w architekturze REST.

Ludzie nie robią HATEOAS z wszystkich powodów, które sugerujesz: to trudne. Zwiększa złożoność zarówno po stronie serwera, jak i klienta (jeśli faktycznie chcesz z tego skorzystać).

JEDNAK miliardy ludzi doświadczają dziś korzyści z REST. Czy wiesz, jaki jest adres URL „kasy” w Amazon? Ja nie. Jednak mogę codziennie płacić. Czy ten adres URL się zmienił? Nie wiem, nie obchodzi mnie to.

Czy wiesz, że to obchodzi? Każdy, kto napisał screen, zeskrobał automatycznego klienta Amazon. Ktoś, kto prawdopodobnie starannie węszył ruch w sieci, czytał strony HTML itp., Aby dowiedzieć się, jakie linki wywołać, kiedy i za pomocą jakich ładunków.

Gdy tylko Amazon zmienił swoje wewnętrzne procesy i strukturę adresów URL, ci zakodowani klienci zawiedli - ponieważ zepsuły się linki.

Jednak zwykli internauci byli w stanie robić zakupy przez cały dzień bez problemu.

To REST w akcji, jest po prostu wspomagany przez człowieka, który jest w stanie zinterpretować i intuicyjnie interfejs oparty na tekście, rozpoznać małą grafikę z koszykiem i dowiedzieć się, co to właściwie oznacza.

Większość ludzi piszących oprogramowanie tego nie robi. Większość ludzi piszących zautomatyzowanych klientów nie obchodzi. Większość ludzi uważa, że ​​łatwiej jest naprawić swoich klientów, gdy się psują, niż zaprojektować aplikację, aby w ogóle się nie zepsuła. Większość ludzi po prostu nie ma wystarczającej liczby klientów tam, gdzie ma to znaczenie.

Jeśli piszesz wewnętrzny interfejs API do komunikacji między dwoma systemami ze wsparciem technicznym ekspertów i IT po obu stronach ruchu, którzy są w stanie szybko, niezawodnie i zgodnie z harmonogramem zmian komunikować zmiany, to REST nic nie kupuje. Nie potrzebujesz tego, Twoja aplikacja nie jest wystarczająco duża i nie jest wystarczająco długa, aby mieć znaczenie.

Problem ten występuje w dużych witrynach z dużymi bazami użytkowników. Nie mogą po prostu prosić ludzi o zmianę kodu klienta dla kaprysu podczas interakcji z ich systemami. Harmonogram rozwoju serwerów różni się od harmonogramu rozwoju klienta. Nagłe zmiany w API są po prostu nie do przyjęcia dla wszystkich zaangażowanych, ponieważ zakłócają ruch i operacje po obu stronach.

Tak więc taka operacja najprawdopodobniej skorzystałaby na HATEOAS, ponieważ jest łatwiejsza do wersji, łatwiejsza migracja starszych klientów, łatwiejsza kompatybilność wsteczna niż nie.

Klient, który deleguje znaczną część swojego przepływu pracy na serwer i działa na podstawie wyników, jest znacznie bardziej odporny na zmiany na serwerze niż klient, który tego nie robi.

Ale większość ludzi nie potrzebuje takiej elastyczności. Piszą kod serwera dla 2 lub 3 działów, to wszystko do użytku wewnętrznego. Jeśli się zepsuje, naprawiają to i uwzględnili to w swoich normalnych operacjach.

Elastyczność, czy to z REST, czy czegokolwiek innego, rodzi złożoność. Jeśli chcesz, żeby było proste i szybkie, nie robisz tego elastycznym, po prostu zrób to i gotowe. W miarę dodawania abstrakcji i dereferencji do systemów, sprawy stają się trudniejsze, bardziej skomplikowane, więcej kodu do przetestowania.

Znaczna część REST zawodzi w podpunkcie „nie będziesz go potrzebować”. Dopóki, oczywiście, nie zrobisz.

Jeśli potrzebujesz, użyj go i używaj zgodnie z układem. REST nie przepycha rzeczy tam iz powrotem przez HTTP. To nigdy nie było, to znacznie wyższy poziom.

Ale kiedy potrzebujesz RESTU i używasz REST, wtedy HATEOAS jest koniecznością. To część pakietu i klucz do tego, co sprawia, że ​​w ogóle działa.

Will Hartung
źródło
11
Uważam, że ta odpowiedź powinna mieć co najmniej tysiąc polubień. Szczerze mówiąc, muszę sobie wyobrazić: Jak ważne jest bycie „prawdziwym” REST, pojawia się dość często pytanie. Do diabła, właśnie z tego powodu szukałem w Google amunicji do wykorzystania na zbliżającym się spotkaniu, kiedy znalazłem ten wątek.
nograde
2
dzięki Bogu (lub kodowi), ktoś też mówi o wadach HATEOAS!
IlliakaillI
6
Czy jest jakaś inna zaleta niż możliwość łatwej zmiany adresów URL? Nie możesz po prostu dodać nowych opcji, ponieważ w przeciwieństwie do ludzi program nie może pracować z czymś nowym. Ponadto przeszedłeś tylko od tworzenia znajomości adresów URL do znajomości nazw działań.
Jimmy T.
Jeśli konsument API nic nie wie, może delegować tylko akcje użytkownika 1: 1
Jimmy T.
2
Jeśli chodzi o zmianę adresów URL, nie zapominaj, że twój klient może korzystać z pamięci podręcznej, więc musisz zachować zachowanie na serwerze, aby obsłużyć również poprzedni adres URL (lub po prostu wykonać przekierowanie). Jak każda strategia ewolucji API, musisz zachować swoje stare zachowanie. HATEOAS niewiele tam pomaga.
Bruno Costa
21

Tak, mam pewne doświadczenie z hipermediami w interfejsach API. Oto kilka korzyści:

  1. Eksplorowalne API: Może wydawać się banalne, ale nie lekceważ potęgi eksplorowalnego API. Możliwość przeglądania danych znacznie ułatwia programistom klienckim zbudowanie mentalnego modelu API i jego struktur danych.

  2. Dokumentacja wbudowana: użycie adresów URL jako relacji odsyłaczy może wskazywać deweloperom klientów na dokumentację.

  3. Prosta logika klienta: klient, który po prostu podąża za adresami URL zamiast konstruować je sam, powinien być łatwiejszy do wdrożenia i utrzymania.

  4. Serwer przejmuje własność struktur URL: użycie hipermedii usuwa zakodowaną na stałe wiedzę klienta o strukturach adresów URL używanych przez serwer.

  5. Przeniesienie treści do innych usług: hipermedia jest konieczna, gdy zawartość jest przenoszona na inne serwery (na przykład CDN).

  6. Wersjonowanie z linkami: Hypermedia pomaga w wersjonowaniu interfejsów API.

  7. Wiele implementacji tej samej usługi / API: hipermedia jest koniecznością, gdy istnieje wiele implementacji tej samej usługi / API. Usługą może być na przykład blog API z zasobami do dodawania postów i komentarzy. Jeśli usługa jest określona w kategoriach relacji łączy zamiast adresów URL zakodowanych na stałe, wówczas ta sama usługa może być tworzona wielokrotnie pod różnymi adresami URL, hostowana przez różne firmy, ale nadal dostępna za pośrednictwem tego samego, dobrze zdefiniowanego zestawu łączy jednego klienta.

Szczegółowe wyjaśnienie tych punktów można znaleźć tutaj: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(tutaj jest podobne pytanie: /software/149124/what-is-the-benefit-of-hypermedia-hateoas, gdzie podałem to samo wyjaśnienie)

Jørn Wildt
źródło
Wiele wdrożeń tej samej usługi: czy możesz to rozwinąć? Nie wiem, jak to pomaga.
Abbadon
Próbowałem to wyjaśnić w tekście. Czy to pomaga?
Jørn Wildt
11

Poziom 3 dojrzałości Richardsona jest cenny i powinien zostać przyjęty. Jørn Wildt podsumował już niektóre zalety, a inna odpowiedź, autorstwa Wilta, bardzo dobrze ją uzupełnia.

Jednak poziom dojrzałości Richardsona 3 nie jest tym samym, co HATEOAS Fieldinga. Poziom dojrzałości Richardsona 3 dotyczy tylko projektowania API. HATEOAS firmy Fielding dotyczy również projektowania interfejsu API, ale zaleca również oprogramowanie klienckie nie zakładało, że zasób ma określoną strukturę poza strukturą zdefiniowaną przez typ nośnika. Wymaga to bardzo ogólnego klienta, takiego jak przeglądarka internetowa, która nie ma wiedzy na temat konkretnych witryn. Ponieważ Roy Fielding ukuł termin REST i ustawił HATEOAS jako wymóg zgodności z REST, pytanie brzmi: czy chcemy przyjąć HATEOAS, a jeśli nie, czy nadal możemy nazwać nasze API RESTful, czy nie? Myślę że możemy. Pozwól mi wyjaśnić.

Załóżmy, że osiągnęliśmy HATEOAS. Aplikacja po stronie klienta jest teraz bardzo ogólna, ale najprawdopodobniej wrażenia użytkownika są złe, ponieważ bez znajomości semantyki zasobów nie można dostosować prezentacji zasobów do tych semantyki. Jeśli zasób „samochód” i zasób „dom” mają ten sam typ nośnika (np. Aplikacja / json), zostaną one przedstawione użytkownikowi w ten sam sposób, na przykład jako tabela właściwości (pary nazwa / wartość).

Ale okej, nasze API jest naprawdę RESTful.

Teraz przypuśćmy, że utworzymy drugą aplikację kliencką na bazie tego interfejsu API. Ten drugi klient narusza idee HATEOAS i ma zakodowane informacje o zasobach. Wyświetla samochód i dom na różne sposoby.

Czy nadal można nazwać interfejs API RESTful? Chyba tak. To nie wina API, że jeden z jego klientów naruszył HATEOAS.

Radzę budować relaksującego API, czyli API dla których ogólna klient może zostać wdrożone w teorii , ale w większości przypadków, muszą Państwo jakieś zakodowane informacje dotyczące zasobów w kliencie w celu spełnienia wymogów użyteczności. Mimo to staraj się jak najmniej wprowadzać na stałe kod, aby zmniejszyć zależności między klientem a serwerem.

Dodałem sekcję o HATEOAS do mojego wzorca implementacji REST o nazwie JAREST .

www.admiraalit.nl
źródło
9

Tworzymy interfejs API REST poziomu 3, w którym nasza odpowiedź znajduje się w HAL-Json. HATEOAS jest świetny zarówno na przód, jak i tył, ale wiąże się z wyzwaniami. Dokonaliśmy pewnych dostosowań / dodatków, aby również zarządzać listą ACL w odpowiedzi HAL-Json (co nie łamie standardu HAL-Json).

Największą zaletą HATEOAS, jaką widzę, jest to, że nie musimy pisać / zgadywać żadnych adresów URL w naszej aplikacji front-end. Wszystko, czego potrzebujesz, to punkt wejścia ( https://hostname), a stamtąd możesz po prostu przeglądać zasoby, korzystając z linków lub linków z szablonu podanych w odpowiedzi. W ten sposób można łatwo obsłużyć wersjonowanie, zmieniając nazwę / zastępując adresy URL, rozszerzając zasoby o dodatkowe relacje bez przerywania kodu front-end.

Buforowanie zasobów w interfejsie użytkownika to bułka z masłem przy użyciu własnych linków. Wysyłamy również zasoby do klientów przez połączenie przez gniazdo, ponieważ są one również renderowane w HAL, możemy łatwo dodać je do pamięci podręcznej w ten sam sposób.

Kolejną zaletą korzystania z HAL-Json jest to, że jest jasne, jak powinien wyglądać model odpowiedzi, ponieważ istnieje udokumentowany standard, którego należy przestrzegać.

Jeden z naszych dostosowań jest to, że dodaliśmy działania obiektów wewnątrz obiektu self-link, który eksponuje do przedniego końca, jakie działania lub operacje CRUD uwierzytelniony użytkownik może wykonywać na danym zasobie ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE). W ten sposób nasza lista ACL frontendu jest całkowicie podyktowana odpowiedzią REST API, przenosząc tę ​​odpowiedzialność w pełni na model zaplecza.

Aby dać szybki przykład, możesz mieć obiekt post w HAL-Json, który wygląda mniej więcej tak:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "[email protected]",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

Teraz wszystko, co mamy do zrobienia na przednim końcu jest Zbuduj AclServicez isAllowedmetody, która sprawdza, czy działania chcemy wykonać to w działaniach obiektu.

Obecnie na front-endzie wygląda to tak prosto, jak: post.isAllowed('delete');

Myślę, że poziom REST 3 jest świetny, ale może prowadzić do bólu głowy. Będziesz musiał dobrze rozumieć REST i jeśli chcesz pracować z REST na poziomie 3, sugerowałbym ścisłe przestrzeganie koncepcji REST, w przeciwnym razie łatwo zgubisz się na swojej drodze podczas jej wdrażania.

W naszym przypadku mamy tę zaletę, że budujemy zarówno front, jak i back-end, ale w zasadzie NIE powinno to robić różnicy. Jednak częstym błędem, który widziałem w naszym zespole, jest to, że niektórzy programiści próbują rozwiązywać problemy związane z front-endem (architekturą), zmieniając model zaplecza tak, aby odpowiadał on potrzebom front-endu.

Więdnąć
źródło
1
Bardzo dobra odpowiedź. Myślę, że taki praktyczny przykład był tym, czego szukał pierwotny pytający.
www.admiraalit.nl
2

Używałem HATEOAS w niektórych prawdziwych projektach, ale z inną interpretacją niż Richardson. Jeśli tego chcą twoi szefowie, myślę, że powinieneś to zrobić. Rozumiem, że HATEOAS oznacza, że ​​twoje zasoby powinny zawierać dokument HTML, hiperłącza do powiązanych zasobów i formularze HTML, aby udostępnić funkcjonalność dla czasowników innych niż GET. (To wtedy typ Accept to text / html - inne typy treści nie wymagają tych dodatków). Nie wiem, skąd wzięło się przekonanie, że wszystkie zasoby REST w całej aplikacji muszą być sklejone. Aplikacja sieciowa powinna zawierać wiele zasobów, które mogą, ale nie muszą być bezpośrednio powiązane. Albo dlaczego uważa się, że XML, JSON i inne typy muszą za tym podążać. (HATEOAS jest specyficzne dla HTML).

Chris Broski
źródło