Quanto è utile / importante REST HATEOAS (livello di maturità 3)?


110

Sono coinvolto in un progetto in cui alcuni membri senior del team ritengono che un'API REST debba essere conforme a HATEOAS e implementare tutti i livelli di maturità di Richardson ( http://martinfowler.com/articles/richardsonMaturityModel.html )!

Per quanto ne so, la maggior parte delle implementazioni REST non sono conformi a HATEOAS e dovrebbe esserci una buona ragione per cui più persone non lo fanno. Posso pensare a ragioni come maggiore complessità, mancanza di framework (lato server e lato client), problemi di prestazioni e ...

Cosa ne pensi? Hai avuto esperienza con HATEOAS in un progetto del mondo reale?


Ecco un buon articolo sull'argomento: medium.com/@andreasreiser94/… Fondamentalmente, il modo in cui "REST" è normalmente implementato, è RPC ...
masterxilo

Risposte:


213

Nessuno nella comunità REST dice che REST è facile. HATEOAS è solo uno degli aspetti che aggiunge difficoltà a un'architettura REST.

Le persone non fanno HATEOAS per tutti i motivi che suggerisci: è difficile. Aggiunge complessità sia al lato server che al client (se si desidera effettivamente trarne vantaggio).

TUTTAVIA, oggi miliardi di persone sperimentano i vantaggi di REST. Sai qual è l'URL di "checkout" su Amazon? Io non. Tuttavia, posso effettuare il checkout ogni giorno. Quell'URL è cambiato? Non lo so, non mi interessa.

Lo sai che ci tiene? Chiunque abbia scritto uno schermo ha raschiato il client automatizzato di Amazon. Qualcuno che probabilmente ha analizzato meticolosamente il traffico web, letto pagine HTML, ecc. Per trovare quali collegamenti chiamare quando e con quali payload.

E non appena Amazon ha cambiato i propri processi interni e la struttura degli URL, quei client hardcoded hanno fallito, perché i collegamenti si sono interrotti.

Eppure, i navigatori occasionali del web erano in grado di fare acquisti tutto il giorno senza problemi.

Questo è REST in azione, è semplicemente aumentato dall'essere umano che è in grado di interpretare e intuire l'interfaccia basata su testo, riconoscere una piccola grafica con un carrello della spesa e scoprire cosa significa effettivamente.

La maggior parte delle persone che scrivono software non lo fa. Alla maggior parte delle persone che scrivono client automatizzati non interessa. La maggior parte delle persone trova più facile riparare i propri clienti quando si rompono che progettare l'applicazione in modo che non si rompa in primo luogo. La maggior parte delle persone semplicemente non ha abbastanza clienti dove conta.

Se stai scrivendo un'API interna per comunicare tra due sistemi con supporto tecnico esperto e IT su entrambi i lati del traffico, che sono in grado di comunicare le modifiche in modo rapido, affidabile e con una pianificazione delle modifiche, REST non ti compra nulla. Non ne hai bisogno, la tua app non è abbastanza grande e non è abbastanza longeva per essere importante.

I siti di grandi dimensioni con una vasta base di utenti presentano questo problema. Non possono semplicemente chiedere alle persone di cambiare il loro codice client per capriccio quando interagiscono con i loro sistemi. La pianificazione dello sviluppo dei server non è la stessa della pianificazione dello sviluppo del client. Le modifiche improvvise all'API sono semplicemente inaccettabili per tutte le persone coinvolte, poiché interrompono il traffico e le operazioni su entrambi i lati.

Quindi, un'operazione del genere molto probabilmente trarrebbe vantaggio da HATEOAS, poiché è più facile da aggiornare, più facile migrare per i client meno recenti, più facile essere retrocompatibili che non.

Un client che delega gran parte del suo flusso di lavoro al server e agisce sui risultati è molto più resistente alle modifiche del server rispetto a un client che non lo fa.

Ma la maggior parte delle persone non ha bisogno di questa flessibilità. Stanno scrivendo codice server per 2 o 3 dipartimenti, è tutto per uso interno. Se si rompe, lo riparano e l'hanno preso in considerazione nelle loro normali operazioni.

La flessibilità, sia da REST che da qualsiasi altra cosa, genera complessità. Se vuoi che sia semplice e veloce, allora non lo rendi flessibile, "fallo e basta" ed è fatto. Man mano che aggiungi astrazioni e dereferenziazione ai sistemi, le cose diventano più difficili, più elementi di base, più codice da testare.

Gran parte di REST fallisce il punto elenco "non ne avrai bisogno". Fino a quando, naturalmente, non lo fai.

Se ne hai bisogno, usalo e usalo così com'è. REST non spinge cose avanti e indietro su HTTP. Non lo è mai stato, è di livello molto più alto di quello.

Ma quando hai bisogno di REST e usi REST, allora HATEOAS è una necessità. Fa parte del pacchetto e una chiave per ciò che lo fa funzionare.


11
Mi sento come se dovessi avere almeno altri mille Mi piace per questa risposta. Onestamente, devo immaginare: quanto sia importante essere "reale" la domanda REST viene fuori un bel po '. Diavolo, stavo cercando su Google proprio questo motivo per le munizioni da usare in una riunione imminente quando ho trovato questo thread.
nograde

2
grazie a dio (o codice), qualcuno sta parlando anche degli svantaggi di HATEOAS!
IlliakaillI

6
C'è qualche altro vantaggio rispetto alla possibilità di cambiare facilmente gli URL? Non puoi semplicemente aggiungere nuove opzioni perché a differenza degli umani il programma non può funzionare con qualcosa di nuovo. Inoltre sei passato dalla creazione di URL che conoscono a conoscere il nome delle azioni.
Jimmy T.

Se il consumatore dell'API non sa nulla, può delegare solo le azioni dell'utente 1: 1
Jimmy T.

2
Per quanto riguarda la modifica degli URL, non dimenticare che il tuo client potrebbe utilizzare la cache e quindi devi mantenere il comportamento sul server per gestire anche l'URL precedente (o semplicemente eseguire un reindirizzamento). Come qualsiasi strategia per evolvere le API, devi mantenere il tuo vecchio comportamento funzionante. HATEOAS non aiuta molto lì.
Bruno Costa

21

Sì, ho avuto una certa esperienza con l'ipermedia nelle API. Ecco alcuni dei vantaggi:

  1. API esplorabile: può sembrare banale ma non sottovalutare la potenza di un'API esplorabile. La capacità di navigare tra i dati rende molto più semplice per gli sviluppatori client costruire un modello mentale dell'API e delle sue strutture dati.

  2. Documentazione in linea: l'uso di URL come relazioni di collegamento può indirizzare gli sviluppatori client alla documentazione.

  3. Logica client semplice: un client che segue semplicemente gli URL invece di costruirli da solo, dovrebbe essere più facile da implementare e mantenere.

  4. Il server assume la proprietà delle strutture URL: l'uso di hypermedia rimuove la conoscenza hardcoded del client delle strutture URL utilizzate dal server.

  5. Disattivazione del caricamento del contenuto su altri servizi: Hypermedia è necessario quando si scarica il contenuto su altri server (ad esempio un CDN).

  6. Controllo delle versioni con collegamenti: Hypermedia aiuta il controllo delle versioni delle API.

  7. Implementazioni multiple dello stesso servizio / API: Hypermedia è una necessità quando esistono più implementazioni dello stesso servizio / API. Un servizio potrebbe ad esempio essere un'API del blog con risorse per l'aggiunta di post e commenti. Se il servizio è specificato in termini di relazioni di collegamento invece di URL hardcoded, lo stesso servizio può essere istanziato più volte su URL diversi, ospitato da società diverse ma comunque accessibile tramite lo stesso insieme ben definito di collegamenti da un singolo client.

Puoi trovare una spiegazione approfondita di questi punti elenco qui: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(c'è una domanda simile qui: /software/149124/what-is-the-benefit-of-hypermedia-hateoas dove ho dato la stessa spiegazione)


Molteplici implementazioni dello stesso servizio: puoi elaborare? Non vedo come aiuta.
Abbadon

Ho provato a spiegarlo nel testo. Aiuta?
Jørn Wildt

11

Il livello di maturità 3 di Richardson è prezioso e dovrebbe essere adottato. Jørn Wildt ha già riassunto alcuni vantaggi e un'altra risposta, di Wilt, la completa molto bene.

Tuttavia, il livello di maturità 3 di Richardson non è lo stesso di HATEOAS di Fielding. Il livello di maturità 3 di Richardson riguarda solo la progettazione API. HATEOAS di Fielding riguarda anche la progettazione delle API, ma prescrive anche che il software client non debba presumere che una risorsa abbia una struttura specifica oltre la struttura definita dal tipo di supporto. Ciò richiede un client molto generico, come un browser web, che non ha conoscenza di siti web specifici. Poiché Roy Fielding ha coniato il termine REST e ha impostato HATEOAS come requisito per la conformità a REST, la domanda è: vogliamo adottare HATEOAS e, in caso contrario, possiamo ancora chiamare la nostra API RESTful o no? Penso che possiamo. Lasciatemi spiegare.

Supponiamo di aver raggiunto HATEOAS. Il lato client dell'applicazione è ora molto generico, ma molto probabilmente l'esperienza utente è negativa, perché senza alcuna conoscenza della semantica delle risorse, la presentazione delle risorse non può essere adattata per riflettere quelle semantiche. Se la risorsa "auto" e la risorsa "casa" hanno lo stesso tipo di supporto (ad es. Application / json), verranno presentate all'utente nello stesso modo, ad esempio come una tabella di proprietà (coppie nome / valore).

Ma va bene, la nostra API è davvero RESTful.

Supponiamo ora di creare una seconda applicazione client su questa API. Questo secondo client viola le idee di HATEOAS e dispone di informazioni hardcoded sulle risorse. Mostra un'auto e una casa in modi diversi.

L'API può ancora essere chiamata RESTful? Credo di si. Non è colpa dell'API se uno dei suoi client ha violato HATEOAS.

Consiglio di costruire API RESTful, cioè API per le quali un client generico può essere implementato in teoria , ma nella maggior parte dei casi, hai bisogno di alcune informazioni hard-coded sulle risorse nel tuo client per soddisfare i requisiti di usabilità. Tuttavia, prova a codificare il meno possibile, per ridurre le dipendenze tra client e server.

Ho incluso una sezione su HATEOAS nel mio modello di implementazione REST chiamato JAREST .


8

Stiamo costruendo un'API REST di livello 3 in cui la nostra risposta è in HAL-Json. HATEOAS è ottimo sia per il front-end che per il back-end, ma presenta sfide. Abbiamo apportato alcune personalizzazioni / aggiunte per gestire anche ACL all'interno della risposta HAL-Json (che non infrange lo standard HAL-Json).

I maggiori vantaggi di HATEOAS che vedo è che non abbiamo bisogno di scrivere / indovinare alcun URL sulla nostra applicazione front-end. Tutto ciò di cui hai bisogno è un punto di ingresso ( https://hostname) e da lì in poi puoi semplicemente navigare tra le risorse usando i link oi link basati su modelli forniti all'interno della risposta. In questo modo il controllo delle versioni può essere gestito facilmente, rinominando / sostituendo gli URL, estendendo le risorse con relazioni aggiuntive senza interrompere il codice front-end.

La memorizzazione nella cache delle risorse sul front-end è un gioco da ragazzi utilizzando i collegamenti automatici. Spingiamo anche le risorse ai client attraverso una connessione socket, poiché anche queste vengono visualizzate in HAL, potremmo facilmente aggiungerle alla cache allo stesso modo.

Un altro vantaggio dell'utilizzo di HAL-Json è che è chiaro come dovrebbe apparire il modello di risposta, poiché esiste uno standard documentato che dovrebbe essere seguito.

Una delle nostre personalizzazioni è che abbiamo aggiunto un oggetto azioni all'interno dell'oggetto auto-link che espone al front-end che le azioni o le operazioni CRUD l'utente autenticato è autorizzato a eseguire sulla rispettiva risorsa ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE). In questo modo, il nostro ACL front-end è totalmente dettato dalla nostra risposta API REST, trasferendo questa responsabilità completamente al modello back-end.

Quindi, per fare un rapido esempio, potresti avere un oggetto post in HAL-Json che assomiglia a questo:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "john.doe@example.com",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

Ora tutto ciò che dobbiamo fare sul front-end è creare un AclServicecon un isAllowedmetodo che controlla se l'azione che vogliamo eseguire è nell'oggetto azioni.

Attualmente sul front-end sembra semplice come: post.isAllowed('delete');

Penso che il livello 3 di RIPOSO sia fantastico, ma può portare ad alcuni mal di testa. Avrai bisogno di avere una grande comprensione del REST e se vuoi lavorare con il livello 3 REST suggerirei di seguire rigorosamente il concetto REST altrimenti ti perderai facilmente durante l'implementazione.

Nel nostro caso abbiamo il vantaggio di costruire sia front che back-end ma in linea di principio NON dovrebbe fare la differenza. Ma una trappola comune che ho riscontrato nel nostro team è che alcuni sviluppatori cercano di risolvere i problemi di front-end (architettura) modificando il loro modello di back-end in modo che "si adatti" alle esigenze di front-end.


1
Risposta molto buona. Penso che un esempio così pratico fosse ciò che l'interrogante originale stava cercando.
www.admiraalit.nl

2

Ho usato HATEOAS in alcuni progetti reali, ma con un'interpretazione diversa rispetto a Richardson. Se questo è ciò che vogliono i tuoi capi, allora immagino che dovresti farlo e basta. Prendo HATEOAS per significare che le tue risorse dovrebbero includere un doctype HTML, collegamenti ipertestuali a risorse correlate e moduli HTML per esporre funzionalità per verbi diversi da GET. (Questo è quando il tipo Accept è text / html - altri tipi di contenuto non richiedono questi extra.) Non so da dove provenga la convinzione che tutte le risorse REST dell'intera applicazione debbano essere incollate insieme. Un'applicazione di rete dovrebbe contenere più risorse che possono o meno essere direttamente correlate. O perché si ritiene che XML, JSON e altri tipi debbano seguire questo. (HATEOAS è specifico per HTML.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.