C'est un sujet quelque peu controversé, et je suppose qu'il y a autant d'opinions que de programmeurs. Mais pour le plaisir, je veux savoir quelles sont les pratiques courantes en entreprise (ou dans vos lieux de travail).
Sur mon lieu de travail, nous avons des directives de codage strictes. Une section est consacrée aux chaînes / nombres magiques. Il indique (pour C #):
N'utilisez pas de valeurs littérales, numériques ou chaînes, dans votre code autrement que pour définir des constantes symboliques. Utilisez le modèle suivant pour définir les constantes:
public class Whatever { public static readonly Color PapayaWhip = new Color(0xFFEFD5); public const int MaxNumberOfWheels = 18; }
Il existe des exceptions: les valeurs 0, 1 et null peuvent presque toujours être utilisées en toute sécurité. Très souvent, les valeurs 2 et -1 sont également correctes. Les chaînes destinées à la journalisation ou au traçage sont exemptées de cette règle. Les littéraux sont autorisés lorsque leur signification est claire par rapport au contexte et non sujets à de futurs changements.
mean = (a + b) / 2; // okay
WaitMilliseconds(waitTimeInSeconds * 1000); // clear enough
Une situation idéale serait un document de recherche officiel montrant les effets sur la lisibilité / maintenabilité du code lorsque:
- Les nombres / cordes magiques sont partout
- Les chaînes / nombres magiques sont remplacés par des déclarations constantes raisonnablement (ou à différents degrés de couverture) - et s'il vous plaît ne me criez pas pour utiliser "raisonnablement", je sais que tout le monde a une idée différente de ce qui est "raisonnablement"
- Les chaînes / nombres magiques sont remplacés en excès et dans des endroits où ils ne devraient pas être (voir mon exemple ci-dessous)
Je voudrais le faire pour avoir des arguments scientifiquement fondés lorsque je me dispute avec un de mes collègues, qui va au point de déclarer des constantes comme:
private const char SemiColon = ';';
private const char Space = ' ';
private const int NumberTen = 10;
Un autre exemple serait (et celui-ci est en JavaScript):
var someNumericDisplay = new NumericDisplay("#Div_ID_Here");
Collez-vous les ID DOM au-dessus de votre fichier javascript si cet ID n'est utilisé qu'à un seul endroit?
J'ai lu les rubriques suivantes:
StackExchange
StackOverflow
Bytes IT Community
Il y a beaucoup plus d'articles, et après avoir lu ces quelques modèles émergent.
Donc, ma question est d'utiliser les chaînes et les nombres magiques dans notre code? Je recherche spécifiquement des réponses d'experts qui sont appuyées par des références si possible.
la source
NumberTen = 10
C'est inutile car le chiffre 10 ne sera pas redéfini.MaxRetryCount = 10
Cela a un point a, nous pouvons vouloir changer le nombre maximal de nouvelles tentatives.private const char SemiColon = ';';
Stupide.private const char LineTerminator = ';'
; Intelligent.Réponses:
L'argument que vous devez faire valoir avec votre collègue ne concerne pas le fait de nommer un espace littéral,
Space
mais son mauvais choix de nom pour ses constantes.Supposons que le travail de votre code consiste à analyser un flux d'enregistrements qui contiennent des champs séparés par des points-virgules (
a;b;c
) et sont eux-mêmes séparés par des espaces (a;b;c d;e;f
). Si la personne qui a rédigé votre spécification vous appelle dans un mois et vous dit: "nous nous sommes trompés, les champs des enregistrements sont séparés par des symboles de tuyau (a|b|c d|e|f
)", que faites-vous?Dans le cadre de la valeur en tant que nom que préfère votre collègue, vous devez modifier la valeur de literal (
SemiColon = '|'
) et vivre avec du code qui continue à être utiliséSemiColon
pour quelque chose qui n'est plus vraiment un point-virgule. Cela conduira à des commentaires négatifs dans les revues de code . Pour réduire cela, vous pouvez changer le nom du littéral enPipeSymbol
et parcourir et changer chaque occurrence deSemiColon
enPipeSymbol
. À ce rythme, vous pourriez tout aussi bien utiliser un point-virgule littéral (';'
) en premier lieu, car vous devrez évaluer chaque utilisation individuellement et vous apporterez le même nombre de modifications.Identifiants pour les constantes doivent être descriptif de ce que la valeur ne , pas ce que la valeur est , et c'est où votre collègue a fait un virage à gauche dans les mauvaises herbes. Dans l'application de séparation de champs décrite ci-dessus, le point-virgule a pour fonction de séparer les champs et les constantes doivent être nommées en conséquence:
De cette façon, lorsque le séparateur de champs change, vous modifiez exactement une ligne de code, la déclaration de la constante. Quelqu'un qui regarde le changement ne verra qu'une seule ligne et comprendra immédiatement que le séparateur de champ est passé d'un point-virgule à un symbole de tuyau. Le reste du code, qui n'a pas eu besoin de changer car il utilisait une constante, reste le même, et le lecteur n'a pas à le fouiller pour voir ce qui lui a été fait d'autre.
la source
#define one 1 #define two 2
etc (ou l'équivalent dans le UK Post Office Coral, alors la langue de choix). Le mot est venu d'en haut qu'à l'avenir le champ de longueur serait le nombre d'octets, pas de segments, donc évidemment le code a été changé en#define one 8 #define two 16
etc;
à|
.public static final String MY_KEY_NAME = "MyKeyName"
CSV_RECORD_SEPARATOR
,TSV_RECORD_SEPARATOR
etc.).Définir le point-virgule comme une constante est redondant, car le point - virgule est déjà constant par lui-même . Cela ne changera jamais.
Ce n'est pas comme si un jour quelqu'un annoncerait "changement de terminologie, + c'est le nouveau point-virgule maintenant", et votre collègue se précipitera avec plaisir juste pour mettre à jour la constante (ils se sont moqués de moi - regardez-les maintenant).
Il y a aussi une question de cohérence. Je garantis que sa
NumberTen
constante ne sera pas utilisée par tout le monde (la plupart des codeurs ne sont pas fous), donc cela ne servira pas à quoi que ce soit qu'on attendait de toute façon. Lorsque l'apocalypse arrive et que "dix" est globalement redimensionné à 9, la mise à jour de la constante ne fera PAS l'affaire, car elle vous laissera toujours un tas de littéraux10
dans votre code, donc maintenant le système devient totalement imprévisible même dans la portée d'une hypothèse révolutionnaire que "dix" signifie "9".Le stockage de tous les paramètres en tant que consts est quelque chose que j'aurais aussi une seconde réflexion. Il ne faut pas faire cela à la légère.
Quels exemples de ce type d'utilisation avons-nous rassemblés jusqu'à présent? Terminateur de ligne ... nombre maximal de nouvelles tentatives ... nombre maximal de roues ... sommes-nous sûrs qu'elles ne changeront jamais?
Le coût est que la modification des paramètres par défaut nécessite la recompilation d'une application, et dans certains cas, même ses dépendances (car les valeurs de const numériques peuvent être codées en dur lors de la compilation).
Il y a aussi l'aspect test et moquerie. Vous avez défini la chaîne de connexion comme une constante, mais maintenant oups, vous ne pouvez pas simuler l'accès à la base de données (établir une fausse connexion) dans votre test unitaire.
la source
’
(guillemet simple gauche, Unicode 8217 ) pour les applications compatibles avec l'affichage d'un glyphe différent pour la marque recourbée. Étant donné que l'Europe utilise des virgules comme les Américains utilisent les points comme point décimal, je me trouve un peu hésitant à déclarer "pas ... jamais".DecimalPoint
constante - mais pasComma
ou desPeriod
constantes. C'est toute une différence: le premier dénote une fonction , un rôle ou un but de la valeur. "Point-virgule" ou "virgule" ne relèvent pas de cette catégorie.Votre collègue vise donc une entrée WTF quotidienne. Ces définitions sont stupides et redondantes. Cependant, comme cela a été souligné par d'autres, les définitions suivantes ne seraient ni idiotes ni redondantes:
Les nombres et les chaînes «magiques» sont des constantes qui ont une signification au-delà de leur valeur littérale immédiate. Si la constante
10
a une signification au-delà de "dix choses" (par exemple, comme un code pour une opération spécifique ou une condition d'erreur), c'est alors qu'elle devient "magique" et doit être remplacée par une constante symbolique qui décrit cette signification abstraite.Au-delà de la description claire de l'intention, les constantes symboliques vous épargnent également quelques maux de tête lorsque vous orthographiez mal un littéral. Une simple transposition de "CVS" à "CSV" en une seule ligne de code a traversé les tests unitaires et l'AQ et a été mise en production, où elle a provoqué l'échec d'une opération particulière. Oui, évidemment, les tests unitaires et d'AQ étaient incomplets et c'est son propre problème, mais l'utilisation d'une constante symbolique aurait évité ce peu de brûlures d'estomac.
la source
Il ne devrait y avoir rien de controversé à ce sujet. Il ne s'agit pas de savoir si les nombres magiques doivent être utilisés ou non, il s'agit d'avoir un code lisible.
Considérez la différence entre:
if(request.StatusCode == 1)
etif(request.HasSucceeded)
. Dans ce cas, je dirais que ce dernier est beaucoup plus lisible, mais cela ne signifie pas que vous ne pouvez jamais avoir de code commeint MaxNumberOfWheels = 18
.PS: C'est pourquoi je déteste absolument les directives de codage. Les développeurs doivent être suffisamment matures pour être capables de porter des jugements comme celui-ci; ils ne devraient pas le laisser à un morceau de texte formé par Dieu sait qui.
la source