Progettazione dell'API RESTful per un'implementazione del dominio esistente di un gioco semplice?

0

Sto provando a racchiudere un'API RESTful attorno a un'implementazione esistente di un gioco.

Ecco un possibile diagramma di stato di un semplice design API che viene in mente:

Ho problemi qui perché l'implementazione del dominio esistente non espone un elenco di mosse. Invece espone lo stato dell'intero consiglio. Non è necessaria una lista di mosse perché il gioco non supporta le maiuscole, né i replay dei giochi ecc.

Posso pensare ad alcune opzioni:

  1. Eseguo il drill sull'implementazione del dominio esistente e visualizziamo un elenco di mosse per ogni gioco. In modo che io possa implementare il design dal diagramma sopra.

    Non mi piace perché dover modificare il modello di dominio esistente solo per calzare il cursore su un'API ha un cattivo odore.

  2. Progetto una transizione di stato da /api/games/{id} con la relazione di estensione newMove (o sth. simile) che consente un POST sulla risorsa /api/games/{id}/moves . Fornirò un documento API sotto /docs/rels/newMove . Non ci sarà un'implementazione per GET nella lista delle mosse.

    Questo è ancora RESTful? Ogni risorsa RESTful deve avere una rappresentazione e consentire GET ?

    Trovo questo interessante, però, perché significa quasi nessuna logica lato server aggiuntiva.

  3. Naturalmente ci sono più opzioni. Potrei progettare la scheda come una sotto risorsa e implementare una transizione di stato PUT (+ link relation e docs) per aggiornarla.

    Non mi piace neanche questo. Significa che devo trasferire l'intera board, inclusa la nuova mossa. Mettendo l'intera scheda sul server e facendo in modo che il server lo rilevasse, quale campo è cambiato e convalida anche che solo un campo è cambiato, e cosa no, è inutilmente complesso. E risulterebbe in una certa quantità di logica aggiuntiva sul server. Che di nuovo ha un cattivo odore. Quindi forse PATCH invece?

  4. Finalmente ho potuto progettare la scheda come una sotto risorsa e ogni campo della scheda come una sotto-risorsa della scheda (ad esempio /api/games/{id}/board/5/11 ) e quindi implementare un PUT per effettuare la mossa.

    Questo non sembra male. Ma sarebbe stupido avere il client che ottiene lo stato della scheda facendogli fare più richieste per ottenere lo stato di ogni campo. Quindi ci dovrebbe probabilmente essere una rappresentazione della scheda completa da qualche parte (ad esempio /api/games/{id}/board o come valore del gioco stesso). In questo caso la domanda sorge spontanea se ha senso implementare GET per ogni campo del board, perché non ne avrai bisogno.

    Quindi, di nuovo qui, ogni risorsa RESTful deve avere una rappresentazione?

Qual è la soluzione più semplice che aderisce ancora ai vincoli REST?

Una delle opzioni sopra o forse qualcosa di completamente diverso?

    
posta leifbattermann 17.01.2017 - 11:46
fonte

2 risposte

1

I'm trying to wrap a RESTful API around an existing implementation of a game.

Dovresti rivedere il discorso di Jim Webber su REST e DDD , che consiglio principalmente per i suoi approfondimenti su REST

  • In HTTP, il lavoro è un effetto collaterale del passaggio di documenti intorno a
  • Il punto di un'API HTTP è di adattare il tuo dominio per il web

In particolare, uno dei vantaggi di hypermedia (uno dei vincoli di interfaccia uniformi di REST) è che se una risorsa non ha senso, non può essere implementata, a prescindere - elidate qualsiasi link a tale risorsa. Poiché il client apre solo i segnalibri e segue i collegamenti, non andrà mai dove non dovrebbe

Must every RESTful resource have a representation and allow GET?

No. Vedi RFC 7231: OPTIONS .

What is the simplest solution that still adheres to the REST constraints? One of the options above or maybe something completely different?

Se lo spazio delle mosse candidate è piccolo, potresti essere in grado di produrre una lista di mosse consentite semplicemente provandole tutte. Ad esempio, un gioco tic-tac-toe ha solo 18 mosse candidate; carica 18 copie del tabellone attuale, prova ognuna delle 18 mosse, filtra dall'elenco le mosse respinte dal gioco e restituisci il resto.

Anche negli scacchi, in una data posizione non ci sono troppe mosse da provare - usando solo le restrizioni di movimento, una regina viene ridotta a un massimo di 27 mosse candidate, meno per gli altri pezzi, e ovviamente puoi ignora le mosse che porterebbero il pezzo oltre i confini del tabellone.

Inoltre, puoi sfruttare il caching: invece di fornire una rappresentazione delle mosse disponibili per lo stato attuale del gioco direttamente, puoi reindirizzare la richiesta a una risorsa che elenca le mosse disponibili nella posizione corrente. Ciò richiede un buon modo per rappresentare lo stato della scheda come parte di un identificatore di risorsa, che può essere o meno pratico.

In un senso più ampio, se stai pensando alle rappresentazioni che dovrebbero essere scambiate tra il client e il server, allora dovresti forse considerare event sourcing . Per gli scacchi, il "documento" che i giocatori modificano sarebbe il libro dei punteggi - su ogni gioco, il giocatore fa una voce in fondo al libro mastro che descrive la loro prossima mossa; puoi trattarlo come POST per la raccolta o PUT per la posizione del movimento stesso. È un po 'più vero di quello che sta succedendo che il client "fa le mosse" sulla propria copia della scheda e poi segnala al server qual è il nuovo stato.

    
risposta data 18.01.2017 - 06:47
fonte
0

Sembra che tu sia molto concentrato sull'implementazione di una specie di rigorosa API RESTful, ma REST è stato implementato con successo in molti modi diversi. Mi concentrerei sulla progettazione di un'API coerente e prevedibile per il tuo dominio specifico.

Dalle tue opzioni, preferisco 2 o 4 , ma dipende molto da come appaiono le mosse di questo gioco.

Se hai un gioco come tic tac toe in cui specifichi la posizione della tavola e il suo nuovo valore, allora l'opzione 4 ha senso.

Se hai un gioco più complesso, l'opzione 2 consentirebbe mosse più complesse che non hanno necessariamente come target una posizione specifica della tavola, es. spostare 3 unità da (2,3) a (5,2), usando l'unità situata a (4,4) per rivelare la cella (8,10)

Ricordati di considerare anche chi utilizzerà la tua API. Se è più facile per loro mettere l'intera scheda sul server ogni mossa, potrebbe funzionare la logica extra del server per capire cosa è cambiato.

    
risposta data 17.01.2017 - 22:01
fonte

Leggi altre domande sui tag