¿Cómo describir un cambio arquitectónico que intencionalmente rompe los estándares REST?

37

Estoy proponiendo cambios a un proyecto de software muy mal diseñado que sufre de una multitud de problemas. En un nivel alto, el proyecto utiliza Angular en el front-end y consume varias API REST; lo cual es genial (no veo la necesidad de cambiar nuestra tecnología o herramientas). El problema es que la base del código es desproporcionadamente más grande en la interfaz de usuario que las API del lado del servidor. Gran parte de la lógica empresarial vive en la interfaz de usuario, y las API REST son simples interfaces de base de datos CRUD para la capa de interfaz de usuario.

Por ejemplo, un POST to customer creará un registro de cliente, mientras que un PUT modificará a ese cliente. No mucho más y no mucho menos. Sin embargo, nuestra lógica de negocios es más exigente que eso. El proceso general de creación de un cliente hace mucho más que insertar 1 registro de base de datos. Proporcionará datos en otras tablas necesarias, realizará ciertas validaciones y cálculos, etc. Preferiría hacer una sola llamada POST / PUT que encapsule todo este comportamiento, aligerando la carga del cliente consumidor.

Entonces, mi punto de vista es que esta orquestación global debería vivir en el servidor (donde tenemos control total, registros, etc.), no en la interfaz de usuario, pero un argumento en contra es que este enfoque ya no sería RESTful. Por lo tanto, no estoy seguro de cómo describir mejor este enfoque cuando mi recomendación es continuar con la pila de tecnología existente, pero implementar cambios fundamentales en las ubicaciones donde pertenece el código.

Ben Harrison
fuente
44
Confinar su API a llamadas CRUD por hacerla "RESTful" es una compensación pobre.
Robert Harvey
38
@EsbenSkovPedersen: ¿Mejor amigo para siempre?
Robert Harvey
55
En lugar de preocuparme por si su servicio se ajusta a REST (iirc, casi ninguno lo hace), me preocuparía más por cumplir con la especificación HTTP . La mayoría de las API con las que he trabajado tampoco cumplen con las especificaciones, pero es una meta más alcanzable y rentable.
aaaaaa
77
@aaaaaa, la razón por la que casi ningún servicio se ajusta a REST es que nadie puede decidir qué es REST. El único punto de acuerdo que he encontrado es que "todos los demás lo están haciendo mal".
Mark
16
- "¿Cómo describir un cambio arquitectónico que intencionalmente rompe los estándares REST?" - falta de respeto . ( Perdón por un comentario poco profesional, fue más fuerte que yo. )
luk32

Respuestas:

49

No estoy seguro de cómo describir mejor este enfoque cuando mi recomendación es continuar con la pila de tecnología existente, pero implementar cambios fundamentales en las ubicaciones donde pertenece el código.

Service oriented architecture.

Usted propone rediseñar su sistema para que sus reglas comerciales y sus datos estén en el mismo lugar. Esa es efectivamente la definición de un servicio ; vea la charla de Udi Dahan sobre Encontrar límites de servicio .

Barra lateral: como señaló Eric, esto no tiene nada que ver con "REST". No hay absolutamente ninguna razón por la que no pueda poner una API REST (es decir, una API que satisfaga las restricciones del estilo arquitectónico REST ) frente a su servicio. Pero eso puede no ser obvio para las personas que entienden que REST significa una asignación de operaciones de base de datos a métodos HTTP.

Puede, o no, valer la pena invertir en cambiar la comprensión de REST por parte de su audiencia.

VoiceOfUnreason
fuente
32
Tampoco puede valer la pena invertir en REST. Si lees la disertación de Roy Fielding (o cómo le expliqué REST a mi esposa ), el verdadero propósito de REST es proporcionar una representación canónica de los recursos en Internet, para que máquinas dispares en Internet tengan una forma estándar de manipular esos recursos . Es posible que una aplicación privada ni siquiera necesite esta capacidad.
Robert Harvey
29

REST no es CRUDO. Ese "contraargumento" se basa en una comprensión fundamentalmente defectuosa de lo que es REST. No he visto nada en su publicación que indique que su cambio haría que su API sea más o menos RESTANTE.

Eric Stein
fuente
66
Bueno, no, no es un mapeo perfecto para CRUD, pero sí camina, habla y canta mucho como CRUD, al menos en la forma en que la mayoría de la gente lo interpreta.
Robert Harvey
11
@RobertHarvey Creo que es ese (mal) entendimiento el problema aquí.
JimmyJames
44
@JimmyJames: Es un malentendido generalizado. Hay un fuerte impulso para hacer las cosas "tranquilas" cuando la mayoría de las personas ni siquiera entienden cuáles son los beneficios o cómo esos beneficios se aplicarían a ellos.
Robert Harvey
44
@RobertHarvey Creo que estás diciendo que si hacerlo de la manera incorrecta es REST, entonces REST no debería ser un objetivo. Está bien, pero a mi modo de ver, llamar a esto "no DESCANSO" es una mierda y soy un gran defensor de llamar la mierda a los imbéciles. Las palabras necesitan un significado comúnmente entendido para ser útiles.
JimmyJames
55
@RobertHarvey De acuerdo, pero eso no sucederá mientras haya suficientes personas que estén dispuestas a corregir estos abusos del término. No estoy listo para tirar la toalla.
JimmyJames
24

Una cosa más a tener en cuenta es lo siguiente ... No validar el lado del servidor de reglas de negocio, significa que confía implícitamente en todo lo que entra, por ejemplo, una solicitud POST, es válido.

Lo que significa que, por ejemplo, si bien su aplicación angular puede verificar si el cliente tiene un rango de edad válido y se asegura de que los usuarios legítimos reciban los comentarios correctos, cualquiera que conozca la URL de su API puede hacer una solicitud POST que contenga algunos valores no legítimos que ya no se validará.

Por lo tanto, mi sugerencia sería mover las reglas de su negocio a la API, permitirle validar la entrada y devolver los errores apropiados (o tal vez solo códigos que indiquen qué salió mal) en el cuerpo de la respuesta. Esos códigos pueden ser utilizados por su aplicación front-end para indicar qué salió mal.

mrsmn
fuente
55
Esta es, con mucho, la respuesta más útil aquí: la API es la superficie de ataque, no la entrada al cliente. Cualquier solicitud de API puede ser falsificada. Por lo tanto, cualquier cosa que se pueda hacer con la API pura es lo que un kiddie de script malintencionado y sin talento puede hacer. El software del cliente se puede utilizar para proporcionar una mejor experiencia de usuario, pero es el servidor el que necesita hacer cumplir las reglas.
cmaster
10

Para agregar a las otras buenas respuestas aquí:

Su interfaz, REST o de otro modo, no debe estar limitada en función de algún tipo de suposiciones en torno a los detalles de implementación. Esto es completamente antitético a la noción de servicios como una capa de abstracción.

Uno de los principales beneficios del uso de los servicios es que los detalles de implementación se pueden cambiar sin que los clientes tengan que hacer nada. Por lo que ha descrito, parece que no hay una capa de abstracción real. Los detalles de la implementación han sido expuestos a través de HTTP. Nada sobre REST dice que sea necesario, útil o deseable. De hecho, creo que podría argumentar que ciertas partes de la definición REST significan que esto es, de hecho, una implementación no RESTful.

Lo que sugiere es cómo se debe diseñar una capa de servicio adecuada. Si alguien te dice que no puedes hacerlo porque no es RESTful, eso es lamentable. Puede estar seguro de que alguien que le dice que sabe poco o nada sobre REST.

Según su pregunta, tiene un recurso llamado cliente. Cualquier cosa y todo lo necesario para crear un recurso de cliente válido puede y debe manejarse en unPOST recurso base del cliente (o alternativamente / opcionalmente en un PUT a un recurso de cliente específico, si no existe). REST no dice nada acerca de cuántos registros de base de datos que necesita crear en una llamada determinada. Como comentó Colin Young, no es necesario que haya una base de datos, es completamente irrelevante cómo se implementan los servicios desde una perspectiva REST.

JimmyJames
fuente
3
REST no dice nada sobre los registros de la base de datos, y mucho menos cuántos. Podría crear un servicio REST que controlara una válvula de agua y exponga una válvula de agua, el suministro de agua y los recursos a nivel del tanque. Se podría argumentar que los objetos físicos en sí mismos son una "base de datos" pero que estiran un poco las cosas.
Colin Young
@ColinYoung Sí, gracias por ayudar a aclarar.
JimmyJames
3

Aquí hay algunas buenas respuestas, pero no estoy seguro de que te ayuden a convencer a tus compañeros de trabajo. Como muchos han señalado, lo que está sugiriendo no es alejarse del diseño RESTful, y creo que es clave para lograr que su propuesta se incorpore.

REST no se trata de asegurarse de que su API solo permita almacenar y recuperar datos. Más bien, se trata de modelar acciones como recursos. Su API debe permitir que se tomen acciones ( después de todo, es una interfaz de programación de aplicaciones). La pregunta es cómo modelar esas acciones.

En lugar de encontrar un término, los ejemplos son probablemente la mejor manera de explicar esto a sus compañeros de trabajo. . De esta manera, puede mostrar cómo lo están haciendo ahora, qué problemas esto causa, una solución que resuelve el problema y cómo sigue siendo RESTful.

Echemos un vistazo a su objeto de cliente.

Problema:

La interfaz de usuario envía a un cliente, pero las tablas posteriores aún no se han actualizado. ¿Qué sucede si una de las llamadas subsiguientes falla debido a un error en su código de UI (o mal funcionamiento del complemento del navegador, etc.)? Ahora sus datos están en un estado inconsistente. Incluso podría ser un estado que rompa otras partes de su API o interfaz de usuario, sin mencionar que simplemente no es válido. ¿Cómo te recuperas? Tendría que probar cada estado posible para asegurarse de que esto no rompería algo, pero sería difícil saber qué es posible.

Solución:

Crea un punto final API para crear clientes. Sabes que no quieres tener un punto final "/ customer / create" o incluso "/ create-customer", porque create es un verbo y violaría REST. Así que dígalo. "/ customer-creation" podría funcionar. Ahora, cuando PUBLICA su objeto CustomerCreation, enviará todos los campos necesarios para que un cliente se cree completamente. El punto final se asegurará de que los datos estén completos y sean válidos (devolviendo un valor 400 o algo así si falla la validación), y puede persistir todo en una sola transacción de base de datos, por ejemplo.

Si también necesita un punto final para OBTENER / objetos de cliente, está bien. Puedes tener ambos. El truco es crear puntos finales que satisfagan las necesidades de los consumidores.

Ventajas:

  1. Usted garantiza que no terminará con un mal estado
  2. En realidad, es más fácil para los desarrolladores de UI si no tienen que "saber" el pedido de solicitudes, preocupaciones de validación, etc.
  3. No es tan hablador de una API, lo que reduce la latencia de las solicitudes de red
  4. Es más fácil probar y conceptualizar escenarios (los datos faltantes / malformados de la interfaz de usuario no se distribuyen entre las solicitudes, algunas de las cuales pueden fallar)
  5. Permite una mejor encapsulación de la lógica empresarial.
  6. En general, facilita la seguridad (porque los usuarios pueden modificar la lógica empresarial y de orquestación en la interfaz de usuario)
  7. Es probable que reduzca la duplicación lógica (es más probable que tenga 2+ consumidores de una API que 2+ API que dan acceso a los mismos datos)
  8. Aún 100% RESTANTE

Desventajas

  1. Es potencialmente más trabajo para el desarrollador de back-end (pero puede no ser a largo plazo)

Puede ser difícil para las personas comprender este paradigma y qué tiene de bueno si no lo han probado. Esperemos que pueda ayudarlos a ver usando un ejemplo de su propio código.

Mi propia experiencia es que una vez que los desarrolladores de mi equipo comenzaron a implementar esta estrategia, casi de inmediato vieron los beneficios.

Estudio adicional:

Este artículo de Thoughtworks realmente me ayudó a tener la idea de modelar acciones como objetos usando ejemplos prácticos: https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling

También sugeriría leer sobre CQRS y Event Sourcing ya que están preocupados precisamente por este tipo de cosas (es decir, divorciar su API de la lógica de persistencia real). No sé qué tan dispuestos estarían tus compañeros de trabajo a leer este tipo de cosas, pero puede darte más claridad y ayudarte a explicárselos.

Planky
fuente
" porque crear es un verbo y violaría REST " - Absolutamente correcto. En otras palabras, sería el enfoque 47.258.346 para ejecutar " RPC sobre REST ". Lo cual es algo que atribuiría "antinatural" al menos, porque hace un mal uso y tergiversa los enfoques RESTful (tienen sus casos de uso, pero RPC no es uno de ellos) y también tiende a ser ineficiente.
JensG