Perché un piccolo vocabolario fisso è visto come un vantaggio per i servizi RESTful?


13

Quindi, un servizio RESTful ha un set fisso di verbi nel suo vocabolario. Un servizio Web RESTful prende questi dai metodi HTTP. Ci sono alcuni presunti vantaggi nel definire un vocabolario fisso, ma non capisco davvero il punto. Forse qualcuno può spiegarlo.

Perché un vocabolario fisso come definito da REST è meglio che definire in modo dinamico un vocabolario per ogni stato? Ad esempio, la programmazione orientata agli oggetti è un paradigma popolare. RPC è descritto per definire interfacce fisse, ma non so perché la gente presuma che RPC sia limitato da questi contrappunti. Potremmo specificare dinamicamente l'interfaccia proprio come un servizio RESTful descrive dinamicamente la sua struttura di contenuto.

REST dovrebbe essere vantaggioso in quanto può crescere senza estendere il vocabolario. I servizi RESTful crescono in modo dinamico aggiungendo più risorse. Cosa c'è di così sbagliato nell'estensione di un servizio specificando dinamicamente un vocabolario per oggetto? Perché non utilizziamo semplicemente i metodi definiti sui nostri oggetti come vocabolario e i nostri servizi descrivono al cliente quali sono questi metodi e se hanno o meno effetti collaterali?

Fondamentalmente ho la sensazione che la descrizione di una struttura di risorse lato server sia equivalente alla definizione di un vocabolario, ma siamo quindi costretti a usare il vocabolario limitato in cui interagire con queste risorse.

Un vocabolario fisso disaccoppia davvero le preoccupazioni del client dalle preoccupazioni del server? Devo sicuramente preoccuparmi di alcune configurazioni del server, questa è normalmente la posizione delle risorse nei servizi RESTful. Reclamare l'uso di un vocabolario dinamico sembra ingiusto perché dobbiamo comunque ragionare dinamicamente su come comprendere questa configurazione in qualche modo. Un servizio RESTful descrive le transizioni che è possibile effettuare identificando la struttura degli oggetti tramite hypermedia.

Non capisco cosa rende un vocabolario fisso migliore di qualsiasi altro vocabolario dinamico che si autodescrive, che potrebbe facilmente funzionare molto bene in un servizio simile a RPC. È solo uno scarso ragionamento per il vocabolario limitante del protocollo HTTP?

Riflessione

Solo per chiarire i miei pensieri un po 'meglio di quanto abbia fatto. Supponiamo che tu stia progettando qualsiasi API per scopi generali, forse nemmeno sul web. Saresti felice se qualcuno dicesse che puoi usare questi nomi di metodo solo sui tuoi oggetti? REST non è limitato a HTTP, ma considera la situazione in cui ogni API che scrivi, che si affaccia sul web o in altro modo consisteva semplicemente in oggetti contenenti i metodi GET POST PUT e DELETE. Quindi quel metodo object.foo che volevi definire non è possibile. Devi definire un nuovo oggetto chiamato foo e chiamarne il metodo GET. Questo è essenzialmente il modo in cui funziona REST e mi rende un po 'a disagio a pensarci. Non hai una migliore comprensione generica di ciò che fa foo, sei stato solo costretto a creare un nuovo oggetto per quello che è essenzialmente un metodo su un oggetto genitore. Inoltre la tua API non è meno complessa, hai appena nascosto la complessità dell'interfaccia creando più oggetti. I servizi Web RESTful ci obbligano ad adottare un'interfaccia che può o non può essere sufficiente nel contesto dell'API che stiamo esponendo. Forse c'è una buona ragione per farlo con le API web, ma una buona ragione per non adottare interfacce standard per ogni oggetto in ogni API di uso generale. Un esempio pratico sarebbe apprezzato.


Per aiutare gli utenti ad analizzare rapidamente la tua domanda e le tue risposte, potresti considerare di aggiungere i tuoi "Aggiornamenti" come risposte separate (in particolare la sezione "Un altro aggiornamento"). Questo è incoraggiato: blog.stackoverflow.com/2011/07/…
Johann,

@Johann grazie, gli ulteriori aggiornamenti ora esistono come risposta accettata per questa domanda.
Matt Esch,

Risposte:


9

La terminologia "verbo" e "sostantivo" è alquanto sfortunata qui. Come hai già detto, puoi facilmente creare un oggetto per la funzione. Tutti i linguaggi orientati agli oggetti ad eccezione di Java hanno quella trasformazione integrata e in Java finisci per farlo sempre, finendo con un sacco di oggetti con metodo singolo e spesso uno chiamato "invoke", "execute", "apply" o somesuch (quindi sono i linguaggi di programmazione in cui la distinzione "verbo" / "sostantivo" in realtà non ha senso).

I "verbi" di REST è più come classificare i tuoi metodi in getter, setter (deleter; possono essere considerati tipi di setter) e altro. E provando a fare tutto con getter e setter. La ragione di ciò è:

  1. Semantica più semplice di fronte al fallimento della comunicazione, poiché sia ​​getter che setter sono idempotenti. Ottenere due volte la risorsa non ha alcun effetto aggiuntivo e nemmeno impostarla sul valore che ha già.
  2. Definire alcune semantiche che possono essere utilizzate possibilmente memorizzando nella cache proxy che non comprende l'interfaccia specifica. I getter vengono memorizzati nella cache e si sa che i setter invalidano la cache.

L'HTTP è stato progettato sin dall'inizio tenendo conto sia della cache che della tolleranza agli errori, quindi questi due punti portano a quattro metodi di base:

  • GETè un getter. Si presume che non modifichi lo stato del server e restituisca lo stesso valore ogni volta con la possibilità di specificare i criteri di scadenza e di riconvalida.
  • PUTe DELETEsono setter e deleter (= setter con zero). Normalmente non vengono utilizzati nel contesto del Web normale, ma hanno senso per REST.
  • POST è un generico lavello "invoke" per il quale le cache non possono assumere nulla.

REST è un modello di progettazione che descrive come utilizzare HTTP raw o protocolli di rete simili per implementare l'interfaccia che consente una facile gestione degli errori mediante un semplice tentativo e funziona perfettamente con i proxy di cache.

Non corrisponde facilmente alla normale API di programmazione orientata agli oggetti. Penso che in realtà sia una buona cosa. Le sfide dell'interfaccia in rete, che è intrinsecamente inaffidabile e in cui i round trip sono molto più lenti rispetto al trasferimento di quantità anche moderate di dati richiedono un approccio di progettazione diverso rispetto all'API in-process, quindi quando appare diverso, le persone non provano ad applicare esperienza non valida dall'altro dominio (quella è la rovina di SOAP, XML-RPC e simili; sembra chiamate di procedura, ma non funziona così e finisce per essere doloroso con cui lavorare).


2

L'idea essenziale è che la complessità sia espressa attraverso la rappresentazione delle risorse e quindi non siano necessari ulteriori verbi. Come alcuni hanno affermato: "In REST, i sostantivi sono buoni, i verbi sono cattivi".

Se guardi i quattro verbi REST, possono essere mappati alle operazioni CRUD di base, essenzialmente permettendoti di fare quello che vuoi con le tue risorse. Questo è -

POST - Crea la risorsa

OTTIENI - Leggi la risorsa

PUT - Aggiorna la risorsa

ELIMINA - Elimina la risorsa

Cos'altro ti serve?


Posso facilitare un verbo in un servizio RESTful creando una risorsa per farlo. Come dici tu, non ho bisogno di ulteriori verbi, solo più resuce. Semplicemente non vedo perché sia ​​meglio fingere che un verbo astratto sia un sostantivo quando ciò che voglio fare è davvero un verbo. Sembra che i verbi siano forzatamente vincolati senza motivo, e sto evitando il problema creando nomi che eseguono le azioni richieste quando vi si accede con un piccolo set di verbi. Perché sarebbe meglio farlo? Deve esserci una buona ragione, qualcosa che posso quantificare come esempio pratico.
Matt Esch,

4
Ottieni un elenco di tutte le risorse, ottieni un elenco di tutte le risorse con determinati vincoli, aggiorna o elimina contemporaneamente un mucchio di risorse, crea atomicamente due diversi tipi di risorse (in modo che entrambe le creazioni falliscano o abbiano successo), elimini tutte le risorse saturare una data condizione ... L'elenco delle cose che si potrebbe desiderare di fare è piuttosto lungo. È possibile inserirli in un'API REST, ma non è sempre naturale. Inoltre, non aiuta il fatto che GET non consenta a un corpo, quindi condizioni di filtraggio complesse diventano problematiche.
Andrea,

Anche le risorse PATCHing sono piuttosto interessanti.
Wyatt Barnett,

2

Considera un linguaggio in cui tutti i costrutti (come le funzioni) sono oggetti. Quindi i verbi RESTful stanno semplicemente chiamando convenzioni e dichiarazioni di assegnazione. Per JavaScript potresti definire una sintassi del verbo fissa come INVOKE per chiamare una funzione, DELETE (lo stesso di delete in js) per cancellare un oggetto su un altro oggetto, SET per assegnare un valore e RETURN per restituire un valore. Potremmo usare i verbi HTTP per indicare il POST equivalente - invoke function, PUT - Assegna valore, GET - Restituisce un valore, - ELIMINA - Elimina un oggetto. Sono stato preso dall'idea che i metodi HTTP stavano effettivamente descrivendo metodi di oggetti, interfacce di oggetti reali, che non riuscivo a vedere che potesse effettivamente descrivere concetti di livello molto più basso, come i costrutti del linguaggio di base che sono chiaramente fissi e finiti in tutto lingue sane.

E ovviamente è utile che routing / proxy abbiano un vocabolario fisso su cui riflettere.


1
  • Perché un programmatore professionista anticipa centinaia, se non migliaia di nomi di metodi altrimenti. Ciò che sembra inutile in un piccolo più piccolo può essere un grosso problema man mano che l'applicazione diventa più grande.

  • Perché non sono necessari standard sui nomi dei metodi quando sono già definiti.

  • Perché l'obiettivo principale del codice è leggibile senza tali traduzioni aggiuntive.

  • Perché incoraggia e aiuta a identificare "quando" un'altra classe dovrebbe essere organizzata.

  • Quando si acquisisce il codice è ragionevole ed effettivamente possibile capire cosa e come lo fa molto più rapidamente.

  • Fornisce un vocabolario comune e quindi il livello di astrazione in modo da poterti concentrare su altri dettagli e vedere schemi.

  • Rende più facile la ricerca di bug poiché il codice e gli approcci comuni possono essere facilmente verificati.

  • Quando lavori con più 'livelli' come uno nello sviluppo web, sapere quali URL corrispondono a quali nomi di azioni è molto utile per il debug.

Nel complesso non è "sempre" necessario, ma come la maggior parte degli standard, ha molto senso mirare a provare ad usarlo!


Indirizzato in ordine 1) Quindi un programmatore anticipa centinaia se non migliaia di risorse altrimenti? Prevediamo già i metodi nelle librerie che utilizziamo. 2) Quindi abbiamo bisogno di standard per i nomi dei metodi ma non per i nomi delle risorse? Non riesco a seguire quella logica. 3) Non sono sicuro del significato delle traduzioni. Se mi dici che esiste una risorsa, devo capirla. Se ti dico che esiste un metodo, devi capirlo. L'unica cosa che mi interessa davvero è quale delle mie azioni avrà effetti collaterali 4) Potresti espandere
Matt Esch,

5) di nuovo potresti espandere. Sono un programmatore. Sono abituato a lavorare con strutture di oggetti ben definite. Perché non dovremmo usare questo stesso meccanismo per definire tutte le nostre API se è davvero meglio? 6) Nessun livello di astrazione vale la pena considerare senza giustificazione 7) Ancora una volta potresti espandere. Se beneficiamo in questo modo sicuramente dovremmo codificare tutte le nostre API in questo modo. 8) Mi aspetterei che qualsiasi oggetto esponga direttamente i suoi metodi. / object / method non può essere confuso. Definiamo gli standard scegliendo di adottarli. Mi manca la motivazione al momento.
Matt Esch,

Matt sembri un po 'polemico ma dirò che per 2) non ho detto che la risorsa non avrebbe bisogno di standard 3) Non avrai bisogno di capire un metodo come' aggiorna 'o' nuovo 'o crea' perché sai esattamente cosa fanno quelli secondo gli standard. Ma che dire di "MsgToPrimary" che cosa fa? Creare un messaggio? Aggiornare uno stato? Invia un'email? 7) Sì, la maggior parte delle API potrebbe trarre vantaggio da questo e molti lo fanno. Vorrei provare a concentrarmi sugli standard standard e le convenzioni sono utili e posso vedere che i tuoi aggiornamenti lo stanno dimostrando.
Michael Durrant,

Sto solo cercando di capire i vantaggi. I forti argomenti contrari devono essere affrontati per chiarire il problema. Capisco comunque che un insieme fisso di verbi è una sorta di descrizione della lingua, ma non sono davvero d'accordo sul fatto che sia più facile da capire. Non puoi togliere un insieme espressivo di verbi e dire ehi, ora capiamo tutti i verbi, quando non capiamo tutte le risorse. Le risorse stanno sostituendo i verbi. Sostituiamo il verbo arbitrario foo con una risorsa chiamata foo. La nostra comprensione di foo non è più chiara di quando era foo un verbo.
Matt Esch,

1

L'alternativa è qualcosa di orribile: WSDL (aka Web Service Definition Language), che è un modo (goffo) per descrivere programmaticamente (in qualche modo) API arbitrarie.

REST limita fortemente i verbi, spingendo quasi tutte le variazioni specifiche dell'applicazione nel payload del documento. Il vantaggio è che molte implementazioni client possono comunicare con molti servizi eterogenei. I client e i server potrebbero essere completamente sconosciuti l'uno all'altro, alcuni non ancora scritti.

C'è un podcast in cui Stefan Tilkov spiega bene il REST .


1

Sì, api di riposo ha un set fisso di verbi, ma non deve essere limitato a (o includere GET, POST, PUT, DELETE). Guarderei GET, POST, PUT, DELETE come un'implementazione predefinita di REST che funziona per l'80% di tutti i sistemi là fuori.

Altri sistemi che stanno implementando più di operazioni crud possono (e fare) implementare i propri verbi per le loro API REST. Verbi come Pubblica, Consumi, Valuta, Commenta, Cerca, Sfoglia possono essere aggiunti e implementati in un sistema REST. Mentre alcuni potrebbero dire che un vocabolario più ampio potrebbe renderlo più complicato, la mia risposta è che dipende. Se l'utente target è un capo tecnico che capisce cos'è un POST, allora potrebbe essere più complicato; tuttavia, se gli utenti target della tua API sono persone reali (ovvero persone che non codificano e non sanno cosa sia un POST), i verbi reali sono molto più facili da usare. In effetti, avere un set appropriato di verbi per la tua API aiuta a mantenere brevi gli URL (il che è importante se vuoi che gli utenti li digiti in un browser. Se usi un vocabolario personalizzato, " voglio assicurarti che la tua API e i suoi verbi siano ben documentati. Quando si utilizza un'API REST personalizzata, è necessario assicurarsi che le proprie "azioni di sola lettura" come HTTP GET e le "azioni di scrittura" con POST.

Il social network per ragazzi, Piczo.com, (può riposare in pace) presentava un'API REST estesa (compresi i verbi sopra menzionati) che è stata implementata in 7 lingue diverse!


0

Semplice è buono.

Ci sono casi in cui hai bisogno di ulteriori verbi e complessità, ma la maggior parte dei problemi può essere ridotta a semplici azioni CRUD sulle risorse, ed è ciò che REST cerca di promuovere. Quando si pensa alla maggior parte delle applicazioni Web, alla fine leggono e persistono i record in un archivio dati, che utilizzano le stesse azioni molto semplici.

object.foo () è tutto buono, ma cosa fa? Cosa sta tornando? Sta modificando lo stato dell'oggetto o una delle sue dipendenze? Puoi chiamarlo due volte e ottenere lo stesso risultato o ti darà due valori diversi? Se hai anche object.bar (), devono essere chiamati in un ordine specifico?

Ci sono molte conoscenze richieste nell'uso di una ricca API e di solito hanno le loro convenzioni (cioè setFoo sta per mutare l'oggetto, getBar è probabilmente idempotente, dispose () o destroy () significa che nessun'altra chiamata sullo stesso oggetto sarà possibile, ecc ...)

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.