Je viens de découvrir un code charmant dans notre application d'entreprise qui utilise des blocs Try-Catch comme opérateurs logiques.
Ce qui signifie "faire du code, si cela génère cette erreur, le fait, mais si cela jette cette erreur, faites cette 3ème chose à la place".
Il utilise "Finally" comme déclaration "else", il apparaît.
Je sais que cela est faux en soi, mais avant d’aller me battre, j’espérais avoir des arguments bien pensés.
Et hé, si vous avez des arguments POUR l’utilisation de Try-Catch de cette manière, veuillez le dire.
Pour tous ceux qui se demandent, le langage utilisé est le C # et le code en question, une trentaine de lignes et cherche des exceptions spécifiques. Il ne gère pas TOUTES les exceptions.
error-handling
programming-logic
James P. Wright
la source
la source
try
'd. Tous les cas exceptionnels qui justifient une exception en général ne doivent pas nécessairement être fatals dans ce cas particulier. Alors, pourriez-vous le faire d'une manière plus simple, plus uniforme ou plus robuste sans utiliser d'exceptions?Réponses:
La gestion des exceptions a tendance à être un moyen coûteux de gérer le contrôle de flux (certainement pour C # et Java).
Le moteur d'exécution fait beaucoup de travail lorsqu'un objet d'exception est construit - rassembler la trace de la pile, déterminer où l'exception est gérée et plus encore.
Tout cela coûte en mémoire et en ressources CPU qu'il n'est pas nécessaire d'étendre si des instructions de contrôle de flux sont utilisées pour le contrôle de flux.
De plus, il y a un problème sémantique. Les exceptions concernent des situations exceptionnelles et non un contrôle de flux normal. Vous devez utiliser la gestion des exceptions pour gérer des situations imprévues / exceptionnelles, et non comme un flux de programme normal, car sinon, une exception non capturée vous en dira beaucoup moins.
En dehors de ces deux-là, il y a le problème des autres lecteurs du code. L'utilisation d'exceptions de cette manière n'est pas ce à quoi la plupart des programmeurs s'attendent. Par conséquent, la lisibilité et la compréhensibilité de votre code en pâtissent. Quand on voit "Exception", on se dit que quelque chose de mauvais est arrivé, quelque chose qui n’est pas censé se produire normalement. L'utilisation d'exceptions de cette manière est donc source de confusion.
la source
Comment sais-tu ça? J'ai abandonné toute cette sorte de "connaissance" et je crois maintenant que le code le plus simple est le meilleur. Supposons que vous souhaitiez convertir une chaîne en un élément facultatif qui est vide si l'analyse échoue. Il n'y a rien de mal avec:
Je suis complètement en désaccord avec l'interprétation habituelle de "Les exceptions sont des conditions exceptionnelles". Lorsqu'une fonction ne peut pas retourner une valeur utilisable ou qu'une méthode ne peut pas répondre à ses post-conditions, lève une exception. Peu importe la fréquence à laquelle ces exceptions sont levées jusqu'à ce qu'il y ait un problème de performances démontré.
Les exceptions simplifient le code en permettant de séparer le traitement des erreurs du flux normal. Il suffit d'écrire le code le plus simple possible, et s'il est plus facile d'utiliser try-catch ou de lever une exception, faites-le.
Les exceptions simplifient les tests en réduisant le nombre de chemins dans le code. Une fonction sans branche complétera ou lèvera une exception. Une fonction avec plusieurs
if
instructions pour vérifier les codes d'erreur a plusieurs chemins possibles. Il est très facile de se tromper ou d’oublier complètement l’une des conditions, de façon à ignorer une condition d’erreur.la source
int i; if(long.TryParse(s, out i)) return i; else return null;
. TryParse renvoie false si la chaîne n'a pas pu être analysée. S'il peut être analysé, il définit l'argument de sortie sur les résultats de l'analyse et renvoie true. Aucune exception ne se produit (même en interne dans TryParse) et en particulier aucune exception d'un type qui signifie une erreur de programmation, comme l'indiqueFormatException
toujours .NETs .Le travail de débogage et de maintenance est très difficile lorsque le flux de contrôle est effectué à l'aide d'exceptions.
De manière inhérente, les exceptions sont conçues pour être un mécanisme permettant de modifier le flux de contrôle normal de votre programme - d’exécuter des activités inhabituelles, entraînant des effets secondaires inhabituels, comme moyen de sortir d’une situation particulièrement difficile qui ne peut être gérée avec moins de complication. veux dire. Les exceptions sont exceptionnelles. Cela signifie que, selon l'environnement dans lequel vous travaillez, l'utilisation d'une exception pour un flux de contrôle régulier peut entraîner:
Inefficacité Les obstacles supplémentaires que l'environnement doit franchir pour effectuer en toute sécurité les changements de contexte relativement difficiles nécessaires pour les exceptions nécessitent de l'instrumentation et des ressources.
Problèmes de débogage Parfois utiles (lors de la tentative de débogage d'un programme), des informations sont projetées par la fenêtre lorsque des exceptions se produisent. Vous pouvez perdre la trace de l’état ou de l’historique du programme pour comprendre le comportement au moment de l’exécution
Problèmes de maintenance Le flux d'exécution est difficile à suivre lors de sauts d'exception. Au-delà de cela, une exception peut être levée à l'intérieur d'un code de type boîte noire, qui peut ne pas se comporter de manière simple à comprendre lors du lancement d'une exception.
Mauvaises décisions en matière de conception Les programmes ainsi conçus encouragent un état d'esprit qui, dans la plupart des cas, ne permet pas facilement de résoudre les problèmes avec élégance. La complexité du programme final décourage le programmeur de comprendre pleinement son exécution et encourage la prise de décisions conduisant à des améliorations à court terme avec des coûts élevés à long terme.
la source
J'ai vu ce modèle utilisé plusieurs fois.
Il y a 2 problèmes majeurs:
goto
. Les sauts sont considérés comme nuisibles pour un certain nombre de raisons. Ils devraient être utilisés si toutes les alternatives présentent des inconvénients considérables. En fait, dans tout mon code, je ne me souviens que de 2 cas, où les sauts étaient clairement la meilleure solution.la source
Parfois, les exceptions sont les plus rapides. J'ai vu des cas où les exceptions d'objet nul étaient plus rapides, même en Java, que l'utilisation de structures de contrôle (je ne peux pas citer l'étude pour le moment, vous devrez donc me faire confiance). Le problème survient lorsque Java doit prendre le temps nécessaire et renseigner la trace de pile d'une classe d'exceptions personnalisée au lieu d'utiliser des classes natives (qui semblent être au moins partiellement mises en cache). Avant de dire que quelque chose est unilatéralement plus rapide ou plus lent, il serait bon de procéder à une analyse comparative.
En Python, non seulement il est plus rapide, mais il est beaucoup plus correct de faire quelque chose qui pourrait provoquer une exception puis de gérer l'erreur. Oui, vous pouvez appliquer un système de types, mais cela va à l’encontre de la philosophie du langage; vous devriez simplement essayer d’appeler la méthode et d’attraper le résultat! (Tester si un fichier est accessible en écriture est similaire - essayez simplement d’écrire et attrapez l’erreur).
J'ai vu des moments où il est plus rapide de faire quelque chose de stupide, comme des tables de requête qui n'existaient pas, plutôt que de déterminer si une table existe en PHP + MySQL (la question de savoir où je compare cette question est en fait ma seule réponse acceptée avec des votes négatifs). .
Cela dit, le recours aux exceptions devrait être limité pour plusieurs raisons:
try...catch
adhérents au flux de contrôle (généralement d'après mon expérience) ne suivent pas la philosophie "minimiser le code dans les blocs bloqués".else if
bloquer. Assez dit (et si quelqu'un contres avec un "Mais ils pourraient utiliser différentes classes d'exceptions", ma réponse est "Allez dans votre chambre et ne sortez pas avant d'avoir pensé à ce que vous avez dit.")Exception
, pour le reste du monde (en tant qu’adhérents à latry...catch
philosophie du contrôle de flux), signifie que quelque chose est entré dans un état instable (bien que peut-être recouvrable). Les états instables sont MAUVAIS et cela devrait nous garder tous éveillés la nuit si nous avons réellement des exceptions évitables (ça me fait peur, pas de mensonges).try...catch
le contrôle des flux va à l’encontre de ce que l’on considère généralement comme les meilleures pratiques. Cela signifie que le débutant d'un projet prend plus de temps à apprendre le projet, ce qui signifie une augmentation du nombre d'heures de travail sans aucun gain.try{ obj.openSomething(); /*something which causes exception*/ obj.doStuff(); obj.closeSomething();}catch(Exception e){obj.closeSomething();}
. Dans unif...else
scénario plus traditionnel, ilcloseSomething()
est moins probable (encore une fois, une expérience personnelle) d'être un travail de copier-coller. (Certes, cet argument a plus à voir avec des personnes que j'ai rencontrées qu'avec la philosophie elle-même).la source
Mon principal argument est que l'utilisation de try / catch pour la logique interrompt le flux logique. Suivre la "logique" à travers des constructions non logiques est (pour moi) contre-intuitif et déroutant. Je suis habitué à lire ma logique comme "si la condition est alors A d'autre B". Lire la même déclaration que "Essayer une capture puis exécuter B" est étrange. Il serait même plus étrange que l'instruction
A
soit une simple affectation, nécessitant du code supplémentaire pour forcer une exception si ellecondition
est fausse (et cela nécessiterait probablement deif
toute façon une instruction-).la source
Eh bien, juste une question d’étiquette, avant de "commencer une dispute avec eux", comme vous le dites, je voudrais demander: "Pourquoi utilisent-ils la gestion des exceptions dans tous ces endroits différents?"
Je veux dire, il y a plusieurs possibilités:
... Je pense que tout cela est également probable. Alors, demandez-leur gentiment.
la source
Try Catch ne doit être utilisé que pour la gestion des exceptions. Plus encore, gestion des exceptions spécifiques. Votre prise d'essai ne devrait capturer que les exceptions attendues, sinon elle n'est pas bien formée. Si vous devez utiliser une attrape tout essayer attraper, alors vous faites probablement quelque chose de mal.
MODIFIER:
Raison: vous pouvez dire que si vous utilisez try catch en tant qu'opérateur conditionnel, comment allez-vous comptabiliser les exceptions REAL?
la source
catch
clause différente de celle qui vise les exceptions "non réelles"?Les exceptions sont pour quand chose exceptionnelle se produire. Le programme fonctionne-t-il selon un flux de travail régulier exceptionnel?
la source
Raison d'utiliser des exceptions:
Raisons pour ne pas utiliser d'exceptions:
À la fin:
L'objectif est d'écrire du code qui communique ce qui se passe. Les exceptions peuvent aider / entraver cela en fonction de ce que fait le code. Un try / catch en python pour une KeyError sur une référence de dictionnaire est parfaitement (tant que vous connaissez la langue) try / catch pour le même KeyError à cinq couches de fonction est dangereux.
la source
J'utilise try-> catch comme contrôle de flux dans certaines situations. Si votre logique principale dépend de quelque chose qui échoue, mais que vous ne voulez pas simplement lancer une exception et quitter ... C'est à quoi sert un bloc try-> catch. J'écris beaucoup de scripts unix côté serveur non surveillés, et il est bien plus important pour eux de ne pas échouer que pour qu'ils échouent joliment.
Alors essayez Plan A, et si Plan A meurt, attrapez et exécutez avec Plan B ... Et si Plan B échoue, utilisez enfin pour lancer Plan C, qui corrigera l’un des services défaillants dans A ou B, ou page moi.
la source
Cela dépend de la langue et peut-être de la mise en œuvre utilisée. La norme en C ++ est que les exceptions doivent être sauvegardées pour des événements vraiment exceptionnels. En revanche, en Python, l’un des principes est " Il est plus facile de demander pardon que pour obtenir une permission ", de sorte que l’intégration des blocs try / except dans la logique du programme est encouragée.
la source
C'est une mauvaise habitude, mais je le fais de temps en temps en python. Comme au lieu de vérifier pour voir si un fichier existe, je viens d'essayer de le supprimer. Si cela jette une exception, j'attrape et passe juste en sachant que ce n'était pas là. <== (pas nécessairement vrai si un autre utilisateur est propriétaire du fichier, mais que je le fais dans le répertoire de base de l'utilisateur, cela ne devrait donc pas se produire).
Pourtant, trop utilisé, c'est une mauvaise pratique.
la source
J'aime la façon dont Apple le définit : les exceptions ne concernent que les erreurs de programmation et les erreurs d'exécution fatales. Sinon, utilisez des codes d'erreur. Cela m'aide à décider quand l'utiliser, pensant à moi-même: "Est-ce une erreur de programmation?"
la source
Cela ressemble à utiliser la gestion des exceptions pour construire la logique goto au dessus d'un langage qui n'a pas de commande goto.
Pour les nombreuses raisons pour lesquelles la logique goto est mauvaise, vous pouvez vous référer à cette question: https://stackoverflow.com/questions/46586/goto-still-considered-harmful
la source