web-dev-qa-db-fra.com

Quand utiliser une assertion et quand utiliser une exception

La plupart du temps, je vais utiliser une exception pour rechercher une condition dans mon code. Je me demande quand il est temps d'utiliser une assertion?

Par exemple,

Group group=null;
try{
    group = service().getGroup("abc");
}catch(Exception e){
    //I dont log error because I know whenever error occur mean group not found
}

if(group !=null)
{
    //do something
}

Pouvez-vous indiquer comment une assertion s'inscrit ici? Devrais-je utiliser une affirmation?

Il semble que je n’utilise jamais d’assertions dans le code de production et que je ne les vois que dans les tests unitaires. Je sais que dans la plupart des cas, je peux simplement utiliser exception pour effectuer la vérification comme ci-dessus, mais je veux savoir comment procéder de manière "professionnelle".

106
cometta

Les assertions devraient être utilisées pour vérifier quelque chose qui ne devrait jamais arriver, alors qu'une exception devrait être utilisée pour vérifier quelque chose qui pourrait arriver. 

Par exemple, une fonction peut être divisée par 0; une exception doit donc être utilisée, mais une assertion peut être utilisée pour vérifier que le disque dur disparaît subitement. 

Une assertion arrêterait l'exécution du programme, mais une exception lui permettrait de continuer à s'exécuter.

Notez que if(group != null) n'est pas une assertion, c'est juste une condition.

78
Marius

Hors de propos (la liste est peut-être incomplète et trop longue pour tenir dans un commentaire), je dirais:

  • utiliser des exceptions lors de la vérification des paramètres transmis aux méthodes et aux constructeurs publics ou protégés
  • utiliser des exceptions lors de l'interaction avec l'utilisateur ou lorsque vous vous attendez à ce que le code client récupère une situation exceptionnelle
  • utiliser des exceptions pour résoudre les problèmes éventuels
  • utiliser des assertions lors de la vérification des conditions préalables, postérieures et invariantes du code privé/interne
  • utiliser des assertions pour fournir des commentaires à vous-même ou à votre équipe de développeurs
  • utilisez des assertions lorsque vous recherchez des événements très peu susceptibles de se produire, sinon cela signifie que votre application présente un défaut grave.
  • utilisez des assertions pour énoncer des choses que vous savez (supposément) être vraies

En d'autres termes, les exceptions traitent de la robustesse de votre application tandis que les assertions traitent de son exactitude.

Les assertions sont conçues pour être peu coûteuses à l’écriture, vous pouvez les utiliser presque partout et j’utilise cette règle: plus une assertion a l’air stupide, plus elle a de la valeur et plus elle contient d’informations. Lors du débogage d'un programme qui ne se comporte pas correctement, vous allez sûrement vérifier les possibilités d'échec les plus évidentes en fonction de votre expérience. Ensuite, vous vérifierez si des problèmes ne peuvent pas se produire: c'est à ce moment précis que les assertions aident beaucoup et permettent de gagner du temps.

159
Gregory Pakosz

Rappelez-vous que les assertions peuvent être désactivées au moment de l'exécution à l'aide de paramètres, et sont désactivées par défaut , aussi ne les comptez pas, sauf à des fins de débogage.

Aussi, vous devriez lire l’article Oracle sur assert pour voir plus de cas où utiliser - ou ne pas utiliser - assert.

25
chburd

En règle générale:

  • Utilisez des assertions pour les contrôles de cohérence internes là où cela n'a pas d'importance si quelqu'un les désactive. (Notez que la commande Java désactive toutes les assertions par défaut.)
  • Utilisez des tests réguliers pour tout type de vérification de ce qui ne devrait pas être désactivé. Ceci inclut / des contrôles défensifs qui protègent contre des dommages potentiels causés par des bogues, ainsi que toute donnée/demande de validation/quelque chose fourni par des utilisateurs ou des services externes.

Le code suivant de votre question est mauvais style et potentiellement buggy

try {
    group = service().getGroup("abc");
} catch (Exception e) {
    //i dont log error because i know whenever error occur mean group not found
}

Le problème est que vous ne savez PAS qu'une exception signifie que le groupe n'a pas été trouvé. Il est également possible que l'appel service() ait généré une exception ou qu'il ait renvoyé null, ce qui a ensuite provoqué une NullPointerException.

Lorsque vous attrapez une exception "prévue", vous devez attraper uniquement l'exception que vous attendez. En attrapant Java.lang.Exception (et en particulier en ne le connectant pas), vous compliquez le diagnostic/le débogage du problème et vous permettez éventuellement à l'application de causer plus de dégâts.

15
Stephen C

De retour chez Microsoft, la recommandation était de créer des exceptions dans toutes les API que vous rendez publiques et de vous servir des assertions dans toutes sortes d'hypothèses que vous formulez sur du code interne. C'est une définition un peu vague, mais je suppose que c'est à chaque développeur de tracer la ligne.

En ce qui concerne l'utilisation des exceptions, comme leur nom l'indique, leur utilisation doit être exceptionnelle. Ainsi, pour le code que vous présentez ci-dessus, l'appel getGroup doit renvoyer null s'il n'existe aucun service. Une exception ne devrait se produire que si un lien réseau tombe en panne ou quelque chose comme ça.

J'imagine que la conclusion est que l'équipe de développement a un peu laissé chaque application définir les limites d'assertion par rapport aux exceptions.

3
rui

Selon ce document http://docs.Oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general , "L’affirmation assert est appropriée pour les conditions préalables non publiques, Les vérifications de précondition publique doivent toujours être effectuées à l'aide de vérifications effectuées à l'intérieur de méthodes entraînant notamment des exceptions documentées, telles que IllegalArgumentException et IllegalStateException. "

Si vous voulez en savoir plus sur les conditions préalables, postconditionnelles et invariantes de classe, consultez cette documentation: http://docs.Oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions . Il contient également des exemples d'utilisation des assertions.

3
cesarsalgado

Tester Null ne détectera que les NULL, ce qui posera problème, alors qu’un catch/catch tel que vous le rencontrerez interceptera any error.

Globalement, essayer/intercepter est plus sûr, mais un peu plus lent, et vous devez faire attention à ne pas intercepter toutes les erreurs pouvant survenir. Donc, je dirais que utilisez try/catch - un jour, le code de getGroup pourrait changer, et vous pourriez avoir besoin de ce plus gros réseau.

1
Phil H

Vous pouvez utiliser cette simple différence d’esprit pendant leur utilisation. Les exceptions seront utilisées pour vérifier les erreurs attendues et inattendues appelées erreurs vérifiées et non vérifiées, tandis que l'assertion est principalement utilisée à des fins de débogage au moment de l'exécution pour voir si les hypothèses sont validées ou non. 

1
SBTec

Voir la section 6.1.2 (Assertions vs. autre code d'erreur) de la documentation de Sun au lien suivant. 

http://www.Oracle.com/technetwork/articles/javase/javapch06.pdf

Ce document donne le meilleur conseil que j'ai vu sur le moment d'utiliser des assertions. Citant le document:

"En règle générale, vous devez utiliser une assertion pour les cas exceptionnels que vous voudriez oublier. Une assertion est le moyen le plus rapide de traiter, et d'oublier, une condition traiter avec."

1
Phil

J'avoue que votre question me laisse un peu perplexe. Lorsqu'une condition d'assertion n'est pas remplie, une exception est levée. Confusément, cela s'appelle AssertionError . Notez qu'il est décoché, comme (par exemple) IllegalArgumentException , qui est levé dans des circonstances très similaires.

Donc, en utilisant des assertions en Java

  1. est un moyen plus concis d'écrire une condition/un bloc
  2. vous permet d'activer/désactiver ces contrôles via les paramètres de la machine virtuelle Java. Normalement, je laisse ces vérifications tout le temps, sauf si elles ont un impact sur les performances d'exécution ou sur une pénalité similaire.
1
Brian Agnew

Malheureusement, les assertions peuvent être désactivées. Lorsque vous êtes en production, vous avez besoin de toute l'aide dont vous avez besoin pour dépister quelque chose d'imprévu, affirme-t-il, se disqualifie. 

0