Je travaille sur un système qui permet aux administrateurs de définir des formulaires contenant des champs. Les formulaires définis sont ensuite utilisés pour saisir des données dans le système. Parfois, les formulaires sont remplis par un humain via une interface graphique, parfois le formulaire est rempli en fonction des valeurs rapportées par un autre système.
Pour chaque champ, l'administrateur peut définir une règle de validation qui limite les valeurs autorisées pour le champ. Les règles de validation peuvent aller de "la valeur entrée dans le champ doit être vraie ou fausse" à "la valeur entrée dans le champ doit exister dans la colonne A du tableau B dans la base de données". L'administrateur peut à tout moment modifier la règle de validation du champ.
Dans ce scénario, quel est, à votre avis, l'endroit le plus approprié pour valider que chaque champ est correctement rempli? J'ai actuellement deux approches principales en tête:
Option # 1: valider dans le modèle de domaine
Chaque objet Field contiendrait la règle de validation spécifiée par l'administrateur. Les objets Field auraient également une référence à un IValidator. Lorsqu'une tentative est effectuée pour définir la valeur du champ, le champ transmet la valeur donnée et la règle de validation à l'IValidator. Si la valeur donnée n'est pas valide, une ValidationException serait levée et gérée de manière appropriée dans l'interface graphique / l'interface vers l'autre système.
Avantages:
- Protection élevée contre les valeurs attribuées accidentellement aux champs qui violent la règle de validation
Les inconvénients:
La couche d'accès aux données doit pouvoir contourner la validation et construire des champs qui violent la règle de validation actuelle. Bien que l'administrateur ait modifié la règle de validation d'un champ, nous devons encore pouvoir construire des objets de champ sur la base des anciennes données, par exemple lors du rendu d'un formulaire rempli il y a des années. Cela pourrait potentiellement être résolu en stockant la règle de validation actuelle chaque fois que nous stockons le champ.
Dans cette conception, le modèle Field a un lien indirect avec la couche d'accès aux données / référentiel via IValidator. L'injection de services / référentiels aux modèles de domaine semble généralement mal vue .
Option # 2: Valider dans un service
Essayez de vous assurer que toutes les tentatives de définition de la valeur d'un champ passent par un service garantissant le respect de la règle de validation. Si la règle de validation est violée, lancez une ValidationException.
Bien entendu, la couche d'accès aux données n'utilisera pas le service lors de la création d'objets Field qui ont été précédemment conservés dans la base de données.
Avantages:
Ne viole pas la pensée "ne pas injecter de services / référentiels dans vos modèles de domaine".
Pas besoin de conserver la règle de validation actuelle lors de la persistance du champ. Le service peut simplement rechercher la règle de validation actuelle pour le champ; lorsque vous regardez les données d'historique, la valeur du champ ne sera pas modifiée.
Les inconvénients:
- Aucune garantie que toute logique devant utiliser le service pour définir la valeur du champ le fait réellement. Je vois cela comme un inconvénient majeur; tout ce qu'il semble prendre, c'est quelqu'un qui écrit "thisField.setValue (thatField.getValue ())" et la règle de validation de thisField peut être violée sans que personne ne soit plus sage. Cela pourrait potentiellement être atténué en s'assurant que la valeur du champ correspond à la règle de validation lorsque la couche d'accès aux données est sur le point de conserver le champ.
Je préfère actuellement l'option n ° 1 à l'option n ° 2, principalement parce que je considère cela comme une logique métier et je pense que l'option n ° 2 présente un plus grand risque d'introduire de mauvaises données dans le système. Quelle option préférez-vous ou existe-t-il une autre conception qui correspond mieux à ce scénario que les deux options décrites?
Edit (Complexité des validations)
Les cas de validation qui se sont présentés jusqu'à présent sont relativement simples; la valeur du champ doit être par exemple numérique, une date, une date avec une heure ou être une valeur existante dans une colonne de base de données. Cependant, je soupçonne la complexité d'augmenter progressivement avec le temps. Par exemple, la solution de validation doit être conçue en tenant compte de l'internationalisation - des éléments tels que les dates peuvent être saisis dans une syntaxe locale spécifique.
J'ai décidé de continuer avec l'option # 1 pour l'instant, en essayant de ne pas attribuer trop de responsabilités au modèle de domaine. Les personnes confrontées à une situation similaire peuvent également consulter les questions connexes Validation et autorisation dans l'architecture en couches et validation de la saisie de données - Où? Combien? .