Arresto di una macchina virtuale tramite un'interfaccia REST
Questo è in realtà un esempio piuttosto famoso, presentato da Tim Bray nel 2009 .
Roy Fielding, discutendo del problema, ha condiviso questa osservazione :
Personalmente preferisco i sistemi che trattano lo stato monitorato (come lo stato di alimentazione) come non modificabili.
In breve, si dispone di una risorsa di informazioni che restituisce una rappresentazione corrente dello stato monitorato; tale rappresentazione potrebbe includere un collegamento ipertestuale a un modulo che richiede una modifica a quello stato e il modulo ha un altro collegamento a una risorsa per gestire (ciascuna) richiesta di modifica.
Seth Ladd ha avuto le informazioni chiave sul problema
Abbiamo trasformato Running da un semplice stato di una persona a un vero Noun che può essere creato, aggiornato e di cui parlare.
Riportare questo al riavvio delle macchine. Direi che POST in / vdc / 434 / cluster / 4894 / server / 4343 / riavvii Una volta pubblicato, hai un URI che rappresenta questo riavvio e puoi OTTENERLO per gli aggiornamenti di stato. Attraverso la magia del collegamento ipertestuale, la rappresentazione del riavvio è collegata al server che viene riavviato.
Penso che coniare lo spazio URI sia economico e che gli URI siano ancora più economici. Crea una raccolta di attività, modellata come sostantivi, e POST, PUT e DELETE via!
La programmazione RESTful è la burocrazia di Vogon su scala web. Come si fa a fare qualcosa di RESTful? Inventa nuovi documenti per esso e digitalizza i documenti.
In un linguaggio un po 'più elaborato, quello che stai facendo è definire il protocollo dell'applicazione di dominio per "arrestare una VM" e identificare le risorse necessarie per esporre / implementare quel protocollo
Guardando i tuoi esempi
PATCH /api/virtualmachines/42
Content-Type:application/json
{ "state": "shutting down" }
Va bene; non stai davvero trattando la richiesta stessa come una propria risorsa di informazioni separata, ma potresti comunque gestirla.
Ti sei perso un po 'nella tua rappresentazione del cambiamento.
Con PATCH, tuttavia, l'entità racchiusa contiene una serie di istruzioni che descrivono come modificare una risorsa attualmente residente sul server di origine per produrre una nuova versione.
Ad esempio, il tipo di supporto JSON Patch formatta le istruzioni come se si stesse modificando direttamente un documento JSON
[
{ "op": "replace", "path": "state", "value": "shutting down" }
]
In alternativa, l'idea è vicina, ma ovviamente non corretta. PUT
è una sostituzione completa dello stato della risorsa nell'URL di destinazione , quindi probabilmente non sceglieresti un'ortografia che assomigli a una raccolta come destinazione di una rappresentazione di una singola entità.
POST /api/virtualmachines/42/actions
È coerente con la finzione che stiamo aggiungendo un'azione a una coda
PUT /api/virtualmachines/42/latestAction
È coerente con la finzione che stiamo effettuando un aggiornamento per l'elemento di coda nella coda; è un po 'strano farlo in questo modo. Il principio della minima sorpresa raccomanda di assegnare a ciascun PUT un proprio identificatore univoco, anziché metterli tutti in un unico posto e modificare più risorse contemporaneamente.
Si noti che, nella misura in cui discutiamo dell'ortografia dell'URI, a REST non importa; /cc719e3a-c772-48ee-b0e6-09b4e7abbf8b
è un URI perfettamente cromulento per quanto riguarda il REST. La leggibilità, come con i nomi delle variabili, è una preoccupazione separata. L'uso di ortografie coerenti con RFC 3986 renderà le persone molto più felici.
CQRS
E se disponessimo di un dominio CQRS con molte di tali "azioni" (ovvero comandi) che potrebbero potenzialmente portare ad aggiornamenti di più aggregati o che non possono essere associati a operazioni CRUD su risorse e risorse secondarie concrete?
Greg Young su CQRS
CQRS è un modello molto semplice che offre molte opportunità per l'architettura che altrimenti potrebbero non esistere. CQRS non è un'eventuale coerenza, non è un evento, non è un messaggio, non ha modelli separati per la lettura e la scrittura, né utilizza l'approvvigionamento di eventi.
Quando la maggior parte delle persone parla di CQRS, in realtà parla dell'applicazione del modello CQRS all'oggetto che rappresenta il limite del servizio dell'applicazione.
Dato che stai parlando di CQRS nel contesto di HTTP / REST, sembra ragionevole supporre che tu stia lavorando in quest'ultimo contesto, quindi andiamo con quello.
Questo, sorprendentemente, è persino più facile del tuo esempio precedente. Il motivo è semplice: i comandi sono messaggi .
Jim Webber descrive HTTP come il protocollo applicativo di un ufficio degli anni '50; il lavoro viene svolto prendendo i messaggi e inserendoli nelle caselle di posta. La stessa idea vale: otteniamo una copia vuota di un modulo, lo compiliamo con le specifiche che conosciamo, lo consegniamo. Ta da
Dovremmo provare a modellare quanti comandi concreti crea o aggiorna su risorse concrete, ove possibile (seguendo il primo approccio dall'esempio I) e utilizzare "endpoint di azione" per il resto?
Sì, nella misura in cui le "risorse concrete" sono messaggi, piuttosto che entità nel modello di dominio.
Idea chiave: l'API REST è ancora un'interfaccia ; dovresti essere in grado di cambiare il modello sottostante senza che i clienti debbano cambiare i messaggi. Quando si rilascia un nuovo modello, si rilascia una nuova versione degli endpoint Web che sanno come prendere il protocollo di dominio e applicarlo al nuovo modello.
Un modello CQRS è più adatto per un'API come RPC?
Non proprio - in particolare, le cache web sono un ottimo esempio di "modello di lettura alla fine coerente". Rendere ciascuno dei tuoi punti di vista indirizzabili in modo indipendente, ognuno con le proprie regole di memorizzazione nella cache, ti dà un sacco di ridimensionamento gratuitamente. C'è relativamente poco appello a un approccio esclusivamente RPC alle letture.
Per quanto riguarda le scritture, è una domanda più complicata: inviare tutti i comandi a un singolo gestore in un singolo endpoint o in una singola famiglia di endpoint è sicuramente più semplice . REST è molto più di come trovi comunicare dove si trova l'endpoint al client.
Considerare un messaggio come una sua unica risorsa ha il vantaggio di poter usare PUT, avvisando i componenti intermedi del fatto che la gestione del messaggio è idempotente, in modo che possano partecipare a determinati casi di gestione degli errori, è bello avere . (Nota: dal punto di vista dei client, se le risorse hanno un URI diverso, allora sono risorse diverse; il fatto che possano avere tutti lo stesso codice del gestore richieste sul server di origine è un dettaglio di implementazione nascosto dall'uniforme interfaccia).
Fielding (2008)
Dovrei anche notare che quanto sopra non è ancora completamente RESTful, almeno come uso il termine. Tutto quello che ho fatto è stato descritto le interfacce di servizio, che non è altro che un RPC. Per renderlo RESTful, avrei bisogno di aggiungere ipertesto per introdurre e definire il servizio, descrivere come eseguire la mappatura utilizzando moduli e / o modelli di link e fornire codice per combinare le visualizzazioni in modi utili.