php - itemscope - tagname html
¿Cómo evitar repetir la lógica empresarial entre el cliente y el servidor? (9)
A medida que crecían las necesidades de las aplicaciones web, me encontré escribiendo más y más aplicaciones web basadas en API. Uso marcos como AngularJS para crear clientes web ricos que se comunican con estas API. Actualmente estoy usando PHP (Lumen o Laravel) para el lado del servidor / API.
El problema es que a menudo me encuentro repitiendo la lógica empresarial entre el cliente y el servidor.
Cuando digo lógica empresarial me refiero a reglas como las siguientes para un formulario de pedido:
- Puedes comprar X si compras Y.
- No puedes comprar Y si tienes Z.
- Si compras 10 de estos, obtendrás un 10% de descuento.
- Altura x Ancho x Profundidad x Costo = Costo final.
- La altura debe estar entre 10 y 20 si su ancho es mayor que 5.
- Etcétera etcétera.
Para que esta aplicación sea rápida y receptiva, la lógica para los cálculos (junto con otra lógica de negocios) se realiza en el lado del cliente. Como no debemos confiar en el cliente, luego vuelvo a verificar esos números en el lado del servidor. Esta lógica puede ser bastante compleja y escribir esta lógica compleja en ambos lugares se siente peligroso.
Tengo tres soluciones en mente:
Haga que todo lo que requiera lógica empresarial realice una llamada ajax a la API. Toda la lógica de negocios viviría en un solo lugar y se puede probar una vez. Esto podría ser lento, ya que el cliente tendría que esperar cada uno de los cambios que realice en el formulario de pedido para obtener valores y resultados actualizados. Tener una API muy rápida ayudaría con esto. El principal inconveniente es que esto puede no funcionar bien cuando los usuarios tienen conexiones deficientes (dispositivos móviles).
Escriba la lógica de negocios en el lado del cliente Y en el lado del servidor. El cliente recibe comentarios instantáneos a medida que realizan cambios en el formulario, y validamos todos los datos una vez que se envían al servidor. El inconveniente aquí es que tenemos que duplicar toda la lógica empresarial y probar ambos lados. Esto es ciertamente más trabajo y haría frágil el trabajo futuro.
¿Confía en el cliente? Escriba toda la lógica de negocios en el lado del cliente y suponga que no manipularon los datos. En mi situación actual, estoy trabajando en un creador de cotizaciones que siempre sería revisado por humanos, así que tal vez esto esté bien.
Honestamente, no estoy contento con ninguna de las soluciones, por eso me dirijo a la comunidad para pedirle consejo. ¡Me encantaría escuchar sus opiniones o enfoques sobre este problema!
Aquí hay un hilo similar acerca de si poner la lógica del lado del cliente o del lado del servidor. Al final del día, cada situación es única y garantiza un plan diferente, pero hay algunos consejos de orientación buenos en este hilo.
En primer lugar: Nunca confíes en el cliente.
Dicho esto, trato con esto todo el tiempo y, lamentablemente, no he encontrado una solución fácil. Debe realizar la validación en ambos lados, PERO, no es necesario realizar la validación completa en ambos.
Lo que hago es tratar de equilibrarlo. En el lado del cliente, realiza la mayor parte de la validación simple (pero valiosa), las cosas normales, los números deben ser números, las fechas deben ser fechas, datos dentro del rango, etc., por lo que, cuando lo envía, va al servidor para obtener la información completa. validado, pero se está asegurando, en el lado del cliente, de que la mayor parte de la información se encuentra, como mínimo, en su formato adecuado, y parte (o la mayoría) de ella, ya está validada; sin embargo, la lógica empresarial real se realiza en el lado del servidor , pero como la mayoría de los datos ya son correctos, la validación del lado del servidor probablemente aprobará la solicitud, por lo que evitará muchos reenvíos.
Ahora, ¿cómo hacerlo para que cuando necesite cambiar algo, no tenga que cambiarlo en ambos lados? Bueno, a veces no podrá evitar esto, cuando se requieren grandes cambios, PERO, los parámetros de la lógica de negocios se pueden compartir y, como sugirió, esto se puede hacer a través de ajax. Crea un archivo php, donde tiene todos los parámetros de la lógica de su negocio, y con una solicitud ajax, lo carga en el lado del cliente, solo una vez (cuando se carga el script), necesita optimizar esto, para que solo obtenga los parámetros. valores, todo lo demás ya debería estar allí en el lado del cliente, por lo que si algún valor de parámetro en la lógica de negocios cambia, solo lo cambia en su archivo de parámetros. (Si se cambia un parámetro después de que se cargó el script, la validación fallará en el lado del servidor, ahora debe decidir si los obliga a recargar el script, por lo que los parámetros están realodados o no, los hago recargarlos)
Creo que entiendes la idea. Esto es lo que hago, y funciona bastante bien para mí, me ahorra mucha grabación.
Espero que encuentres esto útil.
Hoy, la solución es claramente la de @ParthaSarathiGhosh, pero el futuro cercano seguramente nos dará otra solución ...
WebAssembly es un lenguaje ensamblador de bajo nivel que puede implementarse con su aplicación y ejecutarse en el navegador. Le permitirá solicitar algo de lógica desde el JavaScript llamando al código compilado en el ensamblaje. Esto se recomienda para los scripts pesados que ejecutan el lado del cliente, pero al mismo tiempo le permitirá reutilizar su código de back-end en el frente. De esa manera, podrá escribir su lógica para su backend y reutilizarla en el frente.
Hoy en día, esta tecnología ya es compatible con la mayoría de los navegadores modernos, pero solo está disponible desde c / c ++. Así que ya puedes usarlo si tienes estas habilidades.
Seguramente está planeado expandirlo a otro idioma también (ya que ya hay algunas investigaciones para c# - ex: blazor - y otros idiomas). Pero el nivel de madurez no parece lo suficientemente estable para la producción (incluso el equipo de desarrolladores de blazor no lo recomienda todavía para la producción).
Es solo mi opinión, pero => Logic en NodeJS es una solución para reutilizar el código javascript, pero todavía siento la necesidad de un lenguaje fuertemente tipado cuando se trata de un gran código lógico de mantenimiento. (Sí, conozco TypeScript y es realmente bueno, pero echo de menos algo). El ensamblaje web todavía es un poco joven, pero sin duda traerá una gran mejora para respetar el principio DRY.
Problema muy interesante: otra advertencia puede ser que queremos admitir el modo sin conexión, es decir, la aplicación también debe ejecutarse sin conexión.
Otra complicación adicional será si digamos que su lado agradable del servidor estaba en una tecnología como java o .Net, etc. y en el lado del cliente, está eligiendo entre herramientas como nativas o Xamarin, pero desafortunadamente no es lo mismo que el servidor.
Por lo tanto, el enfoque de Partha parece más prometedor, pero como se dice, no funcionará en modo completamente fuera de línea. Por lo tanto, un enfoque ligeramente modificado será considerar las reglas de validación como datos. Pero no datos simples, más bien digamos que "todo el maldito código son datos". Puede elegir cualquier lenguaje de código interpretado que le guste: Groovy, JavaScript, CScript, etc., pero una regla que seguirá al 100% es que TODA LA LÓGICA DE NEGOCIOS ESTÁ EN ESE CÓDIGO.
Si puede lograr esto, entonces en modo fuera de línea, cuando esté sincronizando datos, también sincronizará este tipo de datos muy especial, es decir, ¡el código! (así que no hay riesgo de "confiar" en el cliente)
Y luego, la API sin conexión y la API en línea son 100% el mismo código, pero el código está en nuestro lenguaje interpretado. Creo que este enfoque no solo solucionará este problema sino que también hará que el mantenimiento de la lógica de negocios sea mucho más simple. A menudo creamos modelos de datos muy complejos para soportar reglas; cuando de hecho en 2019, simplemente podría crear la regla con ifs / elses y será mucho más simple. Podríamos capacitar a los usuarios finales en una herramienta de scripting muy simple y lograr menos código para hacer mejores cosas.
He reunido una publicación de blog con estas ideas: https://medium.com/@thesaadahmad/business-logic-conundrum-offline-mobile-apps-a06ecc134aee
Puedes hacer una cosa más.
Cree su código de validación y lógica de negocios solo con JavaScript. Pero hazlo tan flojamente acoplado mucho. Si es posible, solo tome JSON como entrada y JSON como salida.
Luego, configure un servidor nodejs justo al lado del servidor PHP para que sirva esa lógica en el lado del cliente. De modo que en el lado del cliente se puede utilizar sin llamada AJAX.
Luego, desde el lado del servidor (PHP), cuando necesite validar y ejecutar todas esas lógicas de negocios, llame a cURL a nodejs para validar esos datos. Eso significa que es una llamada http del servidor PHP al servidor nodejs. El servidor de Nodejs tendrá otro código que tomará esos datos y los validará con el mismo código y devolverá el resultado.
De esta manera usted puede hacer
- Desarrollo más rápido (un lugar para probar tu lógica por unidad)
- Ejecución más rápida del código del cliente (no es necesario ajax, ya que los archivos javascript de la misma validación están siendo entregados por nodejs a su cliente)
- Toda la lógica de negocio irá al servidor de nodejs . (Cuando la lógica de negocios cambia, solo necesita tocar esta parte, de modo que en un futuro próximo, si también necesita crear otras interfaces, puede usar este servidor para validar sus datos. Funcionará igual que su servidor de reglas empresariales)
Lo único que debe hacer es configurar un nodejs junto al servidor PHP . Pero no necesita cambiar todo su código al servidor de nodejs.
Siento que la opción 1 es la mejor en el futuro. El primer desarrollo de API permite que toda la lógica de negocios se pruebe y funcione correctamente y permite el acceso de las interfaces. ¡Nunca debes confiar en el usuario!
El primer desarrollo de la API de poder es ilimitado en comparación con la codificación de la misma lógica una y otra vez para cada interfaz necesaria.
También estuve en esta posición cuando trabajé en algunos de mis propios proyectos. Siempre es tentador hacer uso del poder del dispositivo del cliente para hacer el trabajo pesado y luego validar los resultados en el lado del servidor. Lo que resultará en que la lógica de negocios aparezca dos veces, tanto front-end como back-end.
Creo que la opción 1 es la mejor, tiene más sentido y también parece más lógica. Si desea expandir su aplicación web a aplicaciones móviles nativas en el futuro, podrá reutilizar toda la lógica comercial llamando a esas API. Para mí, esta es una victoria masiva.
Si se preocupa si realiza demasiadas solicitudes de API y esto podría afectar el rendimiento de los dispositivos móviles, ¿quizás intente agrupar algunas de las solicitudes y realizar una única comprobación al final? Entonces, en lugar de hacer una verificación de cada campo en un formulario, haga una verificación cuando el usuario envíe el formulario completo. Además, la mayoría de la conexión a Internet será suficiente si sigue solicitando y respondiendo los datos al mínimo, así que no me preocuparé por esto.
Un problema mayor que normalmente encuentro es que su aplicación web se dividirá en secciones, y cada sección llamará a las API relevantes. El estado de la aplicación es mucho más complejo de entender, ya que el usuario podría saltar entre estos estados. Tendrá que pensar con mucho cuidado sobre el viaje del usuario y asegurarse de que el proceso no tenga errores.
Estos son algunos de los problemas comunes con los que tuve que lidiar:
- ¿Se muestra un error en la interfaz de usuario si la API devuelve uno?
- Si el usuario cometió un error y envió el formulario, debería ver un error. Pero una vez que el usuario reparó el error y lo vuelve a enviar, el error debería ocultarse y debería aparecer el mensaje de éxito.
- ¿Qué sucede si la API está defectuosa o la conexión a Internet es inestable, por lo que no se devuelve nada? ¿Se colgará la parte delantera?
- ¿Qué pasa si hay varios mensajes de error, puede / muestra la interfaz de usuario todos ellos?
Recomendaría que se realicen muchas pruebas de unidad en el front-end para garantizar que sea estable, incluso si la lógica de negocios está solo en el back-end.
Tuve el mismo problema cuando decidí crear una aplicación utilizando Laravel para el back-end y Angular 2 para el front-end. Y me parece que no hay una solución para evitar la duplicación de la lógica de negocios hasta ahora, porque:
En este momento, PHP y JavaScript no se pueden convertir de uno a otro. ¿Sería bueno si pudiéramos usar el mismo lenguaje para escribir la lógica de negocios y luego integrarlos tanto en el back-end como en el front-end? Desde este punto me lleva a otro punto:
Para lograr el objetivo, debemos escribir la lógica de negocios en un solo idioma, y hasta ahora JavaScript es la mejor solución. Como usted sabe, las secuencias de comandos de TypeScript / EMCA nos ayudan a escribir el código de manera OOP. La infraestructura de NodeJS de Meteor Framework nos ayuda a escribir código en JavaScript para ejecutarse en ambos lados Back-end y front-end.
Desde mi punto de vista, podemos usar TypeScript / EMCA para escribir paquetes para lógica empresarial, por ejemplo, una clase para validación escrita en JavaScript puede implementarse en ambos lados, así que solo escribe una vez, pero se llamará dos veces desde front-end y back-end también.
Ese es mi punto. Espero ver algunas otras soluciones para este tema muy interesante.
Una posible solución es declarar sus reglas de validación en un lenguaje abstracto declarativo como XML o esquema JSON.
Luego, en el lado del cliente, diga AngularJS: puede transformar estas reglas en un renderizador de formularios no estándar. Así que ahora en el lado del cliente terminas con formularios que validan las reglas declaradas.
Luego, en la API del lado del servidor, debe crear un motor de validación reutilizable que se validará según las reglas definidas.
Con lo que terminará es en un solo lugar, su esquema JSON o dondequiera que defina declarativamente sus reglas, en las que se definan su forma y las reglas de validación.