Since rest deals with documents I'm not sure how those would translate into operations executed on a domain model, given that documents are anemic and domain models are not.
La cosa principale da tenere a mente è il point di una web api è di adattare il tuo dominio per il web; vale a dire, per dare l'illusione che le tue risorse siano in realtà solo voci in un archivio di documenti.
In un certo senso, un consumatore dovrebbe essere in grado di guidare la tua API usando un editor di documenti basato sul web.
Approccio a grana grossa
The save action will result in a PUT request (PUT /orders/3) containing the entire order including order lines. The drawback is that it's hard to figure out what has changed (i.e. which order lines should be added / updated / deleted?).
Questo è un approccio perfettamente ragionevole da prendere - dici all'API come vuoi che la risorsa appaia e l'API deve capire come arrivarci.
Poiché i carrelli degli acquisti in genere non richiedono la collaborazione tra più editor, è possibile ottenere creando un nuovo modello di dati per la risorsa dall'istantanea che è stata fornita, quindi sovrascrivendo il modello esistente.
Se tu, per qualsiasi ragione, hai bisogno di scoprire messaggi di comando con grana più fine dal diff; si, può essere imbarazzante. In un caso come questo, non è male - puoi rilevare il cambiamento abbastanza facilmente, e qualsiasi cambiamento valido è probabilmente estratto da un vocabolario piccolo.
Vale anche la pena notare che non è necessario supportare PUT su alcuna rappresentazione arbitraria della risorsa, ma può invece scegliere e scegliere una rappresentazione che abbia senso (e, si spera, in cui sia facile identificare le modifiche corrette ).
Approccio a grana fine
The delete order line action will result in a DELETE request (DELETE /orders/3/lines/5).
Qualsiasi URI che si desidera utilizzare va bene per quanto riguarda REST; ma concettualmente potrebbe essere meglio pensare in termini di rimozione dell'entità per id, piuttosto che per posizione nell'elenco.
The add order line action will result in a POST request
Potrebbe anche essere fatto come PUT.
This implies the app now needs to keep track of a lot of changes, and execute the changes in the correct order when the user decides to save.
Sì; Credo che ti trovi in una situazione simile con un cliente occasionalmente connesso. I messaggi di comando vengono messi in coda fino a quando il sistema di destinazione non diventa disponibile.
Un altro approccio da considerare sarebbe quello di manipolare la cronologia della risorsa, piuttosto che la risorsa stessa. In effetti, la cronologia diventa un'apposita raccolta di modifiche.
I'm just wondering how I can avoid duplicating business rules on the client. For example, if an order line cannot be deleted under certain circumstances, nothing prevents the client from doing so.
Ci sono un paio di risposte qui, basate sull'idea che segnali le informazioni nelle rappresentazioni.
Una risposta è che annoti semplicemente che la riga dell'ordine non deve essere cancellata. Le regole aziendali che decidono se una riga d'ordine può essere eliminata dal vivo sul server, il client vede solo che il flag è stato impostato.
È possibile comunicare tali informazioni fuori banda ai client.
Nell'approccio a grana fine, la solita risposta è che usi i controlli ipermediali. Piuttosto che i client che inviano un messaggio a un endpoint predeterminato, il client dovrebbe guardare nella rappresentazione e "seguire un collegamento". In questo modo puoi comunicare che non è possibile eliminare un articolo dell'ordine rimuovendo il collegamento dell'elemento di cancellazione dalla rappresentazione.
In un approccio a grana del corso, suppongo che potresti provare a distinguere le parti modificabili della risorsa dal resto e fornire rappresentazioni modificabili solo delle parti che il client è autorizzato a modificare. È probabile che ci sia qualche confusione lì.