Java >> Tutoriel Java >  >> Java

Qu'est-ce qu'un nombre magique et comment y remédier ?

Les nombres magiques font partie de ces mauvaises pratiques en programmation qui portent un nom un peu bizarre. Après tout, les gens aiment généralement la magie, donc on ne sait pas ce qui est si mauvais chez eux. Heureusement, aujourd'hui, nous allons parler de ce qu'est un nombre magique et comment les supprimer de vos programmes.

Présentation des numéros magiques

Il y a de fortes chances que vous vous soyez trouvé ici parce qu'un bel outil d'analyse statique comme un linter vous a dit que votre code contient un nombre magique. Sans contexte, ce terme est assez bizarre. Après tout, rien dans la programmation n'est magique, bien que cela puisse parfois en avoir l'air, alors quel est le problème ?

En bref, un nombre magique est une valeur numérique (excluant généralement 0 et 1) qui a un objectif peu clair . Par exemple, nous pourrions calculer l'aire d'un cercle avec une approximation de pi comme suit :

def area_of_circle(radius: float) -> float:
  return 3.14 * radius * radius

Dans cet exemple, notre approximation de pi est ce qui serait considéré comme un nombre magique. C'est un problème car on ne sait pas exactement à quoi sert 3.14 dans notre calcul. En d'autres termes, il a apparemment engendré à partir de rien.

Certes, beaucoup de gens connaissent la formule d'aire d'un cercle ou la valeur de pi, donc ils pourraient probablement le comprendre à partir du contexte. Cela dit, compte tenu de la capacité de notre cerveau à conserver les informations dans la mémoire à court terme, nous devrions vraiment essayer de laisser le moins possible à l'inférence.

Par conséquent, un nombre magique est considéré comme une mauvaise pratique car il rend le code plus difficile à raisonner. Par conséquent, nous devons trouver des moyens de les supprimer de notre code dans la mesure du possible.

Supprimer les numéros magiques du code

Dans notre exemple précédent, nous avions une méthode qui calculait l'aire d'un cercle à partir d'un certain rayon :

def area_of_circle(radius: float) -> float:
  return 3.14 * radius * radius

Le problème, comme nous l'avons déjà évoqué, est que 3,14 est un nombre magique. Pour se débarrasser du nombre magique, nous devons lui créer une constante :

PI = 3.14

def area_of_circle(radius: float) -> float:
  return PI * radius * radius

L'astuce consiste à prendre la valeur apparemment aléatoire et à lui donner un contexte en lui donnant un nom. Dans ce cas, nous avons stocké la valeur de 3,14 dans une constante nommée PI.

Avantages de l'élimination des nombres magiques

Étant donné la banalité des exemples de cet article, vous pourriez en conclure que traiter les nombres magiques est une perte de temps. Laissez-moi prendre un moment pour essayer de vous convaincre des avantages.

Tout d'abord, comme mentionné précédemment, l'un des principaux avantages de la suppression des nombres magiques de votre code est la lisibilité. Les nombres peuvent avoir plusieurs significations qui peuvent être éclaircies avec un simple nom. Cela vous fera gagner du temps à l'avenir lorsque vous devrez inévitablement donner un sens à votre propre code.

Deuxièmement, un autre avantage majeur de la suppression des nombres magiques est de suivre par inadvertance le principe Ne vous répétez pas (DRY). Selon ce principe, vous essayez de limiter la duplication de code (par exemple, en n'utilisant pas le même nombre magique plusieurs fois). Une bonne conséquence de suivre DRY est de créer un point de contrôle unique où un nombre magique peut être modifié selon les besoins. Par exemple, imaginez si nous avions à la fois une méthode d'aire de cercle et une méthode de circonférence de cercle :

def area_of_circle(radius: float) -> float:
  return 3.14 * radius * radius

def circumference_of_circle(radius: float) -> float:
  return 2 * 3.14 * radius

Si, pour une raison quelconque, nous décidions que nous voulions pi à quelques décimales supplémentaires, nous devions le mettre à jour deux fois, une fois pour chaque méthode. Alternativement, nous pourrions utiliser notre constante pour la mettre à jour une fois aux deux endroits :

PI = 3.14159

def area_of_circle(radius: float) -> float:
  return PI * radius * radius

def circumference_of_circle(radius: float) -> float:
  return 2 * PI * radius

Si aucun de ces avantages ne vous semble utile, je vous recommande de désactiver cet avertissement particulier sur votre linter. Ce que vous ne devez absolument pas faire est de trouver une solution de contournement créative. Par exemple, vous avez peut-être une liste dont vous connaissez les indices exacts du contenu :

cards = ["jack", "queen", "king", "ace"]
ace = cards[3]

Une chose que vous ne devriez pas faire est quelque chose comme ça :

cards = ["jack", "queen", "king", "ace"]
ace = cards[1 + 1 + 1]

Bien sûr, ajouter un trois fois la somme de trois, mais je dirais que cette solution est encore plus déroutante que d'utiliser directement le nombre magique. À moins que vous n'essayiez délibérément d'obscurcir votre code, cela va dans la mauvaise direction.

Le pouvoir des meilleures pratiques

Bien que les meilleures pratiques varient d'une langue à l'autre et d'une équipe à l'autre, elles sont généralement pour le plus grand bien. Dans ce cas, les nombres magiques font partie de ces avertissements qui suggèrent en fait des façons d'améliorer votre code.

Cela dit, je ne recommande pas de suivre les règles pour le plaisir de suivre les règles. Très peu de règles de développement de logiciels ont été étudiées de manière empirique, alors faites preuve de discernement et évitez de tomber dans le dogme.

Enfin, je sais que beaucoup de gens qui liront ceci seront mes étudiants Java, et je ne veux pas vous laisser traîner, alors voici comment vous supprimez un nombre magique en Java :

public static double AreaOfCircle(double radius) {
  // Create a local constant using the final keyword
  final double pi = 3.14;  
  return pi * radius * radius;
}

Ou alternativement :

// Create a global constant using the final keyword
private static final double PI = 3.14; 

public static double AreaOfCircle(double radius) {
  return PI * radius * radius;
}

Cela dit, c'est tout ce que j'ai pour nous aujourd'hui. Si vous avez trouvé cet article utile, j'apprécierais que vous le partagiez. De même, vous pouvez trouver d'autres moyens de soutenir The Renegade Coder ici.

Si vous cherchez plus à lire, ne cherchez pas plus loin que la liste suivante :

  • Pouvez-vous réellement renvoyer plusieurs valeurs à partir d'une fonction en Python ?
  • Comment s'améliorer en programmation :leçons tirées des blogs
  • Comprendre la théorie des nombres derrière le chiffrement RSA

Sinon, merci d'être passé ! À la prochaine.


Balise Java