Gestion des validations côté client et côté serveur en un seul endroit

17

Je suis à 100% d'accord avec le cas où l'on devrait certainement utiliser les validations de données côté client et côté serveur.

Cependant, dans les cadres et les environnements dans lesquels j'ai travaillé, les approches que j'ai vues n'ont jamais été SÈCHES. La plupart du temps, il n'y a ni plan ni modèle - les validations sont écrites dans les spécifications du modèle et les validations sont écrites sous la forme sur la vue. (Remarque: la plupart de mon expérience de première main concerne Rails, Sinatra et PHP w / jQuery)

En réfléchissant, il semble qu'il ne serait pas difficile de créer un générateur qui, étant donné un ensemble de validations (par exemple, nom du modèle, champ (s), condition), pourrait produire à la fois le matériel nécessaire côté client et côté serveur. Alternativement, un tel outil pourrait prendre les validations côté serveur (comme le validatescode dans un modèle ActiveRecord) et générer des validations côté client (comme les plugins jQuery, qui seraient ensuite appliquées au formulaire).

De toute évidence, ce qui précède est juste une réflexion «hé, j'ai eu cette idée», et non une proposition officielle. Ce genre de chose est sûrement plus difficile qu'il n'y paraissait lorsque l'idée m'a frappé.

Cela m'amène à la question: comment aborderiez-vous la conception d'une technique «écrire une fois, exécuter sur le serveur et le client» pour la validation des données?

Sous-thèmes connexes: Des outils comme celui-ci existent-ils pour des cadres ou des technologies client-serveur particuliers? Quels sont les principaux problèmes ou défis liés à la tentative de maintenir un seul ensemble de validations?

jachères
la source

Réponses:

6

Dans mon expérience limitée, les points où une validation est requise sont

  1. Le niveau de présentation en HTML,
  2. au niveau post-présentation (ie validation Javascript),
  3. au niveau de la combinaison où les interactions entre plusieurs champs doivent être validées ensemble,
  4. au niveau de la logique métier et
  5. au niveau de la base de données.

Chacun d'eux a des langues, des horaires et des déclencheurs différents. Par exemple, il est peu logique de valider un champ avant que l'enregistrement entier ne soit dans un état cohérent, à moins que vous ne vouliez valider qu'une seule pièce. Les contraintes au niveau de la base de données doivent être applicables uniquement à la fin avant une validation et ne peuvent pas être facilement exécutées par morceaux.

Un concept connexe est que la représentation des données varie entre chacun des niveaux. Un exemple simple est un navigateur Web représentant un morceau de texte comme, peut-être, CP1290, tandis que la base de données le représente en UTF-8; les longueurs des deux chaînes diffèrent, donc l'application de contraintes de longueur devient gênante.

BobDalgleish
la source
yup, différents langages et frameworks rendent cela impossible. Pas "impossible" car avec suffisamment de ressources, cela pourrait être fait, mais l'écriture de convertisseurs automatiques vers et entre les langues est une tâche ÉNORME. Le faire dans un délai raisonnable, puis le maintenir au fur et à mesure que les technologies pertinentes changent, serait beaucoup de travail.
Michael Durrant
Il est certainement vrai que de nombreuses validations côté serveur (par exemple l'unicité d'un champ) ne peuvent pas être effectuées dans le navigateur. Cependant, il est également vrai que toutes les validations côté client doivent être répétées sur le serveur, car vous ne pouvez pas faire confiance au client. C'est là que je vois le séchage des choses particulièrement utile. Par exemple, j'ai pu voir un joyau qui étend Rails ' form_forpour fournir automatiquement un code de validation côté client très utile.
Dan
5

Une considération qui limite souvent les solutions est l'aller-retour du réseau. Le client est censé valider les données utilisateur sans envoyer de message sur le réseau. En d'autres termes, lorsque l'utilisateur clique sur le bouton d'envoi, le client est censé valider les données localement.

Supposons tout d'abord que nous n'avons pas cette limitation. Nous pourrions communiquer avec un point d'extrémité de réseau qui est bon pour articuler les problèmes de validation. Par exemple, lorsque vous lui soumettez votre nouvel enregistrement d'utilisateur, plutôt que de répondre avec un code d'erreur HTTP vanille, il peut renvoyer une réponse JSON détaillée détaillant les problèmes et le client met à jour intelligemment l'affichage pour refléter les problèmes rencontrés. Le point de terminaison joue le rôle d'une passerelle de validation.

C'est SEC mais pas sans inconvénients. Tout d'abord, cela dépend de l'aller-retour du réseau taxant notre serveur avec des validations qui auraient pu être traitées côté client. Deuxièmement, la conception prévoit que toutes les opérations CRUD se produiront via nos points de terminaison, mais qu'en est-il lorsque les développeurs et les processus contournent notre couche d'accès aux données en allant directement contre la base de données ?

Revoyons notre solution pour surmonter ces inconvénients. Au lieu de cela, stockons et communiquons nos validations en tant que métadonnées:

{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']}

Le client et le serveur auraient tous deux un mécanisme (par exemple un moteur) pour interpréter et appliquer ces données. (Certains appellent cela la monade libre car elle sépare la partie déclarative de son interprète.) En JavaScript, nous pourrions mapper chaque information sur des fonctions de travail. Pour démarrer, nous pouvons apprendre à n'importe quelle couche de notre architecture, y compris notre base de données, à appliquer les validations de manière cohérente.

Mario T. Lanza
la source
Comment décrivez-vous un champ lorsqu'un champ est représenté différemment dans le navigateur Web, le transport, le langage d'implémentation et la base de données? Par exemple, le nombre d'octets requis pour représenter un champ de chaîne varie lors de l'utilisation de CP1290 (IE), UTF-8 (JSON), UTF-8 (C #) ou UCS-16 (Oracle). Que signifie une contrainte de longueur? Plus important encore pour le navigateur, lorsque la représentation des caractères dépend du navigateur et du système d'exploitation?
BobDalgleish
Ces contraintes visent un modèle mental pour les êtres humains. Votre travail en tant que programmeur consiste à résumer les différences avec la machine afin que la personne n'ait à se soucier d'aucune différence technique.
Mario T. Lanza
Vous avez complètement raté le point. Jusqu'à présent, personne n'a présenté d'abstraction permettant la validation de bout en bout, avec une seule spécification. Du PO, "écrire une fois" implique que le fait d'avoir des clauses différentes qui traitent de différentes étapes n'est pas admissible. De même, je ne vois rien dans votre validation proposée qui traite de la validation entre champs ou interobjets.
BobDalgleish
Les validations inter-champs / objets ne sont pas très étendues. Les métadonnées représentent simplement la relation. Écrire une fois implique que j'écris une seule validation une fois et que je la fasse appliquer sur plusieurs sites, ce qui est le cas. Vous ajoutez des métadonnées à une table. Ces métadonnées sont reçues par n'importe quel site et une simple classe / utilitaire / moteur applique la contrainte.
Mario T. Lanza
1
Un tel langage de validation serait extrêmement utile. Il pourrait remplacer peut-être un tiers du code impliqué dans les applications Web à forte intensité d'interface utilisateur.
BobDalgleish
2

Une façon serait d'utiliser le même langage / framework à la fois côté serveur et côté client.

Par exemple

Node.js :: Client / Serveur en JavaScript GET :: Client / Serveur en Java

Dans ce cas, la plupart du code "Objet de domaine" serait commun, ce qui inclurait la validation. Framework invoquera le code selon les besoins. Par exemple, le même code serait invoqué dans le navigateur avant de «soumettre» et sur le service Web côté serveur.

EDIT (juin / 2014): Avec Java 8, il est désormais facile d'intégrer également le code de validation JS dans les applications Java. Java 8 possède un nouveau moteur d'exécution JS qui est plus permanent (ex: il utilise invokeDynamic).

Shamit Verma
la source
En ce qui concerne la base de données SQL, je ne sais pas comment cela fonctionnerait.
Michael Durrant
Cela ne résout pas non plus le problème que le navigateur et le système d'exploitation affectent le domaine d'entrée.
BobDalgleish
@Micheal Durrant, pour la validation de la base de données sont implémentées en tant que contraintes de base de données (telles que clé étrangère, unique, etc.). BobDalgleish, 1. Le problème de compatibilité navigateur / système d'exploitation peut être atténué en utilisant une bibliothèque qui modifie l'exécution en fonction du navigateur (comme Sencha) 2. La comatibilité du navigateur n'a pas d'impact sur les parties "logiques" du code telles que la validation, les problèmes de compatibilité sont généralement autour du rendu DOM / UI.
Shamit Verma
0

Je pensais juste au même problème. Je pensais utiliser ANTLR pour obtenir une arborescence de syntaxe abstraite en C # et en javascript. À partir de là, vous utilisez des arborescents pour appliquer les actions spécifiées dans le langage aux objets à valider.

Ainsi, vous pouvez stocker une description de la validation requise où vous le souhaitez - éventuellement dans la base de données.

C'est ainsi que j'aborderais le problème.

Marcus
la source