Rest APIs: desafíos específicos para dispositivos móviles

25

Estoy trabajando en un nuevo proyecto de aplicación para iOS, en el lado móvil. Están ocurriendo algunos cambios en la arquitectura y resulta que tendremos que confiar en una API privada personalizada que será utilizada por la aplicación que estamos creando y también por otros clientes, como un sitio web.

La API que se está diseñando sigue el estilo Rest de las operaciones URI y CRUD centradas en recursos asignadas a verbos HTTP. cosas como:

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

El problema es que este estilo a menudo lleva a la necesidad de que el cliente móvil haga muchas solicitudes para cargar una sola pantalla de aplicación o administrar una acción de IU de un solo usuario. Esto lleva a que la aplicación esté en modo de carga durante 8 segundos hasta que tenga todo lo necesario. Una aplicación lenta y que no responde.

Los clientes móviles tienen serias limitaciones cuando se trata de conectividad y, por lo tanto, idealmente, debemos seguir ese tipo de regla:

1 pantalla == 1 llamada API

1 guardar == 1 llamada API.

Hay muchas situaciones en las que esto lo lleva a un curso de colisión con los principios de diseño REST, por ejemplo:

  • supongamos que su aplicación ha estado fuera de línea durante un día y necesita sincronizarse con cuatro tablas de las bases de datos de fondo y necesita una llamada como www.example.com/sync_everything?since=2015-07-24
  • Digamos que hay una pantalla en la que el usuario puede editar muchos de sus objetos, por ejemplo, marcando tareas en su lista de tareas pendientes. debería haber una manera de editar todos esos registros de tareas en una sola llamada API por lotes en lugar de una llamada API por edición.
  • Digamos que hay una pantalla que mezcla información de las tablas db ORDER, SALESMEN y PRODUCT, debería obtener esos datos en una llamada en lugar de tres.

el riesgo es que podríamos terminar con la API más relajante que existe y también la aplicación móvil que no responde más inútil que existe.

La cuestión es que solo soy un nuevo contratista allí y lo que necesito es algo que me ayude a hacer esos puntos, algunos artículos de fuentes respetadas o algo así. Principales jugadores que se comprometen con el estilo REST para su cliente móvil (por ejemplo: mediante el uso de puntos finales de API agregados compuestos).

O cualquier solución para este problema general. ¡Gracias!

MikaelW
fuente
3
Parece que su pregunta podría ser: "¿Cómo puede una API entregar colecciones de objetos y objetos incrustados de tipos similares o distintos mientras conserva el estilo REST?" ¿Estoy entendiendo tu pregunta?
joshp
Creo que la respuesta general es que cada llamada REST necesita tomar una variedad de parámetros opcionales para que pueda ser flexible pero aún relativamente intuitivo. El caso de sincronización siempre será complicado, pero para las páginas normales normalmente estás viendo varias llamadas del mismo tipo , es decir, todas las GET, ¿verdad?
Ixrec
1
Creo que adaptar su API es la solución incorrecta cuando el problema es la falta de solicitudes paralelas : 8 solicitudes pequeñas no son mucho peores que una solicitud grande cuando no tienen que esperar el uno al otro. ¿Se puede cambiar a HTTP / 2? ¿O al menos utilizar la canalización HTTP / 1.1?
amon
Consulte también: ¿ Patrones para manejar operaciones por lotes en los servicios web REST? . La clave es identificar qué tipos de comandos (y bajo qué condiciones previas) se pueden agrupar sin conflictos, y luego crear una representación JSON del orden por lotes, y luego enviarlo. Pierde el principal atractivo para REST, que es su capacidad de almacenamiento en caché, pero la capacidad de almacenamiento en caché no siempre es relevante para todo tipo de aplicaciones. Tenga en cuenta que el lote / concurrencia no es aplicable si hay dependencias lógicas.
rwong
Una analogía para la situación en la que el intermediario necesita realizar múltiples operaciones en una secuencia, con dependencias lógicas no triviales en cada operación anterior, es algo así como "procedimiento almacenado", que se ejecuta en ese intermediario en lugar de dentro de una base de datos. Debajo, el intermediario puede convertir una sola llamada de "procedimiento almacenado" en tantas solicitudes RESTful como sea necesario, pero ese es un detalle de implementación del intermediario.
rwong

Respuestas:

27

La API que se está diseñando sigue el estilo Rest de las operaciones URI y CRUD centradas en recursos asignadas a verbos HTTP.

Este es tu problema aquí mismo.

Usted ha limitado sus recursos a (supongo) los modelos en su base de datos. Como tal, lleva años cargar todos estos recursos porque su servidor no tiene un concepto de recursos que no tengan una representación en la base de datos.

Por ejemplo podría tener

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

que todos tienen que cargarse para obtener mi biblioteca

Esto no es un problema con el diseño RESTful, esto es realmente un antipatrón REST. No hay absolutamente nada en REST que diga que nuestros recursos deben tener un mapeo uno a uno con cualquier otra cosa en su sistema, incluidos los modelos de bases de datos.

La solución es crear más recursos que coincidan mejor con lo que desea cargar. Si tiene 5 recursos que siempre terminan juntos, cree un nuevo recurso que contenga la información de esos 5 recursos.

Lo que deberías tener es algo como esto

www.example.com/users/334/my_library

que solo carga todos los libros para ese usuario. "my_library" no es un modelo en su base de datos, pero es un recurso. El servidor lo crea en función de los modelos de la base de datos, pero no existe una asignación 1 a 1 y el servidor tiene flexibilidad para crear este recurso sin cambiar su modelo de base de datos.

También podrías tener

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

ninguno de los cuales tiene que existir como modelo en su base de datos o espacio de dominio.

Existe una idea errónea generalizada de que esto es algo incorrecto porque los marcos como Rails enseñaron a las personas a asignar recursos 1 a 1 a modelos en el espacio de dominio que se asignan nuevamente 1 a 1 con filas de base de datos. Esto no es necesario ni se recomienda.

Los recursos deben ser numerosos, baratos y ligeros . Debería ser fácil crearlos, y deberían abstraerse de su modelo de dominio. Si encuentra que necesita uno nuevo, simplemente haga uno nuevo. Si tiene problemas para hacerlo, es culpa de su marco, no es un error con REST.

Ahora la gran advertencia con eso, por supuesto, es si su marco le permite hacer esto. Los marcos como Rails y Django que han tomado el curso para mapear 1-a-1 con el fin de "ahorrarle tiempo" hacen que sea difícil hacerlo. Pero eso es un defecto con los marcos, no con el diseño RESTful.

Aquí está Jim Webber discutiendo esto con más detalle (¡incluyendo algunas excavaciones en Rails también!)

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

Cormac Mulhall
fuente
Esto es muy interesante y estoy totalmente de acuerdo con esto, pero lamentablemente, no soy yo quien hace la API y tengo poca forma de influir en ella, si es que la hay. Muchas personas usarán ese "antipatrón" en todas partes (por muchas razones, siendo las limitaciones del marco uno) y simplemente usan la definición de URI para pensar claramente sobre su base de datos. Los puntos finales de la API son solo otra forma de visualizar su DB ... Además, en algunos casos, crear un recurso como el que describió es difícil debido a que los objetos son realmente diferentes, solo nombrarlos conduciría a términos muy vagos.
MikaelW
Para volver al tema desde un ángulo de eficiencia, acordaron que si una pantalla móvil es muy lenta (y solo si esto sucedió), habrá algunas llamadas compuestas posibles, pero estarán sentadas en un componente que envuelve la API ( en lugar de la API en sí), solo serán utilizados por los clientes móviles y no se considerarán como parte de la API central, el dominio central.
MikaelW
@MikaelW, tienes razón. Incluso lo que dijo Cormac es el escenario ideal, algunas veces está trabajando con una API que necesita atender muchos otros sistemas (escritorio, móvil, web, trabajos programados, sistemas heredados, etc.). Este tipo de API debe ser realmente flexible, proporcionando recursos para atender tantas posibilidades como sea posible, pero no puede atender todas las necesidades de rendimiento específicas de un consumidor. En ese caso, no tienes muchas opciones ...
Dherik