Utiliser des «exceptions de capture» pour améliorer la lisibilité, bon ou mauvais?


9

Dans la section Quand utiliser l'exception dans The Pragmatic Programmer , le livre écrit qu'au lieu de:

retcode = OK;
     if (socket.read(name) != OK) {
      retcode = BAD_READ;
    }
     else {
      processName(name);
       if (socket.read(address) != OK) {
        retcode = BAD_READ;
      }
       else {
        processAddress(address);
         if (socket.read(telNo) != OK) {
          retcode = BAD_READ;
        }
         else {
          //  etc, etc...
        }
      }
    }
     return retcode;

, ils préfèrent:

 retcode = OK;
     try {
      socket.read(name);
      process(name);
      socket.read(address);
      processAddress(address);
      socket.read(telNo);
      //  etc, etc...
    }
     catch (IOException e) {
      retcode = BAD_READ;
      Logger.log( "Error reading individual: " + e.getMessage());
    }
     return retcode;

tout simplement parce qu'il a l'air plus soigné. Je suis tout pour le code plus propre, est cependant pas inutile saisie d' une exception d' un goulot d'étranglement?

Je peux comprendre que nous devrions abandonner l'optimisation minuscule pour le code plus propre (au moins 99% du temps), mais d'après ce que je sais, les exceptions de capture appartiennent à la classe de code qui a un retard notable dans l'exécution. Par conséquent, je me demandais quelle est la justification que le deuxième morceau de code est préféré au premier code?

Ou plutôt, quel code préférez-vous?


migré de la révision de code parce que c'est une question de bonnes pratiques et non une question de révision de code
Winston Ewert

1
IMO, si vous vous attendez à pouvoir lire ces valeurs à partir du socket, un IOEx est exceptionnel.
Steven Evers


Avez-vous mesuré?

@ ThorbjørnRavnAndersen bien sûr, je lisais le livre et je n'ai pas de véritable "cas de test" à mesurer .. mais si nous le mesurons dans un code artificiel, alors il y a évidemment une pénalité de performance
Pacerier

Réponses:


18

Les exceptions ne sont généralement plus lentes que si elles sont effectivement levées. Habituellement, les exceptions dans des situations comme celle-ci sont rares, donc ce n'est pas quelque chose dont vous devriez vous inquiéter. Vous ne devez vraiment vous soucier des performances des exceptions que si elles se produisent tout le temps et sont donc un facteur important.

Le deuxième code est meilleur car il est beaucoup plus facile de suivre la logique. La gestion des erreurs est bien localisée. La seule objection est que si vous utilisez des exceptions, utilisez des exceptions. N'attrapez pas les exceptions, puis retournez un code d'erreur.


4
D'accord, je déteste voir les codes d'erreur dans une langue qui a des exceptions. La plupart du temps, vous devez attraper, enregistrer, relancer sans casser la pile d'appels. Et la plupart du temps, peu importe si un cas "d'exception" est plus lent. L'application a un problème, prenez le temps de le gérer correctement. Tant que l'exception est exceptionnelle et ne fait pas partie du fonctionnement normal ou du chemin heureux de l'application, ce n'est généralement pas une odeur de code.
CaffGeek

En fait, je me demandais comment justifier l'exception EOF que DataStreams utilise pour détecter une fin de ligne (la fin de ligne n'est pas exceptionnelle est-ce) comme le montre docs.oracle.com/javase/tutorial/essential/io/datastreams.html ?
Pacerier

@Pacerier, ça pourrait être exceptionnel. Manquer d'entrée dans la ligne pourrait indiquer de mauvaises données ou quelque chose de mal. Je soupçonne que l'utilisation prévue est d'analyser plusieurs champs d'une ligne.
Winston Ewert

@Downvoter, si vous avez un problème avec la réponse, veuillez expliquer!
Winston Ewert

5

Eh bien, comme ils le disent aussi, les exceptions devraient traiter les cas exceptionnels , et comme il s'agit d'un cas exceptionnel (c'est-à-dire quelque chose qui se produit peu et loin entre les deux), je dirais que cela s'applique également ici.

De plus, je vous conseille contre les choses micro-optimisation de ce genre. Concentrez-vous davantage sur la lisibilité du code , car vous passerez beaucoup plus de temps à lire du code qu'à écrire un nouveau code.

Pour vraiment vous assurer qu'il s'agit d'un goulot d'étranglement des performances, effectuez un profilage, analysez et concentrez-vous sur les tâches les plus critiques basées sur cette analyse.


5

Je peux comprendre que nous devrions abandonner l'optimisation minuscule pour le code plus propre (au moins 99% du temps), mais d'après ce que je sais, les exceptions de capture appartiennent à la classe de code qui a un retard notable dans l'exécution.

D'où le savez-vous? Comment définissez-vous le "retard notable"?

C'est exactement le genre de mythe de la performance vague (et complètement faux) qui conduit à des optimisations prématurées inutiles.

Lancer et intercepter une exception peut être lent par rapport à l'ajout de deux nombres, mais c'est complètement insignifiant par rapport à la lecture de données à partir d'un socket. Vous pourriez probablement lever et intercepter mille exceptions en même temps que vous lisez un seul paquet réseau. Et nous ne parlons pas ici de milliers d'exceptions, seulement d'une seule.


Je viens de .NET donc pardonnez ma connaissance de Java, mais j'ai personnellement expérimenté des exceptions de capture dans .NET provoquant des retards insensés (magnitude de secondes) qui ont été corrigés en supprimant le "code d'exception de capture" ..
Pacerier

@Pacerier, sérieusement? magnitude de secondes? Je suppose que ça a peut-être attrapé beaucoup d'exceptions? Ensuite, j'ai pu voir ça.
Winston Ewert

3
@Pacerier: Si les exceptions entraînent des retards insensés, ce qui les cause n'est clairement pas exceptionnel, et doit donc être traité d'une autre manière. Aucun système ne devrait prendre quelques secondes pour traiter une exception, et je pense que Microsoft est suffisamment compétent pour éviter cela.
David Thornley

5

Je suis d'accord avec les réponses que vous avez déjà obtenues en disant qu'il s'agit d'un cas exceptionnel, il est donc raisonnable d'utiliser la gestion des exceptions.

Pour répondre plus directement à vos préoccupations en matière de performances, je pense que vous devez garder une idée de l'échelle des choses. Lancer / attraper une exception dans ces circonstances est susceptible de prendre un de l'ordre de la microseconde. Comme le contrôle de flux va, c'est lent - plusieurs fois plus lent que les ifinstructions normales , cela ne fait aucun doute.

Dans le même temps, gardez à l'esprit que ce que vous faites ici, c'est la lecture des données d'un réseau. À 10 mégabits par seconde (lent pour un réseau local, mais assez rapide pour les connexions Internet), c'est dans le même ordre que le temps de lire un octet d'informations.

Bien sûr, ces frais généraux ne sont encourus que lorsque vous lâchez également l'exception - lorsqu'il n'est pas levé, il y a généralement peu ou pas de frais généraux (du moins d'après ce que j'ai vu, le surdébit le plus significatif ne provient pas du gestion des exceptions elle-même, comme l'ajout de plus de flux de contrôle potentiels, ce qui rend le code plus difficile à optimiser pour le compilateur).

Dans ce cas, lorsqu'une exception est levée, vos données d'écriture dans le journal. Compte tenu de la nature de la journalisation, il est fort probable que vous vidiez cette sortie dès que vous l'écrivez (pour vous assurer qu'elle n'est pas perdue). L'écriture sur le disque est (encore une fois) une opération assez lente - vous avez besoin d'un SSD de classe entreprise assez rapide pour atteindre même des dizaines de milliers d'IOP / seconde. Un disque utilisé pour la journalisation peut facilement être limité à quelque chose comme des centaines d'IOP / seconde.

Conclusion: il existe des cas où la surcharge de traitement des exceptions peut être importante, mais ce n'est certainement pas l' un d'entre eux.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.