37 votes

Objets de gestion, validation et exceptions

J'ai lu quelques questions et réponses concernant les exceptions et leur utilisation. Semble être une opinion forte que les exceptions doivent être soulevée que par exception non gérée cas. De sorte que me conduire à se demander comment la validation fonctionne avec business objects.

Disons que j'ai un objet métier avec des getters/setters pour les propriétés de l'objet. Disons que j'ai besoin de valider que la valeur est comprise entre 10 et 20. C'est une règle d'entreprise de sorte qu'il appartient à mon objet de l'entreprise. De sorte que semble dire pour moi que le code de validation va dans mon setter. Maintenant, j'ai mon INTERFACE utilisateur lié aux données sur les propriétés de l'objet de données. L'utilisateur entre 5, de sorte que la règle doit échouer et l'utilisateur n'est pas autorisé à sortir de la zone de texte. . L'INTERFACE utilisateur est lié aux données de la propriété de sorte que le poseur va être appelé, la règle vérifiée et a échoué. Si j'ai soulevé une exception de mon business object-à-dire la règle d'échec, l'INTERFACE utilisateur serait de ramasser ça. Mais cela semble aller à l'encontre de l'usage privilégié pour les exceptions. Étant donné que c'est un setter, vous ne vont pas vraiment avoir un "résultat" pour le setter. Si j'ai mis un autre drapeau sur l'objet alors qu'impliquerait l'INTERFACE utilisateur doit vérifier que le drapeau après chaque interaction de l'INTERFACE utilisateur.

Alors, comment devriez-le travail de validation?

Edit: j'ai probablement utilisé un exemple simplifié ici. Quelque chose comme la gamme case ci-dessus pourrait être facilement manipulé par l'INTERFACE utilisateur, mais que faire si le valdation était plus compliquée, par exemple, l'objet de l'entreprise calcule un nombre en fonction de l'entrée et si le nombre calculé est hors de portée, il devrait être recjected. C'est d'une logique plus compliquée que ne devrait pas être dans l'INTERFACE utilisateur.

Il y a aussi la considération de nouvelles données entrées basées sur un terrain déjà entré. e.g.- Je entrer un élément de l'ordre pour obtenir un certain informaion comme en stock, du coût actuel, etc. L'utilisateur peut avoir besoin de cette information pour prendre des décisions sur la poursuite de l'entrée (comme le nombre d'unités à commander) ou il peut être nécessaire afin de poursuivre la validation à faire. Si un utilisateur d'être en mesure d'entrer dans d'autres domaines si l'élément n'est pas valide? Quel serait le sens?

18voto

Mac Points 4570

Vous souhaitez vous plonger un peu dans le remarquable ouvrage de Paul Stovell concernant la validation des données. Il a résumé ses idées à un moment donné dans cet article. Je partage son point de vue sur la question, que j'ai mis en place dans mes propres bibliothèques.

Voici, dans les paroles de Paul, les inconvénients de lancer des exceptions dans les setters (basé sur un échantillon où un Name de la propriété ne doit pas être vide) :

  • Il peut y avoir des moments où vous avez vraiment besoin d'avoir un nom vide. Par exemple, la valeur par défaut pour "Créer un compte" du formulaire.
  • Si vous êtes en s'appuyant sur le présent de valider les données avant de les enregistrer, vous allez manquer le cas où les données sont déjà invalide. Par cela, je veux dire, si vous chargez un compte à partir de la base de données avec un nom vide et ne pas la changer, vous pourriez ne jamais savoir qu'il n'était pas valide.
  • Si vous n'êtes pas à l'aide de la liaison de données, vous devez écrire beaucoup de code avec try/catch blocs de montrer à ces erreurs de l'utilisateur. En essayant de montrer les erreurs sur le formulaire que l'utilisateur est en le remplissant devient très difficile.
  • Je n'aime pas jeter des exceptions pour les non-choses exceptionnelles. Un utilisateur paramètre le nom d'un compte de "Supercalafragilisticexpialadocious" n'est pas une exception, c'est une erreur. C'est, bien sûr, une chose personnelle.
  • C'est très difficile d'obtenir une liste de toutes les règles qui ont été brisés. Par exemple, sur certains sites, vous verrez la validation des messages tels que "le Nom doit être saisi. L'adresse doit être saisie. E-mail doit être saisi". Pour l'afficher, vous allez avoir besoin de beaucoup d' try/catch blocs.

Et voici les règles de base pour une solution alternative :

  1. Il n'y a rien de mal à avoir une défaillance de business object, tant que vous n'essayez pas de persister.
  2. Tout et tout cassé règles devraient être accessibles à partir de l'objet de l'entreprise, de sorte que la liaison de données, ainsi que votre propre code, on peut voir si il y a des erreurs et de les gérer de façon appropriée.

8voto

Mike Thompson Points 4178

En supposant que vous avez séparé de validation et de persister (c'est à dire enregistrer dans la base de données) du code, je voudrais faire le suivant:

  1. L'INTERFACE utilisateur doit effectuer la validation. Ne jetez pas exception ici. Vous pouvez alerter l'utilisateur d'erreurs et d'empêcher l'enregistrement d'être sauvé.

  2. Votre base de données enregistrer le code devrait jeter un argument invalide exceptions pour de mauvaises données. Il est logique de le faire ici, puisque vous ne pouvez pas procéder à la base de données en écriture à ce point. Idéalement, on ne devrait jamais se produire depuis l'INTERFACE utilisateur doit prévenir l'utilisateur d'enregistrer, mais vous avez encore besoin pour assurer la cohérence de base de données. Aussi, vous pourrait être l'appel de ce code à partir d'autre chose que de l'INTERFACE utilisateur (par exemple, mises à jour par lot) où il n'existe pas de données de l'INTERFACE de validation.

8voto

jeremcc Points 3720

J'ai toujours été un fan de Rocky Lhotka de l'approche dans le cadre de l'AAPC (comme mentionné par Charles). En général, il est piloté par le poseur ou en appelant explicitement la méthode de validation, une collection de BrokenRule objets est conservée en interne par l'entreprise d'objet. L'INTERFACE utilisateur doit simplement vérifier une méthode IsValid sur l'objet, qui à son tour vérifie le nombre de BrokenRules, et gérer de manière appropriée. Alternativement, vous pouvez facilement avoir la validation de la méthode de déclencher un événement dont l'INTERFACE d'utilisateur peut manipuler (probablement le plus propre de l'approche). Vous pouvez également utiliser la liste de BrokenRules pour afficher les messages d'erreur à l'utilisation, soit sous forme de résumé ou de côté le champ approprié. Bien que le cadre de l'AAPC est écrit .NET, l'approche globale peut être utilisé dans n'importe quelle langue.

Je ne pense pas que lancer une Exception est la meilleure idée dans ce cas. Je doute suivre l'école de pensée qui dit que les Exceptions doivent être pour des circonstances exceptionnelles, qu'une simple erreur de validation n'est pas. Élever un OnValidationFailed événement serait le plus propre choix, à mon avis.

En passant, je n'ai jamais aimé l'idée de ne pas laisser l'utilisateur de quitter un champ lorsqu'il est dans un état non valide. Il existe de nombreuses situations où vous pourriez avoir besoin de quitter le champ temporairement (peut-être de fixer un autre champ en premier) avant de revenir et la fixation du champ non valide. Je pense que c'est juste une des désagréments inutiles.

5voto

Charles Graham Points 8132

Vous voudrez peut-être déplacer la validation en dehors des getters et des setters. Vous pourriez avoir une fonction ou une propriété appelée IsValid qui exécuterait toutes les règles de validation. t remplirait un dictionnaire ou une table de hachage avec toutes les "règles brisées". Ce dictionnaire serait exposé au monde extérieur et vous pourrez l'utiliser pour renseigner vos messages d'erreur.

C'est l'approche qui est adoptée dans CSLA.Net.

4voto

brad Points 812

Les Exceptions ne doivent pas être jetés comme normal le cadre de la validation. Validation invoqué à partir de l'intérieur de business objects est une dernière ligne de défense, et ne devrait se produire que si l'INTERFACE utilisateur ne parvient pas à vérifier quelque chose. Comme tels, ils peuvent être traités comme toute autre exception d'exécution.

Notez qu'ici, une différence entre la définition des règles de validation et de les appliquer. Vous souhaiterez peut-être définir (c'est à dire le code ou annoter) vos règles de gestion dans votre entreprise de la couche logique, mais les invoquer à partir de l'INTERFACE utilisateur de sorte qu'ils puissent traitées de manière appropriée pour que l'INTERFACE utilisateur particulier. La façon de traiter varient en fonction de l'INTERFACE utilisateur, par exemple à base de formulaire web-apps vs ajax web-apps. Exception-sur-ensemble de validation offre très peu de possibilités de manipulation.

De nombreuses applications dupliquer leurs règles de validation, comme en javascript, le domaine de l'objet de contraintes de base de données et de contraintes. Idéalement, ces informations ne seront définis une fois pour toutes, mais la mise en œuvre de ce qui peut être défi et exige de la pensée latérale.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X