Lors de la levée d'une exception?

j'ai créé des exceptions pour chaque condition que mon application ne s'attend pas. UserNameNotValidException , PasswordNotCorrectException etc.

cependant, on m'a dit que je ne devais pas créer d'exceptions pour ces conditions. Dans mon UML, ce sont des exceptions au flux principal, alors pourquoi ne le serait-il pas?

Toute orientation ou de meilleures pratiques pour la création d'exceptions?

375
demandé sur Kwan Cheng 2008-09-17 01:09:02
la source

30 ответов

Ma Ligne directrice personnelle est: une exception est lancée quand une hypothèse fondamentale du bloc de code actuel est trouvé pour être faux.

exemple 1: disons que j'ai une fonction qui est supposée examiner une classe arbitraire et retourner true si cette classe hérite de la liste<>. Cette fonction pose la question, "Cet objet est-il un descendant de List?"Cette fonction ne devrait jamais jeter une exception, parce qu'il n'y a pas de zones grises dans son fonctionnement - chaque classe simple soit ou n'hérite pas de Liste<>, donc la réponse est toujours "oui" ou "non".

exemple 2: disons que j'ai une autre fonction qui examine une liste<> et retourne true si sa longueur est supérieure à 50, et false si sa longueur est inférieure. Cette fonction pose la question: "cette liste comporte-t-elle plus de 50 éléments?"Mais cette question fait une supposition - elle suppose que l'objet qui lui est donné est une liste. Si je lui donne un nul, alors cette supposition est fausse. Dans ce cas, si la fonction retourne soit vrai ou faux, alors il viole ses propres règles. La fonction ne peut pas retourner quoi que ce soit et prétendre qu'elle a répondu correctement à la question. Pour qu'il ne revienne pas - il jette une exception.

c'est comparable à la " question chargée " fallacy logique. Chaque fonction pose une question. Si l'input qu'il est donné rend cette question une erreur, puis jeter un exception. Cette ligne est plus difficile à tracer avec les fonctions qui retournent void, mais la ligne de fond est: si les hypothèses de la fonction au sujet de ses entrées sont violées, elle devrait jeter une exception au lieu de retourner normalement.

l'autre côté de cette équation est: si vous trouvez vos fonctions jetant des exceptions fréquemment, alors vous devez probablement affiner leurs hypothèses.

548
répondu The Digital Gabeg 2008-11-07 00:55:18
la source

parce que ce sont des choses qui se produiront normalement. Les Exceptions ne sont pas les mécanismes de contrôle de l'écoulement. Les utilisateurs se trompent souvent de mots de passe, ce n'est pas un cas exceptionnel. Les Exceptions devraient être une chose vraiment rare, des situations de type UserHasDiedAtKeyboard .

275
répondu blowdart 2015-07-19 14:24:39
la source

mes petites lignes directrices sont fortement influencées par le grand livre "Code complet":

  • utiliser des exceptions pour notifier des choses qui ne devraient pas être ignorées.
  • N'utilisez pas d'exceptions si l'erreur peut être traitée localement
  • assurez-vous que les exceptions sont au même niveau d'abstraction que le reste de votre routine.
  • les Exceptions doivent être réservées à ce qui est vraiment exceptionnel .
55
répondu Commander Keen 2013-11-19 22:43:08
la source

Ce n'est PAS une exception, si le nom d'utilisateur n'est pas valide ou le mot de passe n'est pas correct. Ce sont des choses auxquelles vous devriez vous attendre dans le déroulement normal des opérations. Les Exceptions sont des choses qui ne font pas partie du fonctionnement normal du programme et qui sont plutôt rares.

EDIT: Je n'aime pas utiliser des exceptions parce que vous ne pouvez pas dire si une méthode lance une exception juste en regardant l'appel. C'est pourquoi les exceptions ne devraient être utilisées que si vous ne pouvez pas gérer la situation dans un manière (penser " out of memory "ou"l'ordinateur est en feu").

34
répondu EricSchaefer 2008-09-17 17:09:38
la source

une règle de base est d'utiliser des exceptions dans le cas de quelque chose que vous ne pouviez pas prévoir normalement. Les exemples sont la connectivité de base de données, le fichier manquant sur le disque, etc. Pour les scénarios que vous pouvez prédire, c'est-à-dire les utilisateurs qui tentent de se connecter avec un mauvais mot de passe, vous devriez utiliser des fonctions qui retournent booléens et savoir comment gérer la situation avec élégance. Vous ne voulez pas brusquement mettre fin à l'exécution en lançant une exception juste parce que quelqu'un a mal entré son mot de passe.

24
répondu japollock 2008-09-17 01:13:19
la source

D'autres proposent que les exceptions ne devraient pas être utilisées parce que la mauvaise connexion est à prévoir dans un flux normal si l'utilisateur se trompe. Je ne suis pas d'accord et je ne comprends pas le raisonnement. Comparer avec l'ouverture d'un fichier.. si le fichier n'existe pas ou n'est pas disponible pour une raison quelconque, alors une exception sera lancée par le framework. Utiliser la logique ci-dessus était une erreur de Microsoft. Ils auraient dû retourner un code d'erreur. Idem pour parsing, webrequests,etc., etc..

je ne considère pas un mauvais login partie d'un flux normal, c'est exceptionnel. Normalement l'utilisateur tape le mot de passe correct, et le fichier existe. Les cas exceptionnels sont exceptionnels et il est parfaitement normal d'utiliser des exceptions pour ceux-ci. Compliquer votre code en propageant les valeurs de retour à travers n niveaux vers le haut de la cheminée est un gaspillage d'énergie et résultera en code désordre. Faire la chose la plus simple qui pourrait éventuellement fonctionner. Ne pas optimiser prématurément en utilisant des codes d'erreur, choses exceptionnelles par définition, cela arrive rarement, et les exceptions ne coûtent rien à moins de les jeter.

22
répondu Bjorn Reppen 2008-09-17 01:39:01
la source

les Exceptions sont un effet assez coûteux, si par exemple vous avez un utilisateur qui fournit un mot de passe invalide, il est généralement une meilleure idée de renvoyer un drapeau d'échec, ou un autre indicateur qu'il est invalide.

cela est dû à la façon dont les exceptions sont traitées, la mauvaise entrée vraie, et les éléments critiques d'arrêt uniques devraient être des exceptions, mais pas l'information de connexion échoué.

15
répondu Mitchel Sellers 2008-09-17 01:11:17
la source

je pense que vous ne devriez jeter une exception que lorsqu'il n'y a rien que vous puissiez faire pour sortir de votre état actuel. Par exemple, si vous allouez de la mémoire et qu'il n'y en a pas à allouer. Dans les cas que vous mentionnez, vous pouvez clairement récupérer de ces états et peut retourner un code d'erreur à votre appelant en conséquence.


vous verrez beaucoup de conseils, y compris dans les réponses à cette question, que vous devriez jeter des exceptions seulement dans les circonstances "exceptionnelles". Cela semble superficiellement raisonnable, mais c'est un conseil erroné, car il remplace une question ("Quand dois-je faire une exception") par une autre question subjective ("qu'est-ce qui est exceptionnel"). Au lieu de cela, suivez les conseils de Herb Sutter (pour C++, disponible dans le article de Dr Dobbs quand et comment utiliser les Exceptions , et aussi dans son livre avec Andrei Alexandrescu, C++ Coding Standards ): jeter un exception si, et seulement si

  • une condition n'est pas remplie (qui fait généralement l'une des opérations suivantes impossible) ou
  • l'alternative de ne pas répondre à un post-condition ou
  • l'alternative ne réussirait pas à maintenir un invariant.

Pourquoi est-ce mieux? Ne remplace-t-il pas la question par plusieurs questions sur les conditions préalables, postconditions et les invariants? C'est mieux pour plusieurs raisons.

  • conditions préalables, postconditions et invariants sont conception caractéristiques de notre programme (son API interne), alors que la décision de throw est un détail de mise en œuvre. Il nous oblige à garder à l'esprit que nous devons considérer la conception et sa mise en œuvre séparément, et notre travail tout en mettant en œuvre une méthode est de produire quelque chose qui satisfait la conception contraintes.
  • il nous force à penser en termes de conditions préalables, postconditions et invariants, qui sont les seulement hypothèses que les appelants de notre méthode devrait faire, et sont exprimés précisément, permettant le couplage lâche entre les composants de notre programme.
  • que l'accouplement lâche puis nous permet de remanier la mise en œuvre, si nécessaire.
  • les post-conditions et les invariants sont testables; il les résultats dans le code qui peut être facilement testé à l'unité, parce que les post-conditions sont des prédicats notre unité-le code de test peut vérifier (affirmer).
  • penser en termes de post-conditions produit naturellement un dessin qui a succès en tant que post-condition , qui est le style naturel pour l'utilisation des exceptions. Le chemin d'exécution normal ("happy") de votre programme est présenté de manière linéaire, avec tout le code de gestion des erreurs déplacé vers les clauses catch .
13
répondu Raedwald 2018-08-01 14:58:06
la source

je dirais il n'y a pas de règles strictes sur l'utilisation des exceptions. Toutefois, il y a de bonnes raisons de les utiliser ou de ne pas les utiliser:

raisons d'utiliser les exceptions:

  • le flux de code pour le cas commun est plus clair
  • peut renvoyer des informations d'erreur complexes en tant qu'objet (bien que cela puisse aussi être réalisé en utilisant le paramètre erreur "out" passé par référence)
  • langues en général fournir une certaine facilité pour la gestion ordonnée de nettoyage dans le cas de l'exception (try/finally en Java, en C#, RAII en C++)
  • dans le cas où aucune exception n'est lancée, l'exécution peut parfois être plus rapide que la vérification des codes de retour
  • En Java, vérifié les exceptions doivent être déclarés ou pris (même si cela peut être une raison contre)

raisons de ne pas utiliser d'exceptions:

  • parfois c'est exagéré si la manipulation des erreurs est simple
  • si les exceptions ne sont pas documentées ou déclarées, elles peuvent ne pas être saisies par le code appelant, ce qui peut être pire que si le code appelant vient d'ignorer un code de retour (sortie de l'application vs échec silencieux - ce qui peut être pire dépend du scénario)
  • en C++, le code qui utilise des exceptions doit être sûr (même si vous ne les lancez pas ou ne les attrapez pas, mais appelez une fonction lancer indirectement)
  • En C++, il est difficile de dire quand une fonction peut-être jeter, donc vous devez être paranoïaque à propos de l'exception de sécurité si vous les utilisez
  • lancer et attraper des exceptions est généralement beaucoup plus coûteux que de vérifier un drapeau de retour

en général, je serais plus enclin à utiliser des exceptions en Java qu'en C++ ou C#, parce que je suis d'avis qu'une exception, déclarée ou non, fait fondamentalement partie l'interface formelle d'une fonction, car changer votre garantie d'exception peut casser le code d'appel. Le plus grand avantage de les utiliser dans Java IMO, est que vous savez que votre interlocuteur doit gérer l'exception, et cela améliore les chances de comportement correct.

pour cette raison, dans n'importe quelle langue, je déduirais toujours toutes les exceptions dans une couche de code ou API d'une classe commune, de sorte que le code appelant peut toujours garantir de saisir toutes les exceptions. Aussi je le considérerais mauvais lancer des classes d'exception qui sont spécifiques à l'implémentation, lors de l'écriture D'une API ou d'une bibliothèque (c'est-à-dire envelopper les exceptions des couches inférieures pour que l'exception que votre appelant reçoit soit compréhensible dans le contexte de votre interface).

notez que Java fait la distinction entre les exceptions générales et les exceptions D'exécution en ce que ces dernières n'ont pas besoin d'être déclarées. Je n'utiliserais les classes D'exception D'exécution que si vous savez que l'erreur est le résultat d'un bug dans le programme.

10
répondu Robert 2008-09-17 03:28:50
la source
Les classes D'Exception

ressemblent aux classes" normales". Vous créez une nouvelle classe quand il "est" un type d'objet différent, avec différents domaines et différentes opérations.

en règle générale, vous devez essayer d'équilibrer le nombre d'exceptions et la granularité des exceptions. Si votre méthode lance plus de 4-5 exceptions différentes, vous pouvez probablement fusionner certaines d'entre elles en exceptions plus "générales" (par exemple dans votre cas "AuthenticationFailedException"), et utiliser le message d'exception pour détailler ce qui a mal tourné. À moins que votre code ne gère chacun d'eux différemment, vous n'avez pas besoin de créer beaucoup de classes d'exception. Et si c'est le cas, Pouvez-vous simplement retourner un enum avec l'erreur qui s'est produite. C'est un peu plus propre de cette façon.

5
répondu Shachar 2008-09-17 01:14:00
la source

si c'est du code courant dans une boucle qui causera probablement une exception encore et encore, alors lancer des exceptions n'est pas une bonne chose, parce qu'elles sont assez lentes pour les gros N. Mais il n'y a rien de mal à lancer des exceptions personnalisées si la performance n'est pas un problème. Assurez-vous juste que vous avez une exception de base qu'ils héritent tous, appelée BaseException ou quelque chose comme ça. BaseException hérite du système.Exception, mais toutes vos exceptions héritent de BaseException. Vous pouvez même avoir un arbre des types D'Exception pour grouper des types similaires, mais cela peut être excessif ou pas.

donc, la réponse courte est que si elle ne cause pas une pénalité de performance significative (ce qui ne devrait pas sauf si vous jetez beaucoup d'exceptions), puis aller de l'avant.

5
répondu Charles Graham 2008-09-17 01:19:22
la source

je suis d'accord avec japollock way là-haut--lancez une acceptation quand vous êtes incertain de l'issue d'une opération. Appels vers des API, accès à des systèmes de fichiers, appels vers des bases de données, etc. Chaque fois que vous dépassez les "limites" de vos langages de programmation.

j'aimerais ajouter, n'hésitez pas à jeter une exception standard. Sauf si vous allez faire quelque chose de "différent" (ignorer, email, log, montrer que Twitter image baleine Machin, etc), alors ne vous embêtez pas avec la coutume exception.

3
répondu dclaysmith 2008-09-17 04:01:15
la source

la règle du pouce pour lancer des exceptions est assez simple. vous le faites lorsque votre code est entré dans un état invalide non récupérable. si les données sont compromises ou que vous ne pouvez pas revenir en arrière le traitement qui s'est produit jusqu'au point alors vous devez y mettre fin. en effet, que pouvez-vous faire d'autre? votre logique de traitement finira par échouer ailleurs. si vous pouvez récupérer d'une façon ou d'une autre alors faites-le et ne jetez pas l'exception.

dans votre cas particulier si vous avez été forcé de faire quelque chose de stupide comme accepter le retrait d'argent et seulement alors vérifier utilisateur/pasword vous devriez mettre fin au processus en jetant une exception pour notifier que quelque chose de mauvais s'est produit et prévenir d'autres dommages.

3
répondu goran 2011-12-19 15:22:35
la source

en général, vous voulez jeter une exception pour tout ce qui peut se produire dans votre application qui est" exceptionnel "

dans votre exemple, ces deux exceptions ressemblent à des appels via une validation mot de passe / nom d'utilisateur. Dans ce cas, on peut faire valoir qu'il n'est pas vraiment exceptionnel que quelqu'un maltraite un nom d'utilisateur / mot de passe.

ce sont des" exceptions "au flux principal de votre UML mais sont plus des "branches" dans le traitement.

si vous avez tenté d'accéder à votre fichier ou base de données passwd et que vous n'avez pas pu le faire, ce serait un cas exceptionnel qui justifierait une exception.

2
répondu Gord 2008-09-17 01:17:03
la source

tout d'abord, si les utilisateurs de votre API ne sont pas intéressés par des échecs spécifiques, alors avoir des exceptions spécifiques pour eux n'a aucune valeur.

Puisqu'il n'est souvent pas possible de savoir ce qui peut être utile à vos utilisateurs, une meilleure approche est d'avoir les exceptions spécifiques, mais de s'assurer qu'ils héritent d'une classe commune (par exemple, std::exception ou ses dérivés en C++). Cela permet à votre client de saisir des exceptions spécifiques s'ils le souhaitent, ou les plus générales exception si ils s'en fichent.

2
répondu Jason Etheridge 2008-09-17 01:17:41
la source

Exceptions sont destinés à des événements qui sont des comportements anormaux, des erreurs, des échecs et des. Comportement fonctionnel, erreur de l'utilisateur, etc., devrait plutôt être gérée selon la logique du programme. Puisqu'un mauvais compte ou mot de passe est une partie attendue du flux logique dans une routine de connexion, il devrait être capable de gérer ces situations sans exceptions.

2
répondu Joe Skora 2008-09-17 02:02:53
la source

j'ai des problèmes philosophiques avec l'utilisation d'exceptions. Fondamentalement, vous vous attendez à ce qu'un scénario spécifique se produise, mais plutôt que de le traiter explicitement, vous poussez le problème à être traité "ailleurs."Et où "ailleurs", c'est peut être n'importe qui conjecture.

2
répondu Dan 2008-09-17 22:43:45
la source

je dirais que généralement tout fondamentalisme mène à l'enfer.

vous ne voudriez certainement pas finir avec le flux d'exception, mais éviter les exceptions tout à fait est également une mauvaise idée. Vous devez trouver un équilibre entre les deux approches. Ce que je ne ferais pas, c'est créer un type d'exception pour chaque situation exceptionnelle. Qui n'est pas productif.

ce que je préfère généralement est de créer deux types fondamentaux d'exceptions qui sont utilisées dans tout le système: LogicalException et TechnicalException . On peut les distinguer par des sous-Types au besoin, mais ce n'est généralement pas nécessaire.

l'exception technique dénote l'exception vraiment inattendue comme le serveur de base de données étant en panne, la connexion au service web jeté L'IOException et ainsi de suite.

d'autre part, les exceptions logiques sont utilisées pour propager la situation erronée moins grave aux couches supérieures (généralement un résultat de validation).

veuillez noter que même l'exception logique n'est pas destinée à être utilisée régulièrement pour contrôler le flux du programme, mais plutôt pour mettre en évidence la situation où le flux devrait réellement prendre fin. Lorsqu'il est utilisé en Java, les deux types d'exception sont RuntimeException sous-classes et la gestion des erreurs est fortement orientée vers l'aspect.

donc dans le login exemple il pourrait être sage de créer quelque chose comme "AuthenticationException" et de distinguer les situations concrètes par des valeurs enum comme UsernameNotExisting , PasswordMismatch etc. Alors vous ne finirez pas par avoir une énorme hiérarchie d'exception et pouvez garder les blocs de capture sur le niveau maintenable. Vous pouvez aussi facilement employer un mécanisme générique de manipulation d'exception puisque vous avez les exceptions catégorisées et savez assez bien ce qu'il faut propager jusqu'à l'utilisateur et comment.

notre usage habituel est de lancer la LogicalException pendant l'appel de Service Web lorsque l'entrée de l'utilisateur était invalide. L'Exception est regroupée dans le détail SOAPFault et est ensuite désactivée sur l'exception à nouveau sur le client, ce qui entraîne l'affichage de l'erreur de validation sur un certain champ d'entrée de page Web puisque l'exception a une correspondance correcte avec ce champ.

ce n'est certainement pas la seule situation: besoin de frapper le service web pour vomir l'exception. Vous êtes libre de le faire dans n'importe quelle situation exceptionnelle (comme dans le cas où vous devez échouer-rapide) - tout est à votre discrétion.

2
répondu Petr Macek 2011-09-30 05:44:05
la source

la raison principale pour éviter de lancer une exception est qu'il ya beaucoup de frais généraux impliqués avec lancer une exception.

Une chose que l'article ci-dessous est qu'une exception est une des conditions exceptionnelles et des erreurs.

un nom d'utilisateur erroné n'est pas nécessairement une erreur de programme mais une erreur d'utilisateur...

voici un bon point de départ pour les exceptions au sein de. Net: http://msdn.microsoft.com/en-us/library/ms229030 (VS.80).aspx

1
répondu Sam 2008-09-17 01:14:43
la source

exceptions de lancer provoque la pile à se détendre, ce qui a quelques impacts de performance (admitted, modern managed environments have improved on that). Encore à plusieurs reprises jeter et attraper des exceptions dans une situation emboîtée serait une mauvaise idée.

probablement plus important que cela, les exceptions sont destinées à des conditions exceptionnelles. Ils ne doivent pas être utilisés pour le flux de contrôle ordinaire, car cela nuira à la lisibilité de votre code.

1
répondu Arno 2008-09-17 01:21:14
la source

j'ai trois types de conditions que j'attrape.

  1. les entrées erronées ou manquantes ne devraient pas faire exception. Utilisez à la fois le côté client JS et le côté serveur regex pour détecter, définir les attributs et rediriger vers la même page avec des messages.

  2. The AppException. Il s'agit généralement d'une exception que vous détectez et jetez avec votre code. En d'autres termes ce sont ceux que vous attendez (le fichier n' exister.) Enregistrez-le, définissez le message et renvoyez-le à la page d'erreur générale. Cette page contient habituellement un peu d'information sur ce qui s'est passé.

  3. L'Exception inattendue. Ce sont ceux que vous ne connaissez pas. Enregistrez - le avec les détails et renvoyez-les à une page d'erreur générale.

Espérons que cette aide

1
répondu Michael 2008-09-17 01:54:36
la source

sécurité est confondu avec votre exemple: vous ne devriez pas dire à un attaquant qu'un nom d'utilisateur existe, mais le mot de passe est erroné. C'est une information supplémentaire que vous n'avez pas besoin de partager. Il suffit de dire "le nom d'utilisateur ou le mot de passe est incorrect."

1
répondu anon 2008-09-17 03:10:36
la source

la réponse simple est, chaque fois qu'une opération est impossible (en raison de l'une ou l'autre application ou parce qu'elle violerait la logique commerciale). Si une méthode est invoquée et qu'il est impossible de faire ce pour quoi la méthode a été écrite, jeter une Exception. Un bon exemple est que les constructeurs jettent toujours des ArgumentExceptions si une instance ne peut pas être créée en utilisant les paramètres fournis. Un autre exemple est L'InvalidOperationException, qui est lancée lorsqu'une opération ne peut pas être effectuée en raison de la état d'un autre membre ou des membres du groupe.

dans votre cas, si une méthode comme Login(nom d'utilisateur, mot de passe) est invoquée, si le nom d'utilisateur n'est pas valide, il est en effet correct de lancer un UserNameNotValidException, ou PasswordNotCorrectException Si mot de passe est incorrect. L'utilisateur ne peut pas être connecté en utilisant le(S) paramètre (s) fourni (s) (i.e. il est impossible parce qu'il violerait l'authentification), donc jeter une Exception. Bien que je puisse avoir vos deux Exceptions hériter de ArgumentException.

après avoir dit que, si vous ne souhaitez pas jeter une Exception parce qu'un échec de connexion peut être très commun, une stratégie est de créer à la place une méthode qui renvoie des types qui représentent des échecs différents. Voici un exemple:

{ // class
    ...

    public LoginResult Login(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            return new UserInvalidLoginResult(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            return new PasswordInvalidLoginResult(user, password);
        }
        else
        {
            return new SuccessfulLoginResult();
        }
    }

    ...
}

public abstract class LoginResult
{
    public readonly string Message;

    protected LoginResult(string message)
    {
        this.Message = message;
    }
}

public class SuccessfulLoginResult : LoginResult
{
    public SucccessfulLogin(string user)
        : base(string.Format("Login for user '{0}' was successful.", user))
    { }
}

public class UserInvalidLoginResult : LoginResult
{
    public UserInvalidLoginResult(string user)
        : base(string.Format("The username '{0}' is invalid.", user))
    { }
}

public class PasswordInvalidLoginResult : LoginResult
{
    public PasswordInvalidLoginResult(string password, string user)
        : base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
    { }
}

la plupart des développeurs apprennent à éviter les Exceptions en raison des frais généraux causés par leur lancer. Il est bon d'être conscient des ressources, mais habituellement pas aux dépens de votre conception de l'application. C'est probablement la raison pour laquelle on vous a dit de ne pas jeter vos deux Exceptions. Le fait d'utiliser ou non des Exceptions se résume habituellement à la fréquence à laquelle l'Exception se produit. Si c'est un résultat assez commun ou assez prévisible, c'est alors que la plupart des développeurs éviteront les Exceptions et créeront plutôt une autre méthode pour indiquer l'échec, en raison de la consommation supposée de ressources.

voici un exemple d'éviter d'utiliser des Exceptions dans un scénario comme vient de le décrire, en utilisant le motif Try ():

public class ValidatedLogin
{
    public readonly string User;
    public readonly string Password;

    public ValidatedLogin(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            throw new UserInvalidException(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            throw new PasswordInvalidException(password);
        }

        this.User = user;
        this.Password = password;
    }

    public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
    {
        if (IsInvalidUser(user) || 
            IsInvalidPassword(user, password))
        {
            return false;
        }

        validatedLogin = new ValidatedLogin(user, password);

        return true;
    }
}
1
répondu Chris 2008-09-17 09:24:54
la source

à mon avis, la question fondamentale devrait être de savoir si l'on s'attendrait à ce que l'appelant souhaite maintenir le flux d'émissions normal si une condition se produit. Si vous ne le savez pas, soit vous avez des méthodes doSomething et trySomething séparées, où la première renvoie une erreur et la seconde non, ou vous avez une routine qui accepte un paramètre pour indiquer si une exception doit être lancée si elle échoue). Considérez une classe pour envoyer des commandes à un système distant et rapporter des réponses. Certain les commandes (par exemple redémarrer) provoqueront l'envoi d'une réponse par le système distant, mais ne répondront pas pendant un certain temps. Il est donc utile de pouvoir envoyer une commande "ping" et de savoir si le système distant répond dans un délai raisonnable sans avoir à jeter une exception si ce n'est pas le cas (l'appelant s'attendrait probablement à ce que les premières tentatives de "ping" échouent, mais l'une d'elles pourrait éventuellement fonctionner). D'un autre côté, si on a une séquence de commandes comme:

  exchange_command("open tempfile");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("close tempfile");
  exchange_command("copy tempfile to realfile");

on voudrait l'échec de n'importe quelle opération d'avorter la séquence entière. Bien qu'on puisse vérifier chaque opération pour s'assurer qu'elle a réussi, il est plus utile d'avoir la routine exchange_command() jeter une exception si une commande échoue.

en fait, dans le scénario ci-dessus, il peut être utile d'avoir un paramètre pour sélectionner un certain nombre de modes de gestion des pannes: ne lancez jamais d'exceptions, lancez des exceptions pour les erreurs de communication seulement, ou lancez des exceptions dans n'importe quel les cas où une commande ne renvoie pas une indication de "succès".

1
répondu supercat 2010-06-24 20:45:18
la source

pour moi, une Exception doit être levée lorsque requis techniques ou des affaires d'échec de la règle. par exemple, si une entité de voiture est associée à une rangée de 4 pneus ... si un ou plusieurs pneus sont nuls ... une exception devrait être lancée "NotEnoughTiresException", car elle peut être capturée à différents niveaux du système et avoir une signification significative à travers la journalisation. en outre si nous essayons juste de contrôler le flux null et empêcher l'instanciation de la voiture . nous ne trouverons peut-être jamais la source le problème, c'est que le pneu n'est pas censé être nul .

1
répondu Genjuro 2011-10-06 19:32:51
la source

vous pouvez utiliser un peu d'exceptions génériques pour ces conditions. Pour par exemple ArgumentException est destiné à être utilisé lorsque quelque chose va mal avec les paramètres à une méthode (à l'exception de ArgumentNullException). Généralement, vous n'avez pas besoin d'exceptions comme LessThanZeroException, NotPrimeNumberException, etc. Penser à l'utilisateur de votre méthode. Le nombre de conditions qu'elle voudra traiter spécifiquement est égal au nombre du type d'exceptions que votre méthode doit lever. De cette façon, vous pouvez déterminer les exceptions détaillées que vous aurez.

par ailleurs, toujours essayer de fournir certains moyens pour les utilisateurs de vos bibliothèques pour éviter les exceptions. TryParse est un bon exemple, il existe de sorte que vous ne devez pas utiliser int.Analyse et attraper une exception. Dans votre cas, vous voudrez peut-être fournir quelques méthodes pour vérifier si le nom d'utilisateur est valide ou le mot de passe est correct de sorte que vos utilisateurs (ou vous) n'auront pas à faire beaucoup de traitement d'exception. Ce sera espérons qu'il en résultera un code plus lisible et de meilleures performances.

0
répondu Serhat Ozgel 2008-09-17 01:19:53
la source

en fin de compte, la décision revient à savoir s'il est plus utile de traiter les erreurs au niveau de l'application comme celle-ci en utilisant la gestion des exceptions, ou par le biais de votre propre mécanisme interne, comme les codes d'état de retour. Je ne pense pas qu'il y ait une règle stricte à propos de ce qui est mieux, mais je considérerais:

  • qui appelle votre code? Est-ce une API publique ou une bibliothèque interne?
  • Quelle langue utilisez-vous? Si c'est Java, par exemple, puis lancer une exception (cochée) place une charge explicite sur votre interlocuteur pour gérer cette condition d'erreur d'une manière ou d'une autre, par opposition à un État de retour qui pourrait être ignoré. Qui pourrait être bon ou mauvais.
  • comment les autres conditions d'erreur dans la même application sont-elles traitées? Les appelants ne voudront pas traiter avec un module qui traite les erreurs d'une manière idiosyncrasique, contrairement à tout autre chose dans le système.
  • combien de choses peuvent aller mal avec le la routine en question, et comment seraient-ils traités différemment? Considérez la différence entre une série de blocs de capture qui traitent des erreurs différentes et un interrupteur sur un code d'erreur.
  • avez-vous des renseignements structurés sur l'erreur que vous devez retourner? Lancer une exception vous donne un meilleur endroit pour mettre cette information que de simplement retourner un statut.
0
répondu eli 2008-09-17 01:26:25
la source

il y a deux classes principales d'exceptions:

1) exception relative au système (par exemple perte de la connexion à la base de données) ou 2) exception de L'utilisateur. (par exemple, la validation des entrées de L'utilisateur, 'mot de passe est incorrect')

j'ai trouvé utile de créer ma propre classe D'Exception D'Utilisateur et quand je veux jeter une erreur d'utilisateur je veux être traitée différemment (c.-à-d. l'erreur de ressource affichée à l'utilisateur) alors tout ce que je dois faire dans mon handler d'erreur principale est de vérifier le type d'objet:

            If TypeName(ex) = "UserException" Then
               Display(ex.message)
            Else
               DisplayError("An unexpected error has occured, contact your help  desk")                   
               LogError(ex)
            End If
0
répondu Crusty 2008-09-17 05:28:33
la source

Quelques choses à penser au moment de décider si une exception est le cas:

  1. quel niveau de code vous voulez avoir exécuté après que le candidat d'exception se produit - c'est-à-dire, combien de couches de la pile d'appels devrait se détendre. Vous voulez généralement gérer une exception aussi près que possible de l'endroit où elle se produit. Pour la validation nom d'utilisateur / mot de passe, vous devriez normalement traiter les échecs dans le même bloc de code, plutôt que de laisser un bulle exception. Une exception n'est donc probablement pas appropriée. (OTOH, après trois tentatives ratées de connexion, le flux de contrôle peut changer ailleurs, et une exception peut être appropriée ici.)

  2. est-ce que cet événement est quelque chose que vous voudriez voir dans un journal d'erreurs? Toutes les exceptions ne sont pas écrites dans un journal d'erreurs, mais il est utile de demander si cette entrée dans un journal d'erreurs serait utile - c'est-à-dire que vous essayeriez de faire quelque chose à ce sujet, ou serait la poubelle vous ignorer.

0
répondu Mike Kantor 2008-09-17 06:10:20
la source

"PasswordNotCorrectException" n'est pas un bon exemple pour l'utilisation d'exceptions. Il faut s'attendre à ce que les utilisateurs obtiennent leurs mots de passe incorrects, ce N'est donc pas une exception IMHO. Vous vous en remettez probablement, montrant un message d'erreur agréable, donc c'est juste un contrôle de validité.

les exceptions sans entrave vont finalement arrêter l'exécution - ce qui est bien. Si vous retournez des codes false, null ou error, vous devrez gérer l'état du programme tout seul. Si vous oubliez pour vérifier les conditions quelque part, votre programme peut continuer à fonctionner avec des données erronées, et vous pouvez avoir du mal à comprendre ce que est arrivé et .

bien sûr, vous pourriez causer le même problème avec des déclarations de captures vides, mais au moins les repérer est plus facile et ne nécessite pas que vous comprenez la logique.

comme règle empirique:

Utiliser où vous ne voulez pas ou tout simplement ne peut pas récupérer d'une erreur.

0
répondu DanMan 2011-12-10 15:53:34
la source

Autres questions sur exception language-agnostic