Assertions Java sous-utilisées

Je me demande pourquoi le mot-clé assert est tellement sous-utilisé en Java? Je ne les ai presque jamais vus utilisés, mais je pense qu’ils sont une excellente idée. Je préfère 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"); } 

Mon soupçon est 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 / habitude de programmation Java
  • Ils sont désactivés à l’exécution par défaut, POURQUOI OH POURQUOI?

    les assertions sont, en théorie, destinées à tester les invariants , des hypothèses qui doivent être vraies pour que le code se termine correctement.

    L’exemple illustré teste une entrée valide, ce qui n’est pas une utilisation 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 y a une surcharge et on suppose que les situations où les invariants échouent ont été détectées comme des erreurs de codage lors du développement et des tests.

    Votre remarque à propos de leur arrivée en Java est également une raison pour laquelle ils ne sont pas plus largement vus.

    En outre, les frameworks de tests unitaires permettent d’exiger que les assertions programmatiques soient externes au code testé.

    C’est un abus d’assertions de les utiliser pour tester les entrées de l’utilisateur. IllegalArgumentException est plus correct de lancer une IllegalArgumentException sur une entrée non valide car cela permet à la méthode appelante d’attraper l’exception, d’afficher l’erreur et de faire ce qu’elle doit (demander à nouveau une entrée, quitter, etc.).

    Si cette méthode est une méthode privée dans l’une de vos classes, l’assertion est correcte car vous essayez juste de vous assurer que vous ne lui transmettez pas accidentellement un argument null. Vous testez avec des assertions et lorsque vous avez testé tous les chemins d’access 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 qu’ils doivent suivre certaines conditions préalables et assert à la fin avec une post-condition que la méthode doit être utilisée. Ils peuvent être tout aussi utiles que les commentaires. moreo, car avec des assertions sur, ils testent réellement ce qu’ils documentent.

    Les assertions sont destinées au test / débogage, et non à la vérification des erreurs, raison pour laquelle elles sont désactivées par défaut: décourager les utilisateurs d’utiliser des assertions pour valider les entrées de l’utilisateur.

    De la programmation avec des assertions

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

    Cela signifie que si vous ne contrôlez pas totalement l’environnement d’exécution, vous ne pouvez pas garantir que le code d’assertion sera 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 des assertions désactivées ( valeur par défaut ), tout votre code de gestion des erreurs disparaît.

    Dans “Effective Java”, Joshua Bloch a suggéré (dans la rubrique “Vérifier les parameters de validité”) que (comme une règle simple à adopter), pour les méthodes publiques, nous validerons les arguments et lancerons les exceptions nécessaires pour les méthodes non publiques (qui ne sont pas exposées et vous, en tant qu’utilisateur, vous devez vous assurer de leur validité), nous pouvons utiliser l’assertion à la place.

    yc

    @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 inscrit (c’est-à-dire émet le bytecode pour if (!expr) throw Ex plutôt que ce bytecode assert idiot).

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

     Note: %n assertions inlined. 

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

    Je ne sais pas pourquoi vous vous donneriez la peine d’écrire des assertions puis de les remplacer par une norme si, ensuite, une déclaration de condition, pourquoi ne pas simplement écrire les conditions sous la forme ifs en premier lieu?

    Les assertions sont uniquement destinées aux tests et ont deux effets secondaires: des binarys plus gros et des performances dégradées une fois activées (c’est pourquoi vous pouvez les désactiver!)

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

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

    En outre, vous ne pouvez rechercher aucune assertion dans un IDE que j’ai vu jusqu’à présent, mais chaque IDE peut rechercher des invocations de méthode.

    Les assertions sont utiles car elles:

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

    Considérez-les comme une auto-validation du code. S’ils échouent, cela signifie que votre programme est cassé et doit s’arrêter. Toujours les allumer pendant les tests unitaires!

    Dans The Pragmatic Programmer, ils recommandent même de les laisser tourner en production.

    Laisser les assertions activées

    Utilisez des assertions pour prévenir l’impossible.

    Notez que les assertions lancent AssertionError si elles échouent. Elles ne sont donc pas interceptées par une exception catch.

    En fait, ils sont arrivés à 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). peut être fait), il est plus facile (je veux dire qu’il nécessite moins d’effort) d’utiliser si et des exceptions (ou pire de ne rien utiliser).

    Comme d’autres l’ont déclaré: les assertions ne sont pas appropriées pour valider les entrées des utilisateurs.

    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 contrôles en utilisant très peu de code, et cela 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