API di riposo: sfide specifiche per dispositivi mobili


25

Sto lavorando a un nuovo progetto di app iOS, sul lato mobile. Alcuni cambiamenti nell'architettura stanno avvenendo e si scopre che dovremo fare affidamento su un'API privata costruita su misura che verrà utilizzata dall'app che stiamo costruendo e anche da altri client come un sito Web.

L'API in fase di progettazione segue lo stile Rest delle operazioni URI e CRUD incentrate sulle risorse mappate ai verbi HTTP. cose come:

GET www.example.com/books
DELETE www.example.com/books/482094
POST www.example.com/users/6793

Il problema è che questo stile porta spesso alla necessità per il client mobile di fare molte richieste per caricare una schermata di una singola app o gestire un'azione dell'interfaccia utente di un singolo utente. Ciò porta l'app in modalità di caricamento per 8 secondi fino a quando non ha tutto il necessario. Un'app lenta e che non risponde.

I client mobili hanno seri limiti quando si tratta di connettività e, idealmente, dovremmo seguire quel tipo di regola:

1 schermata == 1 chiamata API

1 salvataggio == 1 chiamata API.

Ci sono molte situazioni in cui questo ti mette in rotta di collisione con i principi di progettazione REST, ad esempio:

  • supponiamo che la tua app sia rimasta offline per un giorno e devi sincronizzarti con quattro tabelle dei database back-end e hai bisogno di una chiamata come www.example.com/sync_everything?since=2015-07-24
  • diciamo che esiste una schermata in cui l'utente può modificare molti dei suoi oggetti, ad esempio spuntando le attività nella sua lista delle cose da fare. dovrebbe esserci un modo per modificare tutti quei record di attività in una singola chiamata API batch anziché una chiamata API per modifica.
  • diciamo che c'è una schermata che mescola le informazioni dalle tabelle db ORDER, SALESMEN e PRODUCT, dovrei ottenere quei dati in una chiamata anziché tre.

il rischio è che potremmo finire con l'API più riposante che ci sia e anche l'app mobile non rispondente più inutile che ci sia.

Il fatto è che sono solo un nuovo imprenditore e quello di cui ho bisogno è qualcosa che mi aiuti a mettere in evidenza quei punti, alcuni articoli da fonti rispettate o qualcosa del genere. Principali attori che compromettono con lo stile REST per il proprio client mobile (ad es. Utilizzando endpoint API aggregati compositi).

O qualsiasi soluzione per questo problema generale. Grazie!


3
Sembra che la tua domanda potrebbe essere: "Come può un'API distribuire raccolte di oggetti e oggetti incorporati di tipo simile o diverso mantenendo lo stile REST?" Capisco la tua domanda?
joshp

Credo che la risposta generale sia che ogni chiamata REST deve prendere una varietà di parametri opzionali in modo che possa essere flessibile ma relativamente intuitiva. Il caso della sincronizzazione sarà sempre complicato, ma per le pagine normali normalmente stai guardando diverse chiamate dello stesso tipo , vale a dire tutti GET, giusto?
Ixrec,

1
Penso che adattare la tua API sia la soluzione sbagliata quando il problema è la mancanza di richieste parallele - 8 piccole richieste non sono molto peggio di una grande richiesta quando non devono aspettarsi. Puoi passare a HTTP / 2? O almeno utilizzare il pipelining HTTP / 1.1?
amon

Vedi anche: Pattern per la gestione delle operazioni batch nei servizi web REST? . La chiave consiste nell'identificare quali tipi di comandi (e in quali condizioni preliminari) possono essere raggruppati senza conflitti, quindi creare una rappresentazione JSON dell'ordine in batch e quindi inviarlo. Perde l'attrattiva principale per REST che è la sua cache, ma la cache non è sempre rilevante per tutti i tipi di applicazioni. Si noti che batch / concorrenza non è applicabile in presenza di dipendenze logiche.
rwong

Un'analogia per la situazione in cui l'intermediario deve eseguire più operazioni in una sequenza, con dipendenze logiche non banali su ciascuna operazione precedente, è qualcosa di simile alla "procedura memorizzata", che viene eseguita in quell'intermediario anziché all'interno di un database. Sotto, l'intermediario è autorizzato a convertire una singola chiamata "stored procedure" in tutte le richieste RESTful necessarie, ma questo è un dettaglio di implementazione dell'intermediario.
rwong

Risposte:


27

L'API in fase di progettazione segue lo stile Rest delle operazioni URI e CRUD incentrate sulle risorse mappate ai verbi HTTP.

Questo è il tuo problema proprio qui.

Hai limitato le tue risorse a (presumo) i modelli nel tuo database. Di conseguenza, ci vogliono anni per caricare tutte queste risorse perché il tuo server non ha il concetto di risorse che non hanno una rappresentazione nel database.

Ad esempio potrebbe avere

www.example.com/books/482094
www.example.com/books/582045
www.example.com/books/427454
www.example.com/books/319343

che tutti devono essere caricati per ottenere la mia libreria

Questo non è un problema con il design RESTful, questo è in realtà un anti-pattern REST. Non c'è assolutamente nulla in REST che dica che le nostre risorse devono avere un mapping uno a uno con qualsiasi altra cosa nel tuo sistema, inclusi i modelli di database.

La soluzione è creare più risorse che corrispondano meglio a ciò che si desidera caricare. Se hai 5 risorse che finiscono sempre insieme crea una nuova risorsa che contiene le informazioni per quelle 5 risorse.

Quello che dovresti avere è qualcosa del genere

www.example.com/users/334/my_library

che carica solo tutti i libri per quell'utente. "my_library" non è un modello nel database, ma è una risorsa. Il server lo crea in base ai modelli nel database ma non esiste un mapping 1 a 1 e il server ha la flessibilità di creare questa risorsa senza modificare il modello DB.

Potresti anche avere

www.example.com/users/334/favioured_books
www.example.com/users/334/books_ordered_last_week
www.example.com/users/334/wishlist

nessuno dei quali deve esistere come modello nel database o nello spazio del dominio.

Esiste un malinteso diffuso sul fatto che questa è la cosa sbagliata da fare perché quadri come Rails hanno insegnato alle persone a mappare le risorse in modo da 1 a 1 a modelli nello spazio del dominio che mappano di nuovo 1 a 1 con righe di database. Questo non è necessario né raccomandato.

Le risorse dovrebbero essere numerose, economiche e leggere . Dovrebbe essere facile crearli e dovrebbero essere astratti dal tuo modello di dominio. Se trovi di averne bisogno di uno nuovo, ne fai uno nuovo. Se hai problemi a farlo, è colpa del tuo framework, non un errore con REST.

Ora il grande avvertimento con quello ovviamente è se il tuo framework ti consente di farlo. Frame come Rails e Django che hanno seguito il corso per mappare 1 a 1 per "risparmiare tempo" rendono difficile farlo. Ma questo è un difetto con i framework, non con il design RESTful.

Ecco Jim Webber che discute di questo è più in dettaglio (compresi alcuni scavi anche su Rails!)

https://yow.eventer.com/yow-2011-1004/domain-driven-design-for-restful-systems-by-jim-webber-1047


Questo è molto interessante e sono pienamente d'accordo con questo, ma purtroppo non sono quello che fa l'API e ho poco modo di influenzarlo, se presente. Molte persone useranno questo "anti-pattern" dappertutto (per molte ragioni, le limitazioni del framework sono una cosa sola) e usano semplicemente la definizione URI per pensare chiaramente al loro database. Gli endpoint API sono solo un altro modo per visualizzare il loro DB ... Inoltre, in alcuni casi, creare una risorsa come quella che hai descritto è difficile a causa del fatto che gli oggetti sono davvero diversi, semplicemente nominarli porterebbe a termini molto vaghi.
MikaelW,

Per tornare al problema da un punto di vista dell'efficienza, hanno convenuto che se uno schermo mobile è molto lento (e solo se ciò accade), ci saranno alcune chiamate composite possibili ma rimarranno in un componente che avvolge l'API ( anziché l'API stessa), verrà utilizzato solo dai client mobili e non verrà considerato come parte dell'API principale, il dominio principale.
MikaelW,

@MikaelW, hai ragione. Anche quello che Cormac ha detto è lo scenario ideale, a volte stai lavorando con un'API che deve frequentare molti altri sistemi (desktop, mobile, web, lavori programmati, sistemi legacy, ecc.). Questo tipo di API deve essere davvero flessibile, fornendo risorse per soddisfare tutte le possibilità possibili ma non può soddisfare tutte le esigenze di prestazioni specifiche di un consumatore. In quel caso non hai molte scelte ...
Dherik,
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.