Utilisation morbide des constantes

Pourquoi devrais-je écrire (comme dit mon collègue):

import static org.apache.commons.lang.math.NumberUtils.INTEGER_ONE; if (myIntVariable == INTEGER_ONE) { ... } 

au lieu de:

 if (myIntVariable == 1) { ... } 

?

Je sais que l’utilisation de constantes est recommandée mais je pense que la valeur de NumberUtils.INTEGER_ONE ne changera jamais! Alors j’écris 1 .

Tu ne devrais pas. Le nom INTEGER_ONE n’a pas plus de sens que 1. Si toutefois cette valeur a une autre signification (par exemple, mois dans l’année), l’utilisation d’une constante (comme Calendar.FEBRUARY ) rendra votre code plus clair.

Je peux deviner que cette constante dans la bibliothèque Commons Math a été créée en Java 1.4 quand il n’y avait pas de cache Integer et de mise en boîte automatique, il était donc logique de pouvoir réutiliser le même object Integer à différents endroits pour économiser de la mémoire. Donc, il a été ajouté pour des raisons de performance, pas pour la clarté du code. Maintenant, c’est obsolète: même si vous avez besoin d’un object Integer , vous pouvez utiliser Integer.valueOf(1) ou la mise en cache automatique implicite et obtenir celle qui est mise en cache.

Vous ne devriez pas écrire INTEGER_ONE ! Vous ne devriez pas non plus écrire 1 (voir exception ci-dessous)!

Pourquoi? Un littéral comme 1 s’appelle un nombre magique . Les nombres magiques sont des “valeurs uniques avec une signification inexpliquée ou des occurrences multiples qui pourraient (de préférence) être remplacées par des constantes nommées” (explication de la même page Wikipedia).

Donc, ce qui devrait normalement être fait est de faire de ces nombres magiques des constantes dont le nom représente ou explique la signification de ce nombre. La constante INTEGER_ONE n’explique pas la signification.

Donc, ce que vous devez faire est de trouver la signification de la valeur dans ce contexte et de créer une constante avec exactement ce nom. Si le 1 représente le nombre maximum de threads autorisés par exemple, vous devriez avoir une constante comme:

 static final int MAX_NUMBER_OF_THREADS = 1; 

EDIT selon le commentaire de Tagir

Si le littéral lui-même a une signification dans le domaine pour lequel vous écrivez le code, il ne doit pas être remplacé par une constante nommée. L’exemple de Tagir pour calculer l’élément inverse est bon:

 double invert(double x) { return 1/x; } 

Ici, le littéral 1 a une signification dans ce contexte dans le domaine mathématique. Donc, il peut être utilisé tel quel.

Je viens d’écrire des directives de style pour mon entreprise et je suggère ce qui suit:

N’utilisez pas de valeurs “magiques” codées en dur. Si une valeur est constante, définissez-la comme telle. Des nombres tels que -1, 0, 1, 2, 100 peuvent être utilisés dans certaines situations.

Mes exemples sont en Objective-C car c’est le langage pour lequel j’écrivais des lignes direcsortingces, mais les règles s’appliquent toujours.

Bonne utilisation

 static NSSsortingng* const DatabaseName = @"database.name"; //Acceptable use of "2" float x = (ScreenWidth / 2) - (ImageWidth / 2); //Acceptable use of 0 for (int i = 0; i < NumberOfItems; i++) //Acceptable use of 100, but only because the variable is called "percentage" float percentage = (someObjects * 100) / allObjects.count; 

Mauvaise utilisation

 float x = (480 / 2) - (120 / 2); //We have to guess these are sizes? //Unneccessary constants. for (int i = ZERO; i < NumberOfItems; i += ONE) float percentage = (someObjects.count * 100) / 120; //What is 120? 

org.apache.commons.lang.math.NumberUtils.INTEGER_ONE il vous donne un object final static Integer plutôt que primitif int 1, et comme il est final static il agit comme une constante et peut être utilisé en comparaison d’objects Integer car sera toujours retourne la même instance.

Donc, dans le scénario ci-dessus, cela pourrait ne pas sembler approprié, mais quelque part si vous l’utilisez en comparaison, cela a certainement un impact.

De plus, autant que possible, nous devrions préférer l’utilisation de constantes sur du code dur, car:

  1. Cela peut faciliter la maintenance de votre code. Si une situation se produit à l’avenir pour un changement, vous ne pouvez changer qu’à un seul endroit.
  2. Le code est plus propre et plus lisible.

Vous savez peut-être si cela ne changera jamais, mais je ne le ferai pas si je commence à éditer votre code …

En gros, c’est un moyen de documenter votre code dans votre code actuel . La raison d’utiliser des constantes et des exemples comme celui-ci est d’éviter les numéros de magie dans le code et leurs inconvénients.

Cela étant dit, vous pouvez l’utiliser à un point tel qu’il n’est plus avantageux et que l’encombrement induit. J’ai tendance à le faire pour des choses qui sont utilisées plus d’une fois ou qui ont été modifiées par moi ou par quelqu’un d’autre… ou en termes plus simples, des valeurs importantes .

De Class NumberUtils, vous verrez qu’il est défini comme suit:

 /** Reusable Integer constant for one. */ public static final Integer INTEGER_ONE = new Integer(1) 

Donc, vous verrez que INTEGER_ONE n’est pas la même chose que 1. C’est un object qui a déjà été construit pour vous. Donc, si nous avons besoin d’une instance de Integer(1) , plutôt que de créer la vôtre, vous pouvez réutiliser celle de la bibliothèque en économisant du temps et de la mémoire.

Cela dépend vraiment de votre application, si vous en avez vraiment la version int de 1, vous seriez probablement mieux d’utiliser cette classe plutôt que cette classe Integer .

Imaginez que vous avez ceci

 if (myIntVariable == 1) { ... } 

Mais quelques milliers de fois …

Et soudain, il faut être un 2.

Qu’est-ce qu’il est plus facile de changer?

EDIT: Avant de voter, répondez du sharepoint vue des avantages de ne pas utiliser de nombres magiques, je ne suis pas du tout (je pensais que c’était inférable, venez sur les gens) conseillant de changer la constante de la bibliothèque