En tant que développeur de logiciel expérimenté, j'ai appris à éviter les chaînes magiques.
Mon problème est qu'il y a si longtemps que je ne les utilise pas, j'en ai oublié la plupart des raisons. En conséquence, j'ai du mal à expliquer pourquoi ils posent problème à mes collègues moins expérimentés.
Quelles sont les raisons objectives pour les éviter? Quels problèmes causent-ils?
anti-patterns
Kramii
la source
la source
Réponses:
Dans un langage qui compile, la valeur d'une chaîne magique n'est pas vérifiée lors de la compilation . Si la chaîne doit correspondre à un modèle particulier, vous devez exécuter le programme pour garantir qu'il correspond à ce modèle. Si vous avez utilisé quelque chose comme une énumération, la valeur est au moins valide au moment de la compilation, même s'il peut s'agir d'une valeur incorrecte.
Si une chaîne magique est écrite à plusieurs endroits, vous devez tous les changer sans aucune sécurité (telle qu'une erreur de compilation). Cela peut être contré en le déclarant seulement à un endroit et en réutilisant la variable.
Les fautes de frappe peuvent devenir des bugs sérieux. Si vous avez une fonction:
et quelqu'un tape accidentellement:
C’est pire si la chaîne est rare ou complexe, surtout si vous avez des programmeurs qui ne connaissent pas la langue maternelle du projet.
Les chaînes magiques sont rarement auto-documentées. Si vous voyez une chaîne, cela ne vous dit rien de ce que la chaîne pourrait / devrait être d'autre. Vous devrez probablement examiner l'implémentation pour vous assurer que vous avez sélectionné la bonne chaîne.
Ce type d'implémentation présente des fuites , nécessitant soit une documentation externe, soit un accès au code pour comprendre ce qui doit être écrit, d'autant plus qu'il doit s'agir d'un caractère parfait (comme au point 3).
En dehors des fonctions de recherche de chaîne dans les IDE, un petit nombre d'outils prend en charge le modèle.
Il se peut que vous utilisiez par hasard la même chaîne magique à deux endroits différents, alors si vous effectuez une recherche et un remplacement et que vous les modifiez tous les deux, l'un d'eux risque de se rompre pendant que l'autre fonctionne.
la source
Le point culminant de ce que les autres réponses ont compris n'est pas que les "valeurs magiques" sont mauvaises, mais qu'elles devraient l'être:
Ce qui distingue généralement les "constantes" acceptables des "valeurs magiques" est une violation d'une ou plusieurs de ces règles.
Bien utilisées, les constantes nous permettent simplement d’exprimer certains axiomes de notre code.
Ce qui m'amène au dernier point, à savoir un usage excessif de constantes (et donc d'un nombre excessif d'hypothèses ou de contraintes exprimées en termes de valeurs), même s'il respecte par ailleurs les critères ci-dessus (mais surtout s'il s'en écarte), Cela peut impliquer que la solution en cours d’élaboration n’est pas suffisamment générale ou structurée (nous ne parlons donc plus vraiment du pour et du contre des constantes, mais du pour et du contre d’un code bien structuré).
Les langages de haut niveau ont des constructions pour les modèles dans les langages de bas niveaux qui devraient employer des constantes. Les mêmes modèles peuvent également être utilisés dans le langage de niveau supérieur, mais ne devraient pas l'être.
Mais cela peut être un jugement d'expert basé sur une impression de toutes les circonstances et sur ce à quoi une solution devrait ressembler, et la façon dont ce jugement sera justifié dépendra beaucoup du contexte. En effet, il pourrait ne pas être justifié en termes de principe général, si ce n’est d’affirmer "je suis assez vieux pour avoir déjà vu ce genre de travail, avec lequel je suis familier, mieux fait"!
EDIT: après avoir accepté une édition, en rejeter une autre, et ayant maintenant effectué ma propre édition, puis-je maintenant considérer le style de formatage et de ponctuation de ma liste de règles à régler une fois pour toutes haha!
la source
value / 2
, plutôt quevalue / VALUE_DIVISOR
de la définir comme2
ailleurs. Si vous avez l'intention de généraliser une méthode de gestion de fichiers CSV, vous souhaiterez probablement que le séparateur soit passé en tant que paramètre et non défini en tant que constante. Mais c’est une question de jugement dans le contexte. L’exemple de @ WGroleauSPEED_OF_LIGHT
est quelque chose que vous voudriez nommer explicitement, mais tous les littéraux n’ont pas besoin de cela.la source
Exemple concret: je travaille avec un système tiers dans lequel les "entités" sont stockées avec des "champs". Fondamentalement, un système EAV . Comme il est assez facile d'ajouter un autre champ, vous pouvez y accéder en utilisant le nom du champ sous forme de chaîne:
(notez la chaîne magique "ProductName")
Cela peut entraîner plusieurs problèmes:
Ma solution a donc été de générer des constantes pour ces noms, organisées par type d’entité. Alors maintenant je peux utiliser:
C'est toujours une constante de chaîne et compile exactement le même binaire, mais présente plusieurs avantages:
Suivant sur ma liste: masquer ces constantes derrière des classes fortement typées - le type de données est également sécurisé.
la source
nameField = myEntity.ProductName;
.Les chaînes magiques ne sont pas toujours mauvaises , ce qui explique pourquoi vous ne pouvez pas trouver une raison générale de les éviter. (Par "chaîne magique", je suppose que vous entendez littéral chaîne dans le cadre d'une expression et non défini comme une constante.)
Dans certains cas particuliers, les chaînes magiques devraient être évitées:
Mais dans certains cas, les "chaînes magiques" vont bien. Disons que vous avez un analyseur simple:
Il n’ya vraiment pas de magie ici, et aucun des problèmes décrits ci-dessus ne s’applique. Il n'y aurait aucun avantage à mon humble avis à définir
string Plus="+"
etc. Restez simple.la source
if (dx != 0) { grad = dy/dx; }
."+"
et"-"
parTOKEN_PLUS
etTOKEN_MINUS
. A chaque fois que je le lisais, j'avais l'impression qu'il était plus difficile de le lire et de le déboguer! C'est certainement un endroit où je conviens que l'utilisation de chaînes simples est préférable.Pour ajouter aux réponses existantes:
Internationalisation (i18n)
Si le texte à afficher à l'écran est codé en dur et enfoui dans des couches de fonctions, vous aurez beaucoup de difficulté à fournir la traduction de ce texte dans d'autres langues.
Certains environnements de développement (par exemple, Qt) gèrent les traductions en recherchant une chaîne de texte de la langue de base dans la langue traduite. Les chaînes magiques peuvent généralement y survivre - jusqu'à ce que vous décidiez d'utiliser le même texte ailleurs et d'obtenir une faute de frappe. Même dans ce cas, il est très difficile de déterminer quelles chaînes magiques doivent être traduites lorsque vous souhaitez prendre en charge une autre langue.
Certains environnements de développement (par exemple, MS Visual Studio) adoptent une autre approche et exigent que toutes les chaînes traduites soient conservées dans une base de données de ressources et relues pour les paramètres régionaux actuels par l'ID unique de cette chaîne. Dans ce cas, votre application avec des chaînes magiques ne peut tout simplement pas être traduite dans une autre langue sans retouche majeure. Un développement efficace nécessite que toutes les chaînes de texte soient entrées dans la base de données de ressources et se voient attribuer un identifiant unique lors de la première écriture du code, et que la suite est relativement facile. Essayer de le remplacer après coup demandera généralement un très gros effort (et oui, j'y suis allé!), Il est donc préférable de faire les choses correctement.
la source
Ce n'est pas une priorité pour tout le monde, mais si vous voulez pouvoir calculer automatiquement les métriques de couplage / cohésion sur votre code, les chaînes magiques rendent cela presque impossible. Une chaîne située à un endroit fait référence à une classe, une méthode ou une fonction située à un autre endroit. Il n'existe pas de moyen automatique simple pour déterminer que la chaîne est couplée à la classe / méthode / fonction simplement en analysant le code. Seul le cadre sous-jacent (angulaire, par exemple) peut déterminer qu’il existe un lien - et il ne peut le faire qu’au moment de l’exécution. Pour obtenir vous-même les informations de couplage, votre analyseur devrait tout savoir sur le cadre que vous utilisiez, au-delà de la langue de base que vous codez.
Mais encore une fois, ce n’est pas quelque chose qui intéresse beaucoup les développeurs.
la source