web-dev-qa-db-fra.com

Assertions Java sous-utilisées

Je me demande pourquoi le mot clé assert est si peu utilisé en Java? Je ne les ai presque jamais vues utilisées, mais je pense qu'elles sont une bonne idée. Je préfère certainement beaucoup la brièveté de:

assert param != null : "Param cannot be null";

à la verbosité de:

if (param == null) {
    throw new IllegalArgumentException("Param cannot be null");
}

Je soupçonne qu'ils sont sous-utilisés parce que

  • Ils sont arrivés relativement tard (Java 1.4), date à laquelle beaucoup de gens avaient déjà établi leur style de programmation Java.
  • Ils sont désactivés à l'exécution par défaut, POURQUOI OH POURQUOI ??
64
Dónal

(assertions) sont, en théorie, destinés à tester les invariants , supposons que doit être vrai pour que le code se termine correctement. 

L'exemple présenté teste une entrée valide, ce qui n'est pas un usage typique pour une assertion, car elle est généralement fournie par l'utilisateur.

Les assertions ne sont généralement pas utilisées dans le code de production car il existe une surcharge et il est supposé que les situations où les invariants échouent ont été interceptées comme des erreurs de codage lors du développement et des tests.

Votre remarque sur leur arrivée «tardive» en Java est également une raison pour laquelle ils ne sont pas plus vus.

De plus, les frameworks de tests unitaires permettent de répondre en partie au besoin d'assertions programmatiques externes au code testé.

62
Ken Gentle

C'est un abus d'assertions que de les utiliser pour tester les entrées de l'utilisateur. Lancer une IllegalArgumentException sur une entrée invalide est plus correct, car cela permet à la méthode appelante d'attraper l'exception, d'afficher l'erreur et de faire tout ce qui est nécessaire (demander à nouveau l'entrée, quitter, peu importe).

Si cette méthode est une méthode privée dans l'une de vos classes, l'assertion est correcte, car vous essayez simplement de vous assurer que vous ne lui passez pas accidentellement un argument nul. Vous testez avec des assertions activées et, une fois que vous avez testé tous les chemins d'accès et que vous n'avez pas déclenché l'assertion, vous pouvez les désactiver pour ne pas gaspiller de ressources. Ils sont également utiles comme commentaires. Une assert au début d'une méthode est une bonne documentation pour les responsables de la maintenance qu'ils doivent suivre certaines conditions préalables, et une assert à la fin avec des documents de post-condition indiquant ce que la méthode devrait faire. Ils peuvent être aussi utiles que des commentaires. moreso, car avec des affirmations, ils testent réellement ce qu’ils documentent.

Les assertions sont destinées à tester/déboguer, et non à vérifier les erreurs, raison pour laquelle elles sont désactivées par défaut: décourager les personnes d'utiliser des assertions pour valider les entrées de l'utilisateur.

56
Adam Jaskiewicz

From Programmer avec des assertions

Par défaut, les assertions sont désactivées au moment de l'exécution. Deux commutateurs de ligne de commande vous permettent d'activer ou de désactiver de manière sélective les assertions.

Cela signifie que si vous n'avez pas un contrôle total sur l'environnement d'exécution, vous ne pouvez pas garantir que le code d'assertion sera même appelé. Les assertions sont destinées à être utilisées dans un environnement de test, pas pour le code de production. Vous ne pouvez pas remplacer la gestion des exceptions par des assertions, car si l'utilisateur exécute votre application avec les assertions désactivées ( default ), tout votre code de gestion des erreurs disparaît.

19
Bill the Lizard

Dans "Effective Java", Joshua Bloch a suggéré (dans la rubrique "Vérification de la validité des paramètres") que (en quelque sorte comme une règle simple à adopter), pour les méthodes publiques, nous validerons les arguments et lancerons l'exception nécessaire si elle est invalide, et pour les méthodes non publiques (qui ne sont pas exposées et vous, en tant qu'utilisateur, devez en assurer la validité), nous pouvons utiliser l'assertion à la place.

yc

18
yclian

@ Don, vous êtes frustré que l'assertion soit désactivée par défaut. J'étais aussi, et j'ai donc écrit ce petit plugin javac qui les met en ligne (c.-à-d. Qu'il émet le bytecode pour if (!expr) throw Ex plutôt que ce bytecode d'assertion stupide.

Si vous incluez fa.jar dans votre chemin de classe lors de la compilation du code Java, il fera sa magie puis dira

Note: %n assertions inlined.

@see http://smallwiki.unibe.ch/adriankuhn/javacompiler/forceassertions et alternativement sur github https://github.com/akuhn/javac

9
akuhn

Les assertions sont utiles car elles:

  • attraper les erreurs de programmation tôt
  • document code utilisant le code

Considérez-les comme une auto-validation du code. S'ils échouent, cela signifie que votre programme est en panne et doit cesser. Allumez-les toujours pendant les tests unitaires!

Dans Le programmeur pragmatique ils recommandent même de les laisser fonctionner en production.

Laisser les assertions allumées

Utilisez des assertions pour empêcher l'impossible.

Notez que les assertions émettent AssertionError si elles échouent, elles ne sont donc pas interceptées par catch Exception.

2
Christophe Roussy

Je ne suis pas sûr de savoir pourquoi vous vous donneriez la peine d'écrire des assertions, puis de les remplacer par une instruction conditionnelle if si standard, pourquoi ne pas simplement écrire les conditions comme si elles étaient en premier lieu?

Les assertions sont uniquement destinées aux tests et ont deux effets secondaires: des fichiers binaires plus volumineux et des performances dégradées lorsqu'ils sont activés (c'est pourquoi vous pouvez les désactiver!)

Les assertions ne doivent pas être utilisées pour valider des conditions, car cela signifie que le comportement de votre application est différent au moment de l'exécution, lorsque les assertions sont activées/désactivées - ce qui est un cauchemar!

2
Nimbus

Les assertions sont très limitées: vous ne pouvez tester que des conditions booléennes et vous devez écrire le code pour un message d'erreur utile à chaque fois. Comparez ceci à la fonction assertEquals () de JUnit, qui permet de générer un message d'erreur utile à partir des entrées et même d'afficher les deux entrées côte à côte dans le IDE d'un coureur JUnit.

En outre, vous ne pouvez pas rechercher d'assertions dans les IDE que j'ai vus jusqu'à présent, mais chaque IDE peut rechercher des invocations de méthode.

1
Aaron Digulla

Comme d'autres l'ont dit: les assertions ne sont pas appropriées pour valider les entrées de l'utilisateur.

Si vous êtes préoccupé par la verbosité, je vous recommande de consulter une bibliothèque que j'ai écrite: https://bitbucket.org/cowwoc/requirements/ . Cela vous permettra d'exprimer ces vérifications en utilisant très peu de code, et générera même le message d'erreur en votre nom:

requireThat("name", value).isNotNull();

et si vous insistez pour utiliser des assertions, vous pouvez le faire aussi:

assertThat("name", value).isNotNull();

La sortie ressemblera à ceci:

Java.lang.NullPointerException: name may not be null
0
Gili

En fait, ils sont arrivés en Java 1.4

Je pense que le principal problème est que, lorsque vous codez dans un environnement où vous ne gérez pas directement les options jvm, comme dans les serveurs Eclipse ou J2EE (dans les deux cas, il est possible de modifier les options jvm, mais vous devez effectuer une recherche approfondie pour trouver où elles se trouvent. peut être fait), il est plus facile (je veux dire, cela demande moins d’efforts) d’utiliser si et des exceptions (ou pire, de ne rien utiliser).

0
Denis R.