7
votes

Confus sur quand jeter une exception

Je travaille sur une bibliothèque conçue pour communiquer (sur la communication série RS232) avec des périphériques externes. Je pensais que la stratégie de traitement des erreurs et des exceptions semblait être une méthode standard appropriée de l'industrie de signaler des erreurs.

J'ai donc lu peu de directives sur les exceptions. Un stipule assez clairement que je devrais pas Vous inquiétez de la performance HIT:

N'utilisez pas de codes d'erreur en raison de préoccupations que des exceptions pourraient affecter les performances négativement.

Autre m'a dit de ne pas jeter Exception dans les cas normaux:

n'utilisez pas d'exceptions pour des erreurs normales ou attendues, ou pour un flux de contrôle normal.

Je ne suis pas capable de dessiner une ligne claire entre les cas normaux / attendus et autres. Par exemple, dans ma bibliothèque, une opération peut échouer car:

  1. Il n'y a pas de réponse de l'appareil. (Pas de câble connecté, périphérique non activé, mauvais débit en bauds)
  2. La demande d'opération est rejetée par périphérique car elle ne pouvait pas authentifier la demande.
  3. la communication a échoué entre les deux. (Quelqu'un a trébuché sur le câble, le dispositif était éteint soudainement).

    Je peux penser à tout ce qui précède comme des problèmes attendus, car ils peuvent se produire très souvent dans la pratique (en infactuellement, de nombreux meurtres marketing m'appellent pour résoudre le problème ^ dans mon logiciel uniquement pour ne pas connaître le câble à leur ordinateur portable). Donc, peut-être que des exceptions ne devraient pas être jetées car sinon un programmeur d'application devra les attraper à de nombreux endroits (beaucoup de blocs de capture ne sont pas aussi agréables que je pense).

    D'autre part, j'ai aussi tendance à penser que ce sont toutes des erreurs que je dois faire une manière en quelque sorte faire rapport au programmeur d'application, et une exception semble être la meilleure façon de le faire. Si je n'utilise pas d'exceptions, je devrai signaler ces problèmes en utilisant un code d'erreur ou une erreur enums. (Ugly, je sais).

    Quelle approche pensez-vous que je devrais prendre?


0 commentaires

9 Réponses :


1
votes

Avec RS232, sauf si vous avez activé la main de main du matériel (et la plupart du temps, les gens ne le voient pas. Il n'y a aucun moyen pour vous de dire si un appareil est même connecté, autre que le fait que rien n'est envoyé au PC.

Je classerais 1 et 3 ensemble en tant que RS232TimeTorRor et 2 en tant que RS232AuthentiollingError, probablement.

En règle générale, un TimeOtorRor indique que le périphérique distant est enfermé ou n'est tout simplement pas connecté. Une erreur d'authentification est une sorte de ProtocolError, mais subtilement différente de la communication, mais le périphérique distant "vient de dire non" de créer une connexion avec le PC.

Je pense que les paramètres d'exception sont bien justifiés: vous ne vous attendriez jamais à une erreur de délai d'attente pendant les opérations normales, ni d'une erreur d'authentification.


3 commentaires

La bibliothèque est destinée à être utilisée pour la communication avec de nombreux appareils (32 appareils à la fois) et il doit être aussi rapide que possible car il sera utilisé dans l'environnement de production. Pensez-vous que soulever l'exception trop souvent affectera la performance?


Si cela doit être aussi rapide au point où jeter des exceptions est un problème, vous devez écrire la bibliothèque en C. Si vous soulevez une exception de délai d'attente, vous ne revenez plus immédiatement au matériel et voyez une autre exception - Vous ignorez cet appareil jusqu'à ce que vous soyez explicitement dit de y retourner.


@Hemant: retournez la question. Si les erreurs se produisent tout le temps, pensez-vous que cela affectera la performance? Vous attendez-vous souvent des erreurs? La performance sera-t-elle touchée par l'utilisation d'une exception étant-elle comparée à celle de la performance impliquée dans la récupération de l'erreur au niveau suivant d'abstraction?



5
votes

Vous développez une bibliothèque , un composant qui sera utilisé par d'autres applications.

Par conséquent, dans les cas prévus que vous mentionnez, j'utiliserais certainement des exceptions pour communiquer à l'application appelante que quelque chose ne va pas. Vous devez définir une exception personnalisée pour chacun de ces scénarios, puis documenter clairement quand ils peuvent se produire.

Ceci permet ensuite au code du client de l'application de prendre la décision de la meilleure façon de procéder. Seule la demande du client peut effectuer cette décision et des exceptions clairement documentées l'aident considérablement.

La meilleure chose à propos d'une exception personnalisée est que vous pouvez fournir plusieurs données de données significatives / utiles relatives au problème / exception. Ces données sont également bien encapsulées dans un seul objet. Comparez ceci aux codes d'erreur et retournez des valeurs.

La performance peut être un problème, mais uniquement lorsque l'exception est lancée dans une boucle serrée ou une autre situation d'activité élevée. Pour éviter cela, vous pouvez également appliquer un motif utilisé par le .NET Framework, nommément fournir des méthodes .... () (p. Ex. Tryparse () ) qui retourne booléen indiquant si une action a réussi ou échoué.

de toute façon, j'irais avec des exceptions personnalisées initialement, puis effectuez des tests de performance pour voir en réalité que certaines parties de la bibliothèque peuvent nécessiter une optimisation.


1 commentaires

En ce qui concerne la performance, je n'ai vu qu'une seule fois lorsque la performance est entrée en place et qu'il y avait littéralement des centaines d'exceptions étant jetées et restonnées à l'arrière. Nous avions une opération qui pourrait être faite de deux manières, une fois parfois travaillée mais jeté une exception quand elle ne l'a pas fait, et l'inverse de la manière dont la voie est requise. Nous avons décidé que la voie de réflexion devrait être une baisse si nous ne pouvons pas le faire sans réflexion. Les exceptions ont été levées de manière aussi souvent que c'était beaucoup plus rapide d'utiliser toujours la méthode de réflexion (la différence était l'utilisateur qui attend 10 secondes contre des fractions de seconde).



1
votes

si vous lancez ou non une exception est une conséquence du type de la fonction.

  • Si la fonction renvoie un X et que vous échouez de déterminer un X valide, lancez une exception.
  • Si la fonction est une action (par exemple, Connect) et vous ne remplissez pas l'action, lancez une exception.
  • Si la fonction est de la variété tryx, ne jetez pas une exception.

    Je suppose que je dis que vous devriez pousser le problème de "Dois-je jeter une exception?" à "Quelles méthodes les gens appelleront ma bibliothèque?" Avec la mise en garde que les exceptions que vous lancez devraient être évidentes en fonction des méthodes que vous fournissez.


0 commentaires

3
votes

J'utiliserais des exceptions, dans l'approche suivante (inspirée par le design-by-contrat)

  • Si possible, fournissez booléen Fonctions d'inspection vous disant Si une opération peut être en sécurité appliqué
  • pour l'opération donnée, considérez une telle fonction d'inspection en tant que Précondition: si elle tient, le opération peut être effectuée en toute sécurité, sinon, vous jeter une exception.

    De cette manière, si l'utilisateur de l'API peut coder sa logique clé à l'aide de Structures IF-else.

    Si des situations inattendues surviennent (en raison de problèmes de synchronisation subtils, par exemple, une exception sera lancée: le développeur peut attraper cette exception et y faire face. MAIS NOTE: Cela ne doit pas nécessairement être à l'endroit où la méthode a été invoquée: elle peut être plus haute / plus tôt dans la pile d'appels, à un endroit central où toutes les exceptions étranges sont gérées

    J'ai fait des travaux sur l'analyse automatisée du code de manutention des erreurs dans des programmes C multimobiliers de C. Celles-ci étaient basées sur des normes de codage nécessitant une inspection manuelle et une propagation des codes d'erreur. Il s'avère que les développeurs n'aiment pas écrire ce code, ils l'oublient et ils en font facilement des erreurs. En fait, nous avons trouvé 2 écarts des normes de codage (2 défauts, on pourrait dire) pour 1000 lignes de code C.

    • Voir M. Bruntink, A. Van Dursen, et T. TOURNÉS. D Isecture des défauts dans Manipulation des exceptions à base d'idiome . Dans les procédures du 28ème Conférence internationale sur les logiciels Ingénierie (ICSE'06), Pages 242-251, ACM Press, 2006.

      Résumé: (1) J'utiliserais des inspecteurs booléens (2) des exceptions peuvent être attrapées à des endroits plus élevés dans la pile d'appels; (3) s'appuyer sur des codes d'erreur est dangereux dans la pratique.


1 commentaires

Conception par contrat pour la victoire!



1
votes

Ne pas utiliser des exceptions pour la normale ou erreurs attendues, ou pour un flux normal de Contrôle.

Dans vos implémentations de méthode, évitez de provoquer une exception à dessein afin de modifier le flux d'exécution, de gérer une logique spéciale, des cas spéciaux ou des erreurs normales ou attendues. Par exemple, la manipulation des exceptions doit être supprimée dans la fonction suivante. (Il gère des erreurs normales ou attendues, mais comme la note dit que Convert.Tostring ne va pas vraiment échouer.) Il y a une performance mineure touchée en raison du temps nécessaire pour «configurer» la manipulation des exceptions dans la méthode. Ce n'est pas un coup important, mais si vous appelez cette fonction dans une boucle, cela peut devenir important. Si cette méthode est dans une bibliothèque, laissez toute exception à la bulle à l'utilisateur de la bibliothèque. (Les exceptions personnalisées sont différentes, voir la réponse de Ash.) xxx

Voici une mise en œuvre "meilleure" de la méthode: xxx < / blockquote>


0 commentaires

1
votes

Ne pas utiliser les codes d'erreur à cause de préoccupations que les exceptions peuvent affecter performance négativement.

Évitez de concevoir tout comme une fonction qui retourne véritable / faux avec les paramètres "Out" pour éviter les préoccupations de performance "imaginées" avec l'utilisation d'exceptions.


0 commentaires

0
votes

Le choix ne doit pas être compris entre lancer une exception ou renvoyer un code d'erreur. Essayez de retourner un objet d'exception dans une condition exceptionnelle. Le succès de la performance ne consiste pas à créer une exception, mais à la jeter. L'appelant peut ensuite vérifier une valeur de retour «null». L'exception renvoyée pourrait être une fonction de fonction, ou l'un des paramètres "Out".


0 commentaires

2
votes

Des exceptions ont été conçues pour exactement cela - des circonstances exceptionnelles. J'essaie d'y penser comme ça - si vous supposez que tout ce que vous dépendez de fonctionne comme normal pour la majorité du temps, et la méthode x échoue, c'est une circonstance exceptionnelle, car elle ne se produit normalement pas et vous devriez définir des exceptions attraper la situation.

Donc, dans votre situation, vous supposez que l'appareil soit opérationnel. Par conséquent, les circonstances exceptionnelles dans ce cas sont l'appareil n'acceptant pas une connexion, il rejetant une connexion, il n'accepte pas de données que vous l'envoyez ou que vous ne recevez pas de données, il devrait être envoyé, etc. Si vos périphériques sont systématiquement éteints plusieurs fois par jour, puis Vous vous attendez à ce qu'ils soient désactivés, utilisez donc des codes de retour ou un "Bool Isdeviceon ();" méthode pour vérifier avant de vous connecter.

Si c'est quelque chose que vous attendez-vous à ce que se produise dans des circonstances normales, telles que l'interrogation d'un périphérique pour ses capacités, mais celui que vous souhaitez n'est pas disponible, puis utilisez les codes de retour ou une méthode de retour - par exemple "Bool Dudevicehavethiscapabilité ();" Ne pas attraper une exception quand ce n'est pas le cas.

Un autre exemple (pour les applications GUI) est la saisie de l'utilisateur. N'utilisez pas d'exceptions pour cela, car vous vous attendez à ce que un utilisateur entrait quelque chose de mal, nous ne sommes pas parfaits.

J'ai connu des problèmes de performances massives dues à utiliser des exceptions quand ils n'étaient pas des circonstances vraiment exceptionnelles. Un exemple était lorsque je traiterais un fichier de données 2 Go 2-3 fois par jour. Certaines lignes avaient des prix valides dans le format 0.00. Certains n'ont pas. J'ai utilisé une formatException pour attraper ceux qui ne l'ont pas.

Deux ans plus tard, lorsque j'ai eu la chance d'obtenir un analyseur de performance, cette ligne qui a attrapé l'exception était responsable de 80% du temps utilisé pour analyser le fichier. J'ai changé cela pour utiliser la méthode Tryparse () de l'INT et obtenu une augmentation de vitesse massive.

Pour vos exemples, j'utiliserais probablement:

  1. Aucune réponse de l'appareil - Exception Si les périphériques doivent être sur 24/7, le code retour si systématiquement éteint
  2. Opération non autorisée - Exception
  3. Comms a échoué - Exception

1 commentaires

J'ai fini par faire à peu près exactement comme vous l'avez suggéré. Merci.



0
votes

Si une méthode ne parvient pas à effectuer sa fonction première de manière à ce qu'un appelant soit prêt à traiter, la fonction doit généralement indiquer une telle défaillance via une valeur de retour (ou, rarement, par écrit à une variable qui est adoptée par référence) . Si une fonction échoue de manière à ce qu'un appelant ne soit probablement pas prêt à traiter, il vaut mieux organiser une exception. Si certains appelants seraient prêts à faire face à une défaillance et que d'autres appelants ne veulent pas, il est préférable d'utiliser le motif Essayer / faire. Essentiellement, on fournit deux méthodes: dialogue et trydosomething. Dosomething se promet de réussir ou de lancer une exception. Trydosomething promet de ne pas jeter une exception à moins que quelque chose de vraiment inattendu se passe; Il indiquera les défaillances «attendues» par la valeur de retour.


0 commentaires