Diseño de descanso: llamadas múltiples versus devolución de todos los datos en una llamada

8

Estoy tratando de construir una API de descanso para una aplicación de Android. Supongamos que tengo una userstabla con (id, name, email)y una songstabla con (id, song_name, album)y una asociación de unión rica entre ellos como streamsteniendo (user_id, song_id, listen_count). Quiero obtener detalles sobre todas las transmisiones y mostrarlas en la aplicación como una lista. La lista mostraría el nombre de la canción, el nombre del álbum, el nombre de usuario y el recuento de escucha. Veo tres opciones posibles:

  1. GETque /streamsa buscar una lista de todos los song_idse user_ids. Luego, haga GETpara /user/:idy /song/:idpara cada ID de usuario y canción para obtener la información de usuario y canción.
  2. GETque /streamsa buscar una lista de todos los user_idse song_ids. Entonces uno GETa /user?ids=<comma_separated_ids>en busca de información acerca de todos los usuarios y una GETa song?ids=<comma_separated_ids>en busca de información acerca de todas las canciones.
  3. GETa /streamsy traiga todo en una sola llamada. Algo como -

    [
    
      {
    
        "user_id" : 10,
        "song_id" : 14,
        "listen_count" : 5,
        "user" : {
          "id"     : 10,
          "name"   : "bla", 
          "email"  : "bla",
        },
        "song" : {
          "id"     : 14,
          "name"   : "blu",
          "album"  : "blu"
       }
      },
    ...
    ]
    

Estoy tentado de ir con la opción 3 porque me da todo en una sola llamada, pero no creo que esté muy tranquilo y me temo que no será escalable. La opción 2 es buena pero requiere 3 llamadas, lo que significaría un tiempo considerable para cargar la lista. Y la opción 1 sigue al descanso, pero tomará numerosas llamadas para mostrar la lista y hacer tantas llamadas desde un dispositivo móvil no es factible.

¿Cuál sería la forma recomendada de hacer esto?

aandis
fuente
El descanso y la venta son dos cosas diferentes.
Robert Harvey
@RobertHarvey, ¿qué quieres decir?
aandis
¿Qué te hace pensar que la calidad de tu interfaz REST afecta la venta de un producto? ¿Estás vendiendo la interfaz REST? Si no lo eres, a nadie le importa lo que hay debajo del capó. Ver también meta.stackexchange.com/q/142353
Robert Harvey
1
Hay una sobrecarga considerable al hacer una llamada REST. En consecuencia, existe una gran posibilidad de que 3 sea el mejor enfoque desde el punto de vista de la escalabilidad, especialmente si utiliza todos los datos devueltos.
Robert Harvey
1
Relacionado de alguna manera programmers.stackexchange.com/q/257408/56903
toniedzwiedz

Respuestas:

6

Al crear una interfaz REST, no hay requisito, ni siquiera expectativa, de que las respuestas en la interfaz REST correspondan directamente a tablas o uniones en la base de datos.

Su /streamsinterfaz se puede representar tan fácilmente como

[
  {
    "listen_count" : 5,
    "user" : {
      "href"     : "/users/10",
      "name"   : "bla", 
    },
    "song" : {
      "href"     : "/songs/14",
      "name"   : "blu",
      "album"  : "blu"
    }
  },
  ...
]

Donde los objetos JSON contienen los detalles principales de los usuarios y las canciones que son (casi) siempre relevantes para los consumidores de un recurso de transmisión, y un enlace a los recursos de usuario / canción relevantes si se necesitan más detalles.

Esto es esencialmente una variación de su tercera opción, con una alternativa a la opción 1 si se necesitan más detalles.

Bart van Ingen Schenau
fuente
No hay una respuesta garantizada para mí, amigos ... la opción 3 podría ser simple si los dominios siguen siendo simples, pero los meterá en problemas para los objetos que contemplan más de dos niveles de agregaciones. Por ejemplo, desea recuperar todos los cursos disponibles con datos de su maestro. Usted tiene Course-> Teacher(información sobre la persona como maestro, almacenada en una tabla separada) -> Person(la persona física, como puede recordar, la misma persona podría ser maestra de varios cursos). La opción 2 es escalable y requiere * solicitud. También optar. 1 también es escalable, pero podría necesitar >> solicitud.
Victor
Entonces, para sintetizar el comentario anterior: si busca eficiencia, busque el número 1, pero si busca un sistema que pueda crecer sin problemas a tiempo (escalabilidad) sin dolor de cabeza, busque la opción 1 o 2. Vale la pena mencionar que la optimización prematura es la raíz del mal ... así que esto es una advertencia para la opción 3.
Victor
necesito corregirme arriba .. "si buscas eficiencia, entonces lucha por el número 3"
Victor
3

Definitivamente desea una sola GEToperación que devuelva metadatos sobre cada canción y usuario además de sus identificadores opacos.

  • Como señaló, es mucho más simple. Esa es una buena cosa.
  • Hacer una de las operaciones más comunes para sus aplicaciones cliente una solicitud de servidor único en lugar de solicitudes O (n) es mucho más escalable. A la larga, la red será su mayor cuello de botella, por lo que no querrá enviar más solicitudes de las que tiene que enviar.
  • Los identificadores en sí mismos son un poco inútiles, excepto para hacer llamadas REST adicionales.
  • Siempre que sus metadatos tengan un tamaño limitado y relativamente pequeño (por ejemplo, sin páginas de texto descriptivo o archivos de audio reales, solo nombres, tipos, recuentos, etc.) es poco probable que devolverlo además de los identificadores sea un problema de rendimiento.
Ixrec
fuente
Interesante. Pero la opción 3 realmente no se adhiere a un rest-fulldiseño, ¿verdad? A GETto streams debería devolver todo streamsy nada más (incluso si son solo identificadores e inútiles para el cliente).
aandis
2
@zack En el sentido más estricto, sí, pero cualquier principio de diseño puede llevarse demasiado lejos. Cuando te encuentras argumentando que el programa debería hacer algo inútil , generalmente no es una buena señal.
Ixrec
Los metadatos son datos sobre datos, esto son solo datos.
Jacob Raihle
@zack: un streamsrecurso puede contener lógicamente (partes de) otros recursos. Las cosas que son lógicamente parte de un recurso deben estar presentes en la representación de ese recurso.
Bart van Ingen Schenau
1
La opción 3 de @zack es completamente 100% RESTful. Los recursos que expone a través de su API tienen cero requisitos para relacionarse con cualquier otra cosa en su sistema, incluidas sus tablas de base de datos y su modelo de dominio. Podría tener 3 tablas de base de datos y 600 recursos si eso tuviera sentido para su aplicación web. No hay ningún requisito para representar sus relaciones de base de datos en sus relaciones de Recursos.
Cormac Mulhall