J'étudie la propreté et, par conséquent, je repense de façon spectaculaire la façon dont je conçois et écris les logiciels.
Cependant, je suis encore aux prises avec des règles commerciales telles que "lors de l'enregistrement des mises à jour d'un élément, chargez d'abord toute la liste des éléments que j'ai la permission d'afficher / modifier, etc., confirmez que cet élément est dans la liste, et que la catégorie d'élément n'est pas verrouillée pour le moment, (et autres règles, etc.) ".. car il s'agit d'une règle métier (complexe mais non atypique), et doit donc être gérée dans le domaine d'application plutôt que de pousser la logique métier dans la couche db / persistance.
Cependant, il me semble que pour vérifier efficacement ces conditions, il va souvent être préférable de traiter avec une requête db bien conçue, plutôt que de charger toutes les données dans le domaine d'application ...
Sans optimisation prématurée, quelle est l'approche recommandée ou certains articles de l'oncle Bob traitant de cette question? Ou dirait-il "valider dans le domaine jusqu'à ce que cela devienne un problème" ??
J'ai vraiment du mal à trouver de bons exemples / échantillons pour autre chose que les cas d'utilisation les plus élémentaires.
Mise à jour:
Salut à tous, merci pour les réponses. J'aurais dû être plus clair, j'écris (principalement des applications Web) depuis longtemps, et j'ai certainement déjà expérimenté et d'accord avec tous les sujets que vous décrivez collectivement (validez par backend, ne faites pas confiance aux données client, d'une manière générale ne poursuivez l'efficacité brute que lorsque cela est nécessaire, mais reconnaissez les forces des outils db lorsqu'ils sont disponibles, etc., etc.) et avez suivi le cycle de vie d'apprentissage des développeurs de "tout jeter ensemble" pour "construire un contrôleur de graisse géant avec des applications à N niveaux". , et maintenant vraiment aimer et étudier le style de responsabilité propre / unique, etc., essentiellement à la suite de quelques projets récemment évolués en règles commerciales assez maladroites et largement distribuées à mesure que les projets évoluaient et que de nouvelles exigences des clients se faisaient jour.
En particulier, j'examine l'architecture de style propre dans le contexte de la création d'API REST pour les fonctionnalités orientées client et d'utilisation interne, où de nombreuses règles métier peuvent être beaucoup plus complexes que pratiquement tous les exemples que vous voyez sur le net (même par les gars de l'architecture Clean / Hex eux-mêmes).
Donc, je suppose que je demandais vraiment (et je n'ai pas dit clairement) comment Clean et une API REST s'assembleraient, où la plupart des choses MVC que vous voyez ces jours-ci ont des validateurs de demandes entrantes (par exemple la bibliothèque FluentValidation dans .NET), mais où beaucoup de mes règles de "validation" ne sont pas tellement "est-ce une chaîne de moins de 50 caractères" mais plus "cet utilisateur appelant cet utilisateur / cet interacteur peut-il effectuer cette opération sur cette collection de données étant donné qu'un objet lié est actuellement verrouillé par l'équipe X jusqu'à plus tard dans le mois etc etc "... ce genre de validations profondément impliquées où BEAUCOUP d'objets de domaine métier et de règles de domaine sont applicables.
Dois-je transformer ces règles en un type spécifique de type d'objet Validator pour accompagner chaque utilisateur-interaction (inspiré par le projet FluentValidator mais avec plus de logique métier et d'accès aux données), dois-je traiter la validation un peu comme une passerelle, dois-je mettre ces validations DANS une passerelle (ce qui je pense est faux), etc etc.
Pour référence, je pars de plusieurs articles comme celui-ci , mais Mattia ne parle pas beaucoup de validation.
Mais je suppose que la réponse courte à ma question ressemble beaucoup à la réponse que j'ai acceptée: "Ce n'est jamais facile, et cela dépend".
la source
Réponses:
La validation de la saisie de données est l'une de ces choses où tout le monde commence par essayer de la rendre pure et propre et (si elle est intelligente à ce sujet) abandonne finalement, car il y a tellement de préoccupations concurrentes.
La couche d'interface utilisateur doit effectuer certaines formes de validation directement sur la page / formulaire client afin de fournir des commentaires en temps réel à l'utilisateur. Sinon, l'utilisateur passe beaucoup de temps à attendre des commentaires pendant qu'une transaction est publiée sur le réseau.
Étant donné que le client s'exécute souvent sur une machine non approuvée (par exemple, dans presque toutes les applications Web), ces routines de validation doivent être exécutées à nouveau côté serveur où le code est approuvé.
Certaines formes de validation sont implicites en raison de contraintes d'entrée; par exemple, une zone de texte peut autoriser uniquement la saisie numérique. Cela signifie que vous pourriez ne pas avoir un "est-ce numérique?" validateur sur la page, mais vous en aurez toujours besoin à l'arrière, quelque part, car les contraintes d'interface utilisateur pourraient être contournées (par exemple en désactivant Javascript).
La couche d'interface utilisateur doit effectuer certaines formes de validation au niveau du périmètre de service (par exemple, du code côté serveur dans une application Web) afin d'isoler le système contre les attaques par injection ou d'autres formes malveillantes de saisie de données. Parfois, cette validation n'est même pas dans votre base de code, par exemple la validation de demande ASP.NET .
La couche d'interface utilisateur doit effectuer certaines formes de validation juste pour convertir les données saisies par l'utilisateur dans un format que la couche métier peut comprendre; par exemple, il doit transformer la chaîne "26/06/2017" en un objet DateTime dans le fuseau horaire approprié.
La couche métier devrait faire la plupart des formes de validation car, hé, elles appartiennent en théorie à la couche métier.
Certaines formes de validation sont plus efficaces au niveau de la couche de base de données, en particulier lorsque des vérifications d'intégrité référentielle sont nécessaires (par exemple pour garantir qu'un code d'état figure dans la liste des 50 états valides).
Certaines formes de validation doivent se produire dans le contexte d'une transaction de base de données en raison de problèmes de concurrence, par exemple la réservation d'un nom d'utilisateur unique doit être atomique afin qu'un autre utilisateur ne le saisisse pas pendant le traitement.
Certaines formes de validation ne peuvent être effectuées que par des services tiers, par exemple lors de la validation d'un code postal et d'un nom de ville.
Dans tout le système, des vérifications nulles et des vérifications de conversion de données peuvent se produire sur plusieurs couches, pour garantir des modes de défaillance raisonnables en présence de défauts de code.
J'ai vu certains développeurs essayer de codifier toutes les règles de validation dans la couche métier, puis demander aux autres couches de l'appeler pour extraire les règles métier et reconstruire la validation sur une couche différente. En théorie, ce serait formidable car vous vous retrouvez avec une seule source de vérité. Mais je n'ai jamais, jamais vu cette approche faire autre chose que compliquer inutilement la solution, et elle se termine souvent très mal.
Donc, si vous vous tuez en essayant de comprendre où va votre code de validation, soyez avisé - dans une solution pratique même à un problème modérément complexe, le code de validation finira par aller à plusieurs endroits.
la source
La validation fait partie de la couche métier.
Le fait est que la logique métier des DAO invalidera le concept des DAO. Faire une validation dans une couche supérieure entraînera une validation redondante si vous appelez des opérations commerciales à partir d'une autre cas d'utilisation.
Vous évaluez peut-être une certaine sécurité dans l'interface utilisateur. Mais cela est facultatif car les objets de domaine sécurisé feront le travail important. Dans l'interface utilisateur, les composants seront visibles ou invisibles en fonction des autorisations dont dispose l'utilisateur actuellement connecté. Mais ce n'est qu'une partie de l'expérience utilisateur. Vous ne voulez pas que l'utilisateur laisse s'exécuter des exceptions de sécurité chaque fois qu'il essaie de réaliser une action à laquelle il n'est pas autorisé.
la source
Vous voudrez peut-être vérifier votre point de vue sur qui fait quoi par rapport à la validation. Est-ce la DB, où vous savez que vous travaillez avec la DB? Ou s'agit-il d'un service (qui se trouve être soutenu et contrôlé par des opérations de base de données). Sur mon projet, chaque racine agrégée a une liste de groupes qui peuvent le lire et une liste de modificateurs. Lorsque le code recherche une racine spécifique ou une liste de racines que l'utilisateur peut voir, tous les détails sont cachés derrière un service qui prend l'ID utilisateur et les parties supplémentaires du contexte de recherche comme l'endroit où la tuile commence par «bla». Le code ne se soucie pas que la base de données effectue une vérification d'existence pour voir si les groupes d'utilisateurs existent dans les groupes de lecteurs. Il attend simplement une liste avec ou sans contenu en fonction de ce que le service, défini par contrat uniquement, fournit.
Cela s'applique à tous les calques. L'uniformité de la validation est la clé. Mettez autant de validation que possible dans le domaine. Renvoyez les contraintes avec votre api. Je ne pense finalement pas aux contraintes provenant de la bibliothèque X ou du stockage Z, mais du service.
la source
Si une logique de validation est exprimée de la manière la plus simple et la plus claire sous la forme d'une requête de base de données, alors allez-y, vous avez votre réponse. Mais l' efficacité ne devrait être une préoccupation que si vous avez un problème de performance connu, sinon c'est une optimisation prématurée.
la source