web-dev-qa-db-fra.com

Faire valoir une bonne pratique ou non?

Est-ce une bonne pratique d'utiliser Assert pour les paramètres de fonction pour renforcer leur validité. Je parcourais le code source de Spring Framework et j'ai remarqué qu'ils utilisent Assert.notNull beaucoup. Voici un exemple

   public static ParsedSql parseSqlStatement(String sql) {
    Assert.notNull(sql, "SQL must not be null");}

En voici un autre:

public NamedParameterJdbcTemplate(DataSource dataSource) {
            Assert.notNull(dataSource,
                    "The [dataSource] argument cannot be null.");
            this .classicJdbcTemplate = new JdbcTemplate(dataSource);
        }

        public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) {
            Assert.notNull(classicJdbcTemplate,
                    "JdbcTemplate must not be null");
            this .classicJdbcTemplate = classicJdbcTemplate;
      }

Pour info, le Assert.notNull (pas l'instruction assert) est défini dans une classe util comme suit:

public abstract class Assert { 
   public static void notNull(Object   object, String   message) {
      if (object == null) {
          throw new IllegalArgumentException  (message);
      }
   }
}
48
ken

En principe, assertions ne sont pas si différents de nombreux autres contrôles d'exécution.

Par exemple, Java borne-vérifie tous les accès au tableau au moment de l'exécution. Est-ce que cela ralentit un peu les choses? Oui. Est-ce bénéfique? Absolument! Dès qu'une violation hors limite se produit , une exception est levée et le programmeur est alerté de tout bogue possible! Le comportement dans d'autres systèmes où les accès aux baies ne sont pas vérifiés est BEAUCOUP PLUS IMPRÉVISIBLE! (souvent avec des conséquences désastreuses!).

Les assertions, que vous utilisiez la bibliothèque ou la prise en charge des langues, sont similaires dans leur esprit. Il y a des coûts de performance, mais ça en vaut vraiment la peine. En fait, les assertions sont encore plus précieuses car elles sont explicites et communiquent des concepts de niveau supérieur.

Utilisé correctement, le coût des performances peut être minimisé et la valeur, à la fois pour le client (qui détectera les violations de contrat le plus tôt possible) et pour les développeurs (car le contrat est auto-exécutoire et auto-documenté ), est maximisé.

Une autre façon de voir les choses est de considérer les assertions comme des "commentaires actifs". Il n'y a aucun argument que les commentaires sont utiles, mais ils sont PASSIFS; sur le plan informatique, ils ne font rien. En formulant certains concepts comme des assertions au lieu de commentaires, ils deviennent ACTIFS. Ils doivent en fait tenir au moment de l'exécution; les violations seront prises.


Voir aussi: les avantages de la programmation avec assertions

57
polygenelubricants

Ces assertions sont fournies par la bibliothèque et ne sont pas identiques au mot clé assert intégré.

Il y a une différence ici: asserts ne s'exécutent pas par défaut (ils doivent être activés avec le -ea), tandis que les assertions fournies par la classe Assert ne peuvent pas être désactivées.

À mon avis (pour ce que ça vaut), c'est une méthode aussi bonne que n'importe quelle autre pour valider les paramètres. Si vous aviez utilisé des assertions intégrées comme l'indique le titre de la question, je l'aurais argumenté en partant du principe que les vérifications nécessaires ne devraient pas pouvoir être supprimées. Mais cette façon est juste un raccourci pour:

public static ParsedSql parseSqlStatement(String sql) {
    if (sql == null)
        throw new IllegalArgumentException("SQL must not be null");
    ...
}

... ce qui est toujours une bonne pratique à utiliser dans les méthodes publiques.

Le style intégré des assertions est plus utile pour les situations où une condition doit toujours être vraie, ou pour les méthodes privées. Le guide de langue introduisant des assertions a quelques bonnes directives qui sont fondamentalement ce que je viens de décrire.

28
Michael Myers

Oui, c'est une bonne pratique.

Dans le cas Spring, cela est particulièrement important car les vérifications valident les paramètres de propriété, etc. qui proviennent généralement des fichiers de câblage XML. En d'autres termes, ils valident la configuration de la webapp. Et si jamais vous effectuez un développement sérieux basé sur Spring, ces vérifications de validation vous feront économiser des heures de débogage lorsque vous faites une erreur de configuration idiote.

Mais notez qu'il y a une GRANDE différence entre une classe de bibliothèque appelée Assert et le mot clé Java assert qui est utilisé pour définir un Java assertion. Cette dernière forme d'assertions peut être désactivée au moment du lancement de l'application et ne doit PAS être utilisée pour les vérifications de validation des arguments que vous souhaitez toujours effectuer. De toute évidence, les concepteurs de Spring pensent que ce serait une très mauvaise idée de désactiver les vérifications de santé mentale de la configuration webapp ... et je suis d'accord.

[~ # ~] mise à jour [~ # ~]

Dans Java 7 (et versions ultérieures), le Java.util.Objects classe fournit une méthode de commodité requireNonNull pour tester si un argument est null et déclencher une exception. Vous l'utilisez comme ceci:

 SomeType t = ...
 SomeType tChecked = Objects.requireNonNull(t);

ou

 SomeType tChecked = Objects.requireNonNull(t, "t should be non-null");

Cependant, notez que cette méthode génère NullPointerException plutôt que IllegalArgumentException.

18
Stephen C

Sur la base des guide de Sun sur les assertions, vous ne devez pas utiliser les assertions pour la vérification des arguments dans les méthodes publiques.

La vérification des arguments fait généralement partie des spécifications publiées (ou du contrat) d'une méthode, et ces spécifications doivent être respectées, que les assertions soient activées ou désactivées.

6
kiwicptn

Dans les systèmes très grands et mal conçus/entretenus, si vous cherchez à améliorer la prévisibilité de méthodes qui sont, disons, de 6000 lignes et que personne dans l'entreprise ne les comprend plus, il peut être utile d'utiliser le mot clé assert pour provoquer des environnements de développement à exploser, révélant des bugs. Mais si vous implémentiez ces assertions en production, vous pourriez court-circuiter un correctif qui, bien qu'horriblement conçu, résolvait un problème. Vous voulez corriger ce mauvais patch en le découvrant dans l'environnement de développement, pas dans la production. Vous devez donc activer les assertions au moment du développement et les désactiver en production.

Une autre utilisation valide du mot clé assert au moment du développement consiste à insérer des vérifications de validité dans des algorithmes qui doivent s'exécuter en moins d'une milliseconde et qui sont suffisamment bien isolés des appelants imprévisibles ou non testés. Vous ne pourrez peut-être pas vous permettre de conserver le contrôle de validité en production dans un tel cas, bien qu'il soit toujours très utile en développement. D'un autre côté, si la source des paramètres que vous validez est imprévisible ou pourrait le devenir (si elle est déterminée en partie par l'entrée de l'utilisateur, par exemple), vous ne pourrez probablement jamais vous permettre d'ignorer la vérification, même en production, et devriez prendre la performance comme un coût pour faire des affaires. (Dans ce dernier cas, vous ne voudrez probablement pas utiliser une assertion.) Mais vous devriez opter pour des assertions pour éliminer un contrôle de validité au moment de la production niquement après que le profilage vous indique que vous ne pouvez tout simplement pas vous permettre les frais généraux.

2
nclark

Oui, c'est une bonne idée. Vous imposez la sous-traitance de l'interface ou de la classe. En cas de violation de contrat, vous souhaitez le détecter le plus rapidement possible. Plus vous attendez, plus les résultats peuvent être imprévisibles et plus il peut être difficile à diagnostiquer.

Lorsque vous vérifiez explicitement comme cela, vous devez également fournir un message d'information qui, lorsqu'il est affiché dans un fichier journal, peut fournir un contexte utile pour aider à trouver la cause racine ou même simplement pour réaliser que vous avez fait une hypothèse erronée sur ce qu'est le contrat.

1
cletus

Je garde mes assertions dans les binaires publiés mais avec un comportement modifié: abandon n'est pas appelé mais stacktrace est collecté.

Plus de détails ici: http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/

0
Dariusz Cieslak