¿Qué tan útil / importante es REST HATEOAS (nivel de madurez 3)?

110

Me estoy involucrando en un proyecto en el que algunos miembros del equipo senior creen que una API REST debe ser compatible con HATEOAS e implementar todos los niveles de madurez de Richardson ( http://martinfowler.com/articles/richardsonMaturityModel.html ).

AFAIK, la mayoría de las implementaciones de REST no son compatibles con HATEOAS y debería haber una buena razón por la que más personas no lo estén haciendo. Puedo pensar en razones como mayor complejidad, falta de marcos (lado del servidor y del cliente), preocupación por el rendimiento y ...

¿Qué piensas? ¿Ha tenido alguna experiencia con HATEOAS en un proyecto del mundo real?

mhdwrk
fuente
Aquí hay un buen artículo sobre el tema: medium.com/@andreasreiser94/… Básicamente, la forma en que "REST" se implementa normalmente, es RPC ...
masterxilo

Respuestas:

213

Nadie en la comunidad REST dice que REST es fácil. HATEOAS es solo uno de los aspectos que añade dificultad a una arquitectura REST.

La gente no hace HATEOAS por todas las razones que sugieres: es difícil. Agrega complejidad tanto al lado del servidor como al cliente (si realmente desea beneficiarse de ello).

SIN EMBARGO, miles de millones de personas experimentan los beneficios de REST hoy. ¿Sabes cuál es la URL de "pago" en Amazon? Yo no. Sin embargo, puedo pagar todos los días. ¿Ha cambiado esa URL? No sé, no me importa.

¿Sabes que le importa? Cualquiera que haya escrito una pantalla eliminó el cliente automatizado de Amazon. Alguien que probablemente haya rastreado minuciosamente el tráfico web, leído páginas HTML, etc. para encontrar qué enlaces llamar, cuándo y con qué cargas útiles.

Y tan pronto como Amazon cambió sus procesos internos y la estructura de la URL, esos clientes codificados fallaron, porque los enlaces se rompieron.

Sin embargo, los internautas ocasionales pudieron comprar todo el día sin apenas problemas.

Eso es REST en acción, simplemente aumentado por el ser humano que es capaz de interpretar e intuir la interfaz basada en texto, reconocer un pequeño gráfico con un carrito de compras y darse cuenta de lo que eso realmente significa.

La mayoría de la gente que escribe software no hace eso. A la mayoría de las personas que escriben clientes automatizados no les importa. A la mayoría de las personas les resulta más fácil arreglar a sus clientes cuando se rompen que diseñar la aplicación para que no se rompa en primer lugar. La mayoría de la gente simplemente no tiene suficientes clientes donde importa.

Si está escribiendo una API interna para comunicarse entre dos sistemas con soporte técnico experto y TI en ambos lados del tráfico, que pueden comunicar cambios de manera rápida, confiable y con un cronograma de cambios, entonces REST no le compra nada. No la necesita, su aplicación no es lo suficientemente grande y no es lo suficientemente duradera como para importar.

Los sitios grandes con grandes bases de usuarios tienen este problema. No pueden simplemente pedirle a la gente que cambie su código de cliente por capricho al interactuar con sus sistemas. El programa de desarrollo de los servidores no es el mismo que el programa de desarrollo del cliente. Los cambios abruptos en la API son simplemente inaceptables para todos los involucrados, ya que interrumpen el tráfico y las operaciones en ambos lados.

Por lo tanto, una operación como esa probablemente se beneficiaría de HATEOAS, ya que es más fácil de versionar, más fácil de migrar para los clientes más antiguos, más fácil de ser compatible con versiones anteriores que no.

Un cliente que delega gran parte de su flujo de trabajo al servidor y actúa sobre los resultados es mucho más robusto a los cambios del servidor que un cliente que no lo hace.

Pero la mayoría de la gente no necesita esa flexibilidad. Están escribiendo código de servidor para 2 o 3 departamentos, todo es para uso interno. Si se rompe, lo arreglan y lo han incluido en sus operaciones normales.

La flexibilidad, ya sea de REST o cualquier otra cosa, genera complejidad. Si lo quiere simple y rápido, entonces no lo hace flexible, simplemente "hágalo" y listo. A medida que agrega abstracciones y desreferenciación a los sistemas, las cosas se vuelven más difíciles, más placa de caldera, más código para probar.

Gran parte de REST falla en el punto de viñeta "no lo vas a necesitar". Hasta que, por supuesto, lo hagas.

Si lo necesita, utilícelo y utilícelo como está diseñado. REST no está moviendo cosas de un lado a otro a través de HTTP. Nunca lo ha sido, es un nivel mucho más alto que ese.

Pero cuando necesita REST, y usa REST, entonces HATEOAS es una necesidad. Es parte del paquete y la clave de lo que hace que funcione.

Will Hartung
fuente
11
Siento que deberías tener al menos mil me gusta más para esta respuesta. Honestamente, tengo que imaginarme: ¿Qué importancia tiene para ser "real" la pregunta de REST que surge bastante. Demonios, estaba buscando en Google solo por esa razón para usar municiones en una próxima reunión cuando encontré este hilo.
nograde
2
gracias a dios (o código), ¡alguien también está hablando de las desventajas de HATEOAS!
IlliakaillI
6
¿Existe alguna otra ventaja además de la capacidad de cambiar fácilmente las URL? No puede simplemente agregar nuevas opciones porque, a diferencia de los humanos, el programa no puede funcionar con algo nuevo. Además, solo pasó de crear URL conocidas a conocer el nombre de las acciones.
Jimmy T.
Si el consumidor de API no sabe nada, solo puede delegar las acciones del usuario 1: 1
Jimmy T.
2
Con respecto al cambio de URL, no olvide que su cliente puede usar caché y, por lo tanto, debe mantener el comportamiento en el servidor para manejar la URL anterior también (o simplemente hacer una redirección). Como cualquier estrategia para hacer evolucionar las API, debe mantener su antiguo comportamiento en funcionamiento. HATEOAS no ayuda mucho allí.
Bruno Costa
21

Sí, he tenido algo de experiencia con hipermedia en API. Éstos son algunos de los beneficios:

  1. API explorable: puede parecer trivial, pero no subestime el poder de una API explorable. La capacidad de navegar por los datos hace que sea mucho más fácil para los desarrolladores del cliente construir un modelo mental de la API y sus estructuras de datos.

  2. Documentación en línea: el uso de URL como relaciones de enlace puede llevar a los desarrolladores de clientes a la documentación.

  3. Lógica de cliente simple: un cliente que simplemente sigue las URL en lugar de construirlas él mismo, debería ser más fácil de implementar y mantener.

  4. El servidor se apropia de las estructuras de URL: el uso de hipermedia elimina el conocimiento codificado del cliente de las estructuras de URL utilizadas por el servidor.

  5. Descarga de contenido a otros servicios: Hypermedia es necesario cuando se descarga contenido a otros servidores (una CDN, por ejemplo).

  6. Control de versiones con enlaces: Hypermedia ayuda al control de versiones de las API.

  7. Múltiples implementaciones del mismo servicio / API: Hypermedia es una necesidad cuando existen múltiples implementaciones del mismo servicio / API. Un servicio podría ser, por ejemplo, una API de blog con recursos para agregar publicaciones y comentarios. Si el servicio se especifica en términos de relaciones de enlace en lugar de URL codificadas, entonces el mismo servicio puede ser instanciado varias veces en diferentes URL, alojado por diferentes compañías pero aún accesible a través del mismo conjunto bien definido de enlaces por un solo cliente.

Puede encontrar una explicación detallada de estos puntos aquí: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(hay una pregunta similar aquí: /software/149124/what-is-the-benefit-of-hypermedia-hateoas donde he dado la misma explicación)

Jørn Wildt
fuente
Múltiples implementaciones de un mismo servicio: ¿puedes elaborar? No veo cómo ayuda.
Abbadon
He intentado explicarlo en el texto. Te ayuda?
Jørn Wildt
11

El nivel de madurez 3 de Richardson es valioso y debe adoptarse. Jørn Wildt ya ha resumido algunas ventajas y otra respuesta, de Wilt, la complementa muy bien.

Sin embargo, el nivel de madurez 3 de Richardson no es el mismo que el de Fielding HATEOAS. El nivel de madurez 3 de Richardson solo se refiere al diseño de API. HATEOAS de Fielding también trata sobre el diseño de API, pero también prescribe que el software del cliente no debe asumir que un recurso tiene una estructura específica más allá de la estructura definida por el tipo de medio. Esto requiere un cliente muy genérico, como un navegador web, que no tiene conocimientos sobre sitios web específicos. Dado que Roy Fielding ha acuñado el término REST y ha establecido HATEOAS como un requisito para el cumplimiento de REST, la pregunta es: ¿queremos adoptar HATEOAS y si no, podemos llamar a nuestra API RESTful o no? Creo que podemos. Dejame explicar.

Supongamos que hemos logrado HATEOAS. El lado del cliente de la aplicación es ahora muy genérico, pero lo más probable es que la experiencia del usuario sea mala, porque sin ningún conocimiento de la semántica de los recursos, la presentación de los recursos no se puede adaptar para reflejar esa semántica. Si el recurso 'coche' y el recurso 'casa' tienen el mismo tipo de medio (por ejemplo, aplicación / json), se presentarán al usuario de la misma forma, por ejemplo, como una tabla de propiedades (pares de nombre / valor).

Pero está bien, nuestra API es realmente RESTful.

Ahora, supongamos que construimos una segunda aplicación cliente sobre esta API. Este segundo cliente viola las ideas de HATEOAS y tiene información codificada sobre los recursos. Muestra un coche y una casa de diferentes formas.

¿Se puede seguir llamando RESTful a la API? Creo que sí. No es culpa de la API que uno de sus clientes haya violado HATEOAS.

Aconsejo a construir API REST API, es decir, para los que un cliente genérico se puede implementar en la teoría , pero en la mayoría de los casos, se necesita alguna información codificada sobre los recursos del cliente con el fin de satisfacer los requisitos de usabilidad. Aún así, intente codificar lo menos posible para reducir las dependencias entre el cliente y el servidor.

He incluido una sección sobre HATEOAS en mi patrón de implementación REST llamada JAREST .

www.admiraalit.nl
fuente
8

Estamos construyendo una API REST de nivel 3 donde nuestra respuesta está en HAL-Json. HATEOAS es ideal tanto para el front como para el back-end, pero conlleva desafíos. Hicimos algunas personalizaciones / adiciones para administrar también ACL dentro de la respuesta HAL-Json (que no rompe el estándar HAL-Json).

Las mayores ventajas de HATEOAS que veo es que no necesitamos escribir / adivinar ninguna URL en nuestra aplicación front-end. Todo lo que necesita es un punto de entrada ( https://hostname) y, a partir de ahí, puede navegar a través de los recursos utilizando los enlaces o enlaces con plantilla proporcionados dentro de la respuesta. Así, el control de versiones se puede manejar fácilmente, cambiando el nombre / reemplazando las URL, extendiendo los recursos con relaciones adicionales sin romper el código del front-end.

El almacenamiento en caché de recursos en el front-end es muy sencillo con los enlaces propios. También enviamos recursos a los clientes a través de una conexión de socket, ya que también se procesan en HAL, podríamos agregarlos fácilmente al caché de la misma manera.

Otra ventaja de usar HAL-Json es que está claro cómo debe verse el modelo de respuesta, ya que hay un estándar documentado que debe seguirse.

Una de nuestras personalizaciones es que hemos añadido un objeto acciones dentro del objeto de auto-enlace que expone a la parte delantera qué acciones u operaciones CRUD se permite al usuario autenticado a cabo en el recurso respectivo ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE). De esta manera, nuestra ACL frontal está totalmente dictada por nuestra respuesta de API REST, trasladando esta responsabilidad completamente al modelo de back-end.

Entonces, para dar un ejemplo rápido, podría tener un objeto de publicación en HAL-Json que se parezca a esto:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "[email protected]",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

Ahora todo lo que tenemos que hacer en la interfaz es construir AclServiceun isAllowedmétodo que verifique si la acción que queremos realizar está en el objeto de acciones.

Actualmente, en el front-end parece tan simple como: post.isAllowed('delete');

Creo que el nivel 3 de REST es excelente, pero puede provocar algunos dolores de cabeza. Necesitará tener una gran comprensión de REST y si desea trabajar con el nivel 3 de REST, le sugiero que siga estrictamente el concepto de REST, de lo contrario, se perderá fácilmente en su camino al implementarlo.

En nuestro caso, tenemos la ventaja de que estamos construyendo tanto el front como el back-end, pero en principio NO debería marcar la diferencia. Pero un error común que he visto en nuestro equipo es que algunos desarrolladores intentan resolver problemas de front-end (arquitectura) cambiando su modelo de back-end para que "se adapte" a las necesidades de front-end.

Marchitar
fuente
1
Muy buena respuesta. Creo que un ejemplo tan práctico era lo que buscaba el interrogador original.
www.admiraalit.nl
2

He usado HATEOAS en algunos proyectos reales, pero con una interpretación diferente a la de Richardson. Si eso es lo que quieren tus jefes, supongo que deberías hacerlo. Supongo que HATEOAS significa que sus recursos deben incluir un tipo de documento HTML, hipervínculos a recursos relacionados y formularios HTML para exponer la funcionalidad de verbos distintos de GET. (Esto es cuando el tipo Accept es text / html; otros tipos de contenido no requieren estos extras). No sé de dónde vino la creencia de que todos los recursos REST en toda su aplicación deben estar pegados. Una aplicación de red debe contener múltiples recursos que pueden o no estar directamente relacionados. O por qué se cree que XML, JSON y otros tipos deben seguir esto. (HATEOAS es específico de HTML).

Chris Broski
fuente