Administrar validaciones del lado del cliente y del lado del servidor en un solo lugar

17

Estoy 100% de acuerdo con el caso de que uno definitivamente debería usar validaciones de datos tanto del lado del cliente como del lado del servidor.

Sin embargo, en los marcos y entornos en los que he trabajado, los enfoques que he visto nunca han sido SECOS. La mayoría de las veces no hay un plan o patrón: las validaciones se escriben en la especificación del modelo y las validaciones se escriben en el formulario de la vista. (Nota: la mayor parte de mi experiencia de primera mano es con Rails, Sinatra y PHP con jQuery)

Reflexionando sobre ello, parece que no sería difícil crear un generador que, dado un conjunto de validaciones (por ejemplo, nombre del modelo, campo (s), condición), podría producir tanto el material necesario del lado del cliente como del lado del servidor. Alternativamente, dicha herramienta podría tomar las validaciones del lado del servidor (como el validatescódigo en un modelo ActiveRecord) y generar validaciones del lado del cliente (como los complementos jQuery, que luego se aplicarían al formulario.

Obviamente, lo anterior es solo una reflexión "oye, tuve esta idea", y no una propuesta formal. Este tipo de cosas seguramente es más difícil de lo que parecía cuando la idea me golpeó.

Eso me lleva a la pregunta: ¿cómo abordaría el diseño de una técnica de "escribir una vez, ejecutar en el servidor y el cliente" para la validación de datos?

Subtemas relacionados: ¿Existen herramientas como esa para marcos específicos o tecnologías cliente-servidor? ¿Cuáles son los principales problemas o desafíos al tratar de mantener solo un conjunto de validaciones?

asfallows
fuente

Respuestas:

6

En mi experiencia limitada, los puntos donde se requiere validación son

  1. El nivel de presentación usando HTML,
  2. en el nivel posterior a la presentación (es decir, validación de Javascript),
  3. en el nivel de combinación donde las interacciones entre múltiples campos deben validarse juntas,
  4. a nivel de lógica de negocios y
  5. a nivel de la base de datos.

Cada uno de ellos tiene diferentes idiomas, tiempos y disparadores. Por ejemplo, tiene poco sentido validar un campo antes de que todo el registro esté en un estado coherente, a menos que desee validar solo una pieza. Las restricciones en el nivel de la base de datos tienen que ser aplicables solo al final antes de una confirmación, y no pueden hacerse fácilmente por partes.

Un concepto relacionado es que la representación de datos varía entre cada uno de los niveles. Un ejemplo simple es que un navegador web representa un fragmento de texto como, quizás, CP1290, mientras que la base de datos lo representa en UTF-8; las longitudes de las dos cadenas difieren, por lo que aplicar restricciones de longitud se vuelve incómodo.

BobDalgleish
fuente
Sí, diferentes lenguajes y marcos hacen que esto sea poco práctico. No es "imposible de deshacer" porque con suficientes recursos podría hacerse, pero escribir convertidores automáticos entre idiomas es una tarea ENORME. Hacerlo en un plazo razonable y luego mantenerlo a medida que cambien las tecnologías relevantes sería mucho trabajo.
Michael Durrant
Definitivamente es cierto que muchas validaciones del lado del servidor (por ejemplo, la unicidad de un campo) no se pueden realizar en el navegador. Sin embargo, también es cierto que cualquier validación del lado del cliente debe repetirse en el servidor, ya que no puede confiar en el cliente. Ahí es donde veo que SECAR las cosas es especialmente útil. Por ejemplo, podría ver que una gema que extiende Rails form_forpara proporcionar automáticamente el código de validación del lado del cliente es muy útil.
Dan
5

Una consideración que a menudo limita las soluciones es el viaje de ida y vuelta de la red. Se supone que el cliente valida los datos del usuario sin enviar un mensaje a través de la red. En otras palabras, cuando el usuario presiona el botón de enviar, se supone que el cliente valida los datos localmente.

Primero, supongamos que no tenemos esta limitación. Podríamos comunicarnos con un punto final de red que sea bueno para articular problemas de validación. Por ejemplo, cuando envía su nuevo registro de Usuario, en lugar de responder con un código de error HTTP de vainilla, podría devolver una respuesta JSON detallada que detalla los problemas y el cliente actualizará de forma inteligente la pantalla para reflejar los problemas que encontró. El punto final desempeña el papel de una puerta de enlace de validación.

Está SECO pero no sin inconvenientes. Primero, depende de la red de ida y vuelta que grava a nuestro servidor con validaciones que podrían haberse manejado del lado del cliente. En segundo lugar, el diseño anticipa que todas las operaciones CRUD ocurrirán a través de nuestros puntos finales, pero ¿qué pasa cuando los desarrolladores y procesos omiten nuestra capa de acceso a datos yendo directamente contra la base de datos ?

Revisemos nuestra solución para superar estos inconvenientes. En su lugar, almacenemos y comuniquemos nuestras validaciones como metadatos:

{field: 'username', type: 'required'}
{field: 'username', type: 'unique'} //requires a network roundtrip
{field: 'password', type: 'length', min: 10, max: 50}
{field: 'password', type: 'contains', characters: ['upper', 'special', 'letter', 'number']}

Tanto el cliente como el servidor tendrían algún mecanismo (por ejemplo, un motor) para interpretar y aplicar estos datos. (Algunos lo llaman la mónada libre, ya que separa la parte declarativa de su intérprete). En JavaScript podríamos asignar cada pieza de información a las funciones de trabajo. Para arrancar, podemos enseñar a cualquier capa de nuestra arquitectura, incluida nuestra base de datos, a aplicar validaciones de manera consistente.

Mario T. Lanza
fuente
¿Cómo describe un campo cuando un campo se representa de manera diferente en el navegador web, el transporte, el lenguaje de implementación y la base de datos? Por ejemplo, la cantidad de bytes necesarios para representar un campo de cadena varía cuando se utilizan CP1290 (IE), UTF-8 (JSON), UTF-8 (C #) o UCS-16 (Oracle). ¿Qué significa una restricción de longitud? ¿Más importante para el navegador, cuando la representación de caracteres depende del navegador y del sistema operativo?
BobDalgleish
Estas limitaciones están dirigidas como modelo mental a los seres humanos. Su trabajo como programador es abstraer las diferencias a la máquina para que la persona no tenga que preocuparse por las diferencias técnicas.
Mario T. Lanza
Te perdiste completamente el punto. Hasta ahora, nadie ha presentado una abstracción que permita la validación de extremo a extremo, con una especificación. Desde el OP, "escribir una vez" implica que tener diferentes cláusulas que aborden diferentes etapas no califica. Del mismo modo, no veo nada en su validación propuesta que aborde la validación entre campos o entre objetos.
BobDalgleish
Las validaciones intercampo / objeto no son muy difíciles. Los metadatos solo representan la relación. Escribir una vez implica que puedo escribir una sola validación una vez y aplicarla en varios sitios, lo que hace. Agrega metadatos a una tabla. Cualquier sitio recibe esos metadatos y una clase / utilidad / motor simple impone la restricción.
Mario T. Lanza
1
Tal lenguaje de validación sería extremadamente útil. Podría reemplazar quizás un tercio del código involucrado con las aplicaciones web intensivas de IU.
BobDalgleish
2

Una forma sería utilizar el mismo lenguaje / marco tanto en el lado del servidor como del cliente.

P.ej

Node.js :: Cliente / Servidor en JavaScript GET :: Cliente / Servidor en Java

En este caso, la mayoría del código de "Objeto de dominio" sería común, eso incluiría la validación. Framework invocará el código según sea necesario. Por ejemplo, se invocaría el mismo código en el navegador antes de "enviar" y en el servicio web del lado del servidor.

EDITAR (junio / 2014): con Java 8, ahora también es fácil integrar el código de validación JS en aplicaciones Java. Java 8 tiene un nuevo motor de ejecución JS que es más permanente (por ejemplo, hace uso de invokeDynamic).

Shamit Verma
fuente
Cuando se trata de la base de datos SQL, no estoy seguro de cómo funcionaría.
Michael Durrant
Tampoco resuelve el problema de que el navegador y el sistema operativo afectan el dominio de entrada.
BobDalgleish
@Micheal Durrant, para la validación de la base de datos, se implementan como restricciones de base de datos (como clave externa, única, etc.). BobDalgleish, 1. El problema de la compatibilidad del navegador / sistema operativo se puede mitigar mediante el uso de una biblioteca que ajusta el tiempo de ejecución de acuerdo con el navegador (como Sencha) 2. La compatibilidad del navegador no afecta las partes "lógicas" del código, como la validación, por lo general, los problemas de compatibilidad son alrededor del renderizado DOM / UI.
Shamit Verma
0

Estaba pensando en el mismo problema. Estaba pensando en usar ANTLR para obtener un árbol de sintaxis abstracta tanto en C # como en JavaScript. A partir de ahí, utiliza los caminadores de árboles para aplicar las acciones especificadas en el lenguaje a los objetos que se validarán.

Entonces, podría almacenar una descripción de la validación requerida donde quiera, posiblemente en la base de datos.

Así es como abordaría el problema.

Marcus
fuente