Pregunta

El diseño RESTful parece abogar por representaciones estructuradas planas o poco profundas (al menos cuando los recursos se representan como XML).Una representación de recurso debe contener solo el recurso que identifica el URI.Me pregunto cuándo es sensato presentar los subrecursos del recurso dentro del recurso principal.

Para elaborar, considere esto:La empresa puede tener varios empleados.Por lo general, esta situación probablemente se diseñaría como dos recursos separados, empresa y empleado, donde el empleado sería el subrecurso de la empresa.

/company/acme/
/company/acme/employees/
/company/acme/employee/john

Con este diseño de URI, la representación de la empresa debería incluir enlaces a sus empleados, pero la representación XML probablemente no incluiría a los empleados per se.

Por tanto, ¿cuándo tiene sentido presentar subelementos a través del padre?¿Y existe alguna situación en la que sería sensato presentar el subtema solo a través de sus padres.Quiero decir que no habría ningún URI para los subelementos.Sólo se puede acceder a ellos a través del recurso principal.

<company>
<name>Acme</name>
 <employees>
  <employee>John</employee>
  <employee>Jack</employee>
 </employees>
</company>

¿Es sensato ofrecer sólo un método para acceder a un recurso?Si un padre expone sus subelementos, ¿puede haber también un URI explícito para los subelementos?Entonces, si el XML de la empresa contiene los empleados de la empresa, ¿tendría sentido ofrecer el URI /company/acme/employees a pesar de que puede obtener la misma información a través del recurso de la empresa?

¿Fue útil?

Solución

Si el subrecurso solo tiene sentido en el contexto de su padre, entonces sí, debe devolverse anidado dentro de su padre.Por ejemplo, en HTML, un <li> El elemento no tiene sentido como subrecurso por sí solo.

Sin embargo, si un recurso puede ser independiente y desea manipular un recurso independientemente de cualquier otro recurso, entonces debería tener su propio URI.De esa manera, puede POST o PUT en ese recurso sin afectar otros recursos relacionados y sin tener que repetirlos como loro al servidor.Si tuviera que manipular todo desde el padre, piense en lo que sucede si una persona hace un GET, modifica un subelemento y luego hace un PUT de todo con ese subelemento cambiado;¿Qué pasa si alguien más cambia a uno de los demás mientras tanto?Luego es necesario agregar bloqueos y semántica transaccional, lo que anula toda la apatridia de REST.

Al menos para las solicitudes GET, probablemente sea una buena idea tener algún tipo de interfaz de consulta masiva, mediante la cual un cliente pueda obtener una gran cantidad de recursos a la vez;tener que hacer una nueva solicitud HTTP para cada recurso puede llevar mucho tiempo, ya que implica un nuevo viaje de ida y vuelta por la red para cada GET.Puede que también tenga sentido tener una función de actualización masiva.Pero si desea poder manipular un recurso a la vez, debe proporcionar un URI para ese recurso.

Y sí, está perfectamente bien tener más de una forma de acceder a los recursos.Puedes pensar en ello como un blog;Puede obtener historias en la página principal, en las páginas de archivo o accediendo a su enlace permanente.

editar:Si desea realizar una actualización masiva sin encontrarse con el problema de que un cliente proporcione datos obsoletos al servidor, básicamente tiene dos opciones:

  1. Cierre.Un cliente le dice al servidor "Quiero bloquear todo este conjunto de datos", recupera los datos que desea modificar, los modifica, los envía de regreso al servidor y los desbloquea.
  2. Concurrencia optimista:El cliente descarga el conjunto de datos, que está marcado con algún tipo de etiqueta de revisión que el servidor cambia cada vez que obtiene nuevos datos.El cliente lo modifica y lo envía de vuelta al servidor.Si alguno de los demás datos del conjunto se ha modificado mientras tanto, la etiqueta de revisión se quedará sin datos y el servidor responderá con un "lo siento, sus datos no están actualizados, inténtelo de nuevo".

Cada uno de estos tiene ventajas y desventajas.El problema con el bloqueo es que tiene estado y, por lo tanto, no encaja muy bien en una arquitectura REST.Si el programa cliente falla o muere mientras tiene el bloqueo, entonces esos datos se bloquearán permanentemente a menos que tenga algún tipo de tiempo de espera de bloqueo, lo que puede resultar complicado.El bloqueo también puede provocar un punto muerto si los clientes realizan algún tipo de transacción sofisticada que implique múltiples bloqueos.

El problema con la concurrencia optimista es que si hay una carga alta en un conjunto de datos, con muchos clientes cambiándolos a la vez, pueden ser necesarios muchos, muchos intentos antes de que un cliente determinado pueda publicar sus datos;de hecho, un cliente lento puede terminar sin poder publicar actualizaciones porque otros clientes cambian continuamente los datos de manera que los cambios del cliente lento siempre fallan.

Tendrás que decidir por ti mismo cuál de estas opciones te conviene.Estos problemas también surgen al cambiar un solo recurso (una actualización puede afectar a otra), pero cuando agrega recursos en una interfaz masiva, surgirán con mucha más frecuencia.Es por eso que recomendaría tener dos interfaces, si vas a agregar recursos;uno en el que se puede acceder a los recursos individualmente y una interfaz masiva opcional donde se pueden leer y escribir muchos recursos a la vez.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top