2009-03-31 17 views
8

Il design RESTful sembra difendere rappresentazioni strutturate piatte o superficiali (almeno quando le risorse sono rappresentate come XML). Una rappresentazione di risorsa dovrebbe contenere solo la risorsa, identificata dall'URI. Mi chiedo quando è sensato presentare le risorse secondarie della risorsa all'interno della risorsa genitore?Quando includere gli elementi secondari nella rappresentazione risorsa RESTful?

Per elaborare, prendere in considerazione questo: La società può avere più dipendenti. Solitamente questa situazione verrebbe probabilmente progettata come due risorse separate, azienda e dipendente, in cui il dipendente sarebbe la sotto-risorsa dell'azienda.

/company/acme/ 
/company/acme/employees/ 
/company/acme/employee/john 

Con questo disegno URI, la rappresentanza società dovrebbe includere link ai propri dipendenti, ma la rappresentazione XML probabilmente non dovrebbe includere emplyoyees per sé.

Pertanto, quando ha senso presentare sottovoci tramite il genitore? E c'è una situazione in cui sarebbe sensato presentare la sottovoce solo attraverso il loro genitore. Voglio dire che non ci sarebbe alcun URI per gli oggetti secondari. Potrebbero essere raggiunti solo attraverso la risorsa principale.

<company> 
<name>Acme</name> 
<employees> 
    <employee>John</employee> 
    <employee>Jack</employee> 
</employees> 
</company> 

E 'sensato offrire solo un metodo per accedere a una risorsa: se un genitore espone i suoi elementi secondari, ci può essere un URI esplicita per i sub-elementi troppo? Quindi, se l'XML dell'azienda contiene dipendenti della società, avrebbe senso offrire a URI/azienda/dipendente/dipendente che è possibile ottenere le stesse informazioni attraverso la risorsa aziendale?

+0

@massive Ho risposto alla tua domanda su come gestire i problemi di concorrenza negli aggiornamenti di massa modificando la mia risposta. Spero che questo ti aiuti! –

risposta

8

Se la sub-risorsa ha senso solo nel contesto del suo genitore, allora sì, dovrebbe essere annidata all'interno del suo genitore. Ad esempio, in HTML, un elemento <li> non ha senso come risorsa secondaria da solo.

Tuttavia, se una risorsa può essere autonoma e si desidera manipolare una risorsa indipendentemente da altre risorse, è necessario disporre di un proprio URI. In questo modo, puoi POSTARE o METTERE su quella risorsa senza influire sulle altre risorse correlate e senza doverli sottoporre a pappagallo sul server. Se dovessi manipolare ogni cosa dal genitore, pensa a cosa succede se una persona fa un GET, modifica un sotto-oggetto, e poi fa un PUT del tutto con quell'elemento secondario cambiato; cosa succede se qualcun altro ha cambiato uno degli altri nel frattempo? Quindi è necessario aggiungere blocchi e semantica transazionale, che sconfigge l'intero stato di apolidia di REST.

Per le richieste GET, è probabile che sia una buona idea avere una qualche forma di interfaccia di query di massa, grazie alla quale un client può ottenere un gran numero di risorse contemporaneamente; dover fare una nuova richiesta HTTP per ogni risorsa può richiedere molto tempo, poiché significa un nuovo round trip sulla rete per ogni GET. Potrebbe avere senso avere anche funzionalità di aggiornamento collettivo. Ma se vuoi essere in grado di manipolare una risorsa alla volta, devi fornire un URI per quella risorsa.

E sì, è perfetto avere più di un modo per accedere alle risorse. Puoi pensarlo come un blog; puoi ottenere storie sulla pagina principale, o su pagine di archivio, o andando al loro permalink.

modificare: Se si desidera ad un aggiornamento di massa senza incorrere nel problema di avere un cliente dare dati non aggiornati al server, si hanno fondamentalmente due opzioni:

  1. Locking.Un client dice al server "Voglio bloccare tutto questo insieme di dati", recupera i dati che desidera modificare, modifica i dati, li rimanda al server e li sblocca.
  2. Optimistic concurrency: il client scarica il set di dati, contrassegnato da una sorta di tag di revisione che il server cambia ogni volta che riceve nuovi dati. Il client lo modifica e lo invia di nuovo al server. Se uno qualsiasi degli altri dati nel set è stato modificato nel frattempo, il tag di revisione avrà esaurito i dati e il server risponderà con un "mi dispiace, i tuoi dati non sono aggiornati, riprova".

Questi presentano vantaggi e insidie. Il problema con il blocco è che è di stato e quindi non si adatta molto bene a un'architettura REST. Se il programma client si blocca o muore in altro modo mentre ha il blocco, i dati verranno bloccati in modo permanente a meno che non si abbia un qualche tipo di timeout di blocco, che può risultare complicato. Il blocco può portare anche a deadlock se i clienti stanno facendo una sorta di transazioni di fantasia che coinvolgono più blocchi.

Il problema con la concorrenza ottimistica è che se c'è un carico elevato su un set di dati, con molti client che lo cambiano contemporaneamente, possono essere necessari molti, molti tentativi prima che un dato cliente possa pubblicare i suoi dati; in effetti, un client lento può finire per essere completamente tagliato da postare aggiornamenti perché altri client cambiano continuamente i dati in modo tale che i client lenti cambiano sempre fallendo.

Dovrai decidere autonomamente quale di queste opzioni ti soddisfa. Questi problemi emergono anche quando si modifica una singola risorsa (un aggiornamento potrebbe clobarne un altro), ma quando si aggregano le risorse in un'interfaccia di massa, si presenteranno molto più spesso. Ecco perché raccomanderei di avere due interfacce, se hai intenzione di aggregare le risorse; uno in cui è possibile accedere alle risorse individualmente e un'interfaccia di massa facoltativa in cui è possibile leggere e scrivere molte risorse contemporaneamente.

+0

Grazie per la risposta. Informazioni sugli aggiornamenti di massa, come è possibile implementare tale funzionalità senza compromettere l'integrità dei dati come si afferma nel secondo paragrafo della risposta? – massive

Problemi correlati