Est-ce une bonne idée de coder des valeurs dans nos applications?


45

Est-ce une bonne idée de coder des valeurs dans nos applications? Ou est-il toujours judicieux d'appeler ces types de valeurs de manière dynamique au cas où ils devraient changer?


2
un paramètre de configuration vous aiderait
Gopi

54
On ne sait jamais quand la valeur de pipourrait changer ...
Gabe

12
Man, je suppose que les gens comme @gabe sont la raison pour laquelle il s’agit d’une "règle". Si vous répétez 3.14 à 20 endroits dans votre code et constatez que vous avez réellement besoin de plus de précision, vous êtes foutus. Je n'avais pas réalisé que ce n'était pas évident.
Bill K

17
C'était un peu grossier, @ Bill. @ Gabe était clairement en train de plaisanter, mais à part cela, la question portait sur le codage en dur par rapport aux paramètres de configuration, et non par l'utilisation d'un nombre magique constant ou répété à plusieurs endroits.
David Conrad le

1
Oui, le codage en dur peut parfois être une bonne idée. Voir l'article de Wikipedia sur l'anti-motif "Softcoding".
user16764

Réponses:


64

Oui, mais rend les choses évidentes .

Faire:

  • utiliser des constantes
  • utiliser un nom de variable descriptif

Ne pas:


44
Lequel est plus propre diameter = 2 * radiusou diameter = RADIUS_TO_DIAMETER_FACTOR * radius? Il existe effectivement des cas où un nombre magique pourrait être la meilleure solution.
Joonas Pulakka le

5
Je ne peux pas être assez d'accord avec cette réponse. J'ai tendance à penser que programmer est comme un romancier. Vous racontez votre histoire à travers le code et si les gens ne peuvent pas comprendre la logique, cela rend votre code sans valeur à mon avis. C'est pourquoi des conventions de nommage bien pensées sont essentiellement destinées à la lisibilité. En outre, il n'y a aucune bonne raison d'utiliser des nombres magiques. En utilisant des nombres magiques, vous supprimez le "pourquoi" de l'équation et vous la rendez plus difficile à comprendre. Par exemple: "diamètre = 2 * rayon" À quoi servent les deux? Ce "diamètre = RADIUS_TO_DIAMETER_FACTOR * rayon" a beaucoup plus de sens.
chrisw

9
diamètre = 2 * le rayon est directement issu des mathématiques au lycée. La raison pour ne pas nommer le "2" est que pour qu’il ait une valeur autre, il faudrait modifier les lois de la physique ou des mathématiques, ou les deux. (Par contre, nommer Pi, ou constante de Plancks est un bon choix pour une lisibilité simple).
Rapidement maintenant

8
@Joonas: Pfft. Vous voulez sûrement dire diameter = radius << 1? Je suppose que cela pourrait aussi être diameter = radius << RADIUS_TO_DIAMETER_BITS_TO_SHIFT.
Ant

4
comment « bout certainsdiameter = radius.toDiameter()
Carson Myers

27

Ce que je trouve curieux à propos de cette séance de questions-réponses jusqu’à présent, c’est que personne n’a en fait tenté de définir clairement le "code dur" ou, plus important encore, les alternatives.

tl; dr: Oui, il est parfois une bonne idée de valeurs coder en dur, mais il n'y a pas de règle simple à quand ; cela dépend complètement du contexte.

La question se limite aux valeurs , ce qui, à mon sens, désigne les nombres magiques , mais la réponse à la question de savoir si elles sont ou non une bonne idée est relative à ce à quoi elles sont réellement utilisées!

Voici quelques exemples de valeurs "codées en dur":

  • Valeurs de configuration

    Je grince des dents chaque fois que je vois des déclarations comme command.Timeout = 600. Pourquoi 600? Qui a décidé ça? Était-ce la fin du temps imparti avant, et quelqu'un a-t-il augmenté le délai d'attente au lieu de résoudre le problème de performances sous-jacent? Ou s'agit-il réellement d'une attente connue et documentée en matière de temps de traitement?

    Celles-ci ne doivent pas être des nombres ou des constantes magiques , elles doivent être externalisées dans un fichier de configuration ou une base de données quelque part avec un nom explicite, car leur valeur optimale est déterminée en grande partie ou entièrement par l'environnement dans lequel l'application est exécutée.

  • Formules mathématiques

    Les formules ont généralement tendance à être plutôt statiques, de sorte que la nature des valeurs constantes à l'intérieur n'est pas vraiment importante. Le volume d'une pyramide est (1/3) b * h. Est-ce que nous nous soucions d'où vient le 1 ou le 3? Pas vraiment. Un intervenant précédent a fait remarquer à juste titre que c’était diameter = radius * 2probablement mieux que diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR- mais c’est une fausse dichotomie.

    Ce que vous devriez faire pour ce type de scénario, c'est créer une fonction . Je n'ai pas besoin de savoir comment vous en êtes arrivé à la formule, mais j'ai toujours besoin de savoir à quoi elle sert . Si, au lieu des absurdités écrites ci-dessus, j'écris volume = GetVolumeOfPyramid(base, height), tout devient alors tout à fait plus clair, et il est parfaitement correct d'avoir des nombres magiques dans la fonction ( return base * height / 3) car il est évident qu'ils font simplement partie de la formule.

    La clé ici est bien sûr d'avoir des fonctions courtes et simples . Cela ne fonctionne pas pour les fonctions avec 10 arguments et 30 lignes de calcul. Utilisez la composition de fonction ou les constantes dans ce cas.

  • Domaine / règles métier

    Celui-ci est toujours la zone grise car elle dépend de la valeur exacte. La plupart du temps, ce sont ces nombres magiques particuliers qui peuvent être transformés en constantes, car cela rend le programme plus facile à comprendre sans compliquer la logique du programme. Considérez le test if Age < 19contre if Age < LegalDrinkingAge; vous pouvez probablement comprendre ce qui se passe sans la constante, mais c'est plus facile avec le titre descriptif.

    Ceux-ci peuvent également devenir candidats à une abstraction de fonction, par exemple function isLegalDrinkingAge(age) { return age >= 19 }. La seule chose à faire est que, souvent, votre logique métier est beaucoup plus complexe et qu'il n'est peut-être pas logique de commencer à écrire des dizaines de fonctions comportant chacune 20 à 30 paramètres. S'il n'y a pas d'abstraction claire basée sur des objets et / ou des fonctions, le recours à des constantes est acceptable.

    La mise en garde est que, si vous travaillez pour le service des impôts, il devient vraiment très lourd et honnêtement inutile d’écrire AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR). Vous n'allez pas faire cela, vous allez le faire, AttachForm("B-46")car chaque développeur qui a déjà travaillé ou travaillera ici saura que "B-46" est le code de formulaire pour un contribuable déposant blah blah blah - les codes de formulaire font partie du domaine lui-même, ils ne changent jamais, ils ne sont donc pas vraiment des nombres magiques.

    Vous devez donc utiliser les constantes avec parcimonie dans la logique métier; en gros, vous devez comprendre si ce "nombre magique" est réellement un nombre magique ou s'il s'agit d'un aspect bien connu du domaine. Si c'est un domaine, vous ne le codez pas à moins qu'il y ait une très bonne chance que cela change.

  • Codes d'erreur et indicateurs d'état

    Celles-ci ne sont jamais acceptables pour le codage en dur, comme le dit tout pauvre bâtard qui a déjà été touché Previous action failed due to error code 46. Si votre langue le prend en charge, vous devriez utiliser un type d’énumération. Sinon, vous aurez généralement un fichier / module complet rempli de constantes spécifiant les valeurs valides pour un type d'erreur particulier.

    Ne me laisse jamais voir return 42dans un gestionnaire d'erreur, capiche? Pas d'excuses.

J'ai probablement omis plusieurs scénarios, mais je pense que cela couvre la plupart d'entre eux.

Donc, oui, il est parfois acceptable de coder de manière stricte. Juste ne soyez pas paresseux à ce sujet; il devrait s'agir d'une décision consciente plutôt que d'un vieux code bâclé.


Merci pour la bonne ventilation! - la plupart des gens ne réfléchissent pas à toutes les options mais j'ajouterais "Configuration de l'environnement" - Je pense que celles-ci devraient être évitées (non codées en dur), car la plupart des données devraient être placées dans un fichier de configuration ou une base de données. Ceci suit le principe de "garder les données et la logique séparées" qui est un pilier de MVC ou de MVVM. string TestServerVar = "foo"; chaîne ProdServerVal = "bar";
M1M1K

7

L'attribution d'un identifiant à un numéro peut avoir différentes raisons.

  • Si le nombre peut changer, il devrait avoir un identifiant. Il est beaucoup plus facile de trouver NUMBER_OF_PLANETS que de rechercher chaque instance de 9 et de déterminer si elle doit être changée en 8. (Notez que les chaînes visibles par l'utilisateur devront peut-être être modifiées si le logiciel doit être utilisé dans une autre langue, une chose difficile à prédire à l'avance.)
  • Si le numéro est difficile à saisir de quelque manière que ce soit. Pour les constantes telles que pi, il est préférable de donner une définition de précision maximale plutôt que de la retaper à plusieurs endroits, éventuellement de manière inexacte.
  • Si le nombre apparaît à des endroits différents. Vous ne devriez pas avoir à regarder deux utilisations de 45 dans des fonctions adjacentes et vous demander si elles veulent dire la même chose.
  • Si le sens n'est pas immédiatement reconnaissable. Il est prudent de supposer que tout le monde sait ce que 3.14159265 ... est. Il n’est pas prudent de supposer que tout le monde reconnaîtra la constante gravitationnelle, voire pi / 2. ("Tout le monde" dépend ici de la nature du logiciel. On peut s’attendre à ce que les programmeurs connaissent la représentation octale des bits de permission Unix ou similaires. Dans les logiciels d’architecture navale / marine, vérifiez le nombre de Froude d’une coque proposée et voir si c'est 1.1 ou supérieur pourrait être parfaitement explicite pour quiconque devrait travailler dessus.)
  • Si le contexte n'est pas reconnaissable Tout le monde sait qu'il y a 60 minutes dans une heure, mais multiplier ou diviser par 60 peut ne pas être clair s'il n'y a aucune indication immédiate que la quantité est une valeur de temps ou une valeur de taux.

Cela nous donne des critères pour coder en dur les littéraux. Ils doivent être immuables, faciles à dactylographier, apparaître à un endroit ou dans un seul contexte et avoir une signification reconnaissable. Il est inutile de définir 0 comme ARRAY_BEGINNING, par exemple, ou 1 comme ARRAY_INCREMENT.


5

En complément d'autres réponses. Utilisez des constantes pour les chaînes lorsque cela est possible. Bien sûr, vous ne voulez pas avoir

const string server_var="server_var";

mais vous devriez avoir

const string MySelectQuery="select * from mytable;";

(en supposant que vous ayez toujours une requête pour laquelle vous voulez obtenir tous les résultats d'une table spécifique, toujours)

Autre que cela, utilisez des constantes pour tout nombre autre que 0 (généralement). Si vous avez besoin d’un masque binaire d’autorisation de 255, n’utilisez pas

const int 8th_bit=255; //or some other obscure naming scheme that equates to 255.

utilisez plutôt

const int AllowGlobalRead=255;

Bien sûr, avec les constantes, sachez quand utiliser les énumérateurs. Le cas ci-dessus conviendrait probablement bien dans un cas.


typedef enum {state_0 = 0, state_1 = 1, state_2 = 2, ...} ... Ne rigolez pas, je l'ai déjà vu. Frappez cette personne autour de la tête avec un poisson mouillé!
Rapidement maintenant

@ rapidement bien sûr, vous voudriez quelque chose de plus semblable àtypedef enum {init_state=0, parse_state=1, evaluation_state=2, ... }
Earlz

6
THIS_NAMING_CONVENTION_IS_RECOMMENDED_FOR_CONSTANTS
StuperUser

4
Pour les chaînes, vous ne voulez pas seulement des constantes. Vous souhaitez placer toutes les chaînes visibles par l'utilisateur dans une sorte de fichier de ressources (les détails dépendent de votre plate-forme) afin de pouvoir passer facilement à une autre langue.
David Thornley le

Vous pouvez également vouloir coller des chaînes liées à la logique métier (telles que des requêtes SQL) dans un fichier de ressources avec un type de cryptage ou d'obfuscation. Cela empêchera les utilisateurs "curieux" de procéder à un reverse engineering de votre logique (ou de votre schéma de base de données).
TMN

4

Cela dépend de ce que vous considérez comme codage en dur. Si vous essayez d'éviter tout ce qui est codé en dur, vous vous retrouvez dans une zone de codage souple et vous créez un système que seul le créateur peut gérer (et c'est le code définitif ultime).

Beaucoup de choses sont codées en dur dans tout cadre raisonnable et elles fonctionnent. c'est-à-dire qu'il n'y a aucune raison technique pour laquelle je ne devrais pas être en mesure de changer le point d'entrée d'une application C # (Static void Main), mais un codage en dur qui ne crée aucun problème pour aucun utilisateur (à l'exception de la question occasionnelle SO )

La règle empirique que j’utilise est que tout ce qui peut et va changer, sans affecter l’état de tout le système, doit être confugurable.

Donc, IMHO, il est idiot de ne pas coder en dur des choses qui ne changent jamais (pi, constante gravitationnelle, constante dans une formule mathématique - pensez au volume d’une sphère).

En outre, il est idiot de ne pas coder en dur les éléments ou processus qui auront un impact sur votre système et qui nécessiteront une programmation dans tous les cas, c’est-à-dire qu’il est inutile de permettre à l’utilisateur d’ajouter des champs dynamiques à un formulaire. Entrez et écrivez un script qui fera en sorte que cette chose fonctionne. En outre, il est stupide (et je l’ai vu quelques fois dans des environnements d’entreprise) de créer un outil de configuration. Ainsi, rien n’est codé en dur. Pourtant, seuls les développeurs du service informatique peuvent l’utiliser, et il est légèrement plus facile à utiliser que faire dans Visual Studio.

Ainsi, le résultat final, si une chose doit être codée en dur est une fonction de deux variables:

  • la valeur changera-t-elle
  • comment un changement de la valeur affectera le système

4

Est-ce une bonne idée de coder des valeurs dans nos applications?

Je code uniquement les valeurs si les valeurs sont spécifiées dans la spécification (sur une version finale de la spécification), par exemple, la réponse HTTP OK sera toujours 200(sauf si elle change dans le RFC), vous verrez donc (dans certains de mes codes ) des constantes comme:

public static final int HTTP_OK = 200;

Sinon, je stocke les constantes dans le fichier de propriétés.

La raison pour laquelle j'ai spécifié des spécifications, est que la modification des constantes dans les spécifications nécessite une gestion des modifications, dans laquelle les parties prenantes examinent les modifications et les approuvent / désapprouvent. Cela n'arrive jamais du jour au lendemain et prend des mois / années pour une approbation. N'oubliez pas que de nombreux développeurs utilisent des spécifications (HTTP, par exemple). Cela signifie donc que des millions de systèmes doivent être détruits.


3
  • si la valeur peut changer, et peut même changer, alors codez-la autant que possible dans la mesure du possible, à condition que l'effort requis ne dépasse pas le retour attendu
  • certaines valeurs ne peuvent pas être codées de manière souple; suivre les directives de Jonathan dans les cas (rares)

3

J'ai remarqué que chaque fois que vous pouvez extraire des données de votre code, cela améliore ce qui reste. Vous commencez à remarquer de nouvelles refactorisations et à améliorer des sections entières de votre code.

C'est juste une bonne idée de travailler à l'extraction de constantes, ne le considérez pas comme une règle stupide, considérez cela comme une opportunité de mieux coder.

Le plus gros avantage serait de pouvoir trouver des constantes similaires comme la seule différence entre les groupes de code - les résumer dans des tableaux m'a aidé à réduire certains fichiers de 90% de leur taille et à corriger quelques bugs de copier-coller entre-temps. .

Je n'ai pas encore vu un seul avantage à ne pas extraire de données.


2

J'ai récemment codé une fonction MySQL pour calculer correctement la distance entre deux paires lat / long. Vous ne pouvez pas simplement faire Pythagore; les lignes de longitude se rapprochent au fur et à mesure que la latitude augmente vers les pôles, il y a donc un trig assez poilu impliqué. En fait, j’étais assez découragé de décider de coder en dur la valeur représentant le rayon de la Terre en miles.

J'ai fini par le faire, même si le fait est que les lignes lat / gauche sont beaucoup plus rapprochées sur, par exemple, la lune. Et ma fonction sous-représenterait considérablement les distances entre points sur Jupiter. Je me suis dit que les chances que le site Web que je construis aient un emplacement extraterrestre dans lequel on entre est assez mince.


Oui, probablement, mais qu'en est-il de google.com/moon
Residuum

1

Cela dépend si votre langue est compilée. Si ce n'est pas compilé, ce n'est pas grave, il suffit de modifier le code source, même s'il sera légèrement délicat pour un non-programmeur.

Si vous programmez avec un langage compilé, ce n'est clairement pas une bonne idée, car si les variables changent, vous devez recompiler, ce qui est une grosse perte de temps si vous souhaitez ajuster cette variable.

Vous n'avez pas besoin de faire un curseur ou une interface pour modifier dynamiquement sa variable, mais le moins que vous puissiez faire est un fichier texte.

Par exemple, avec mon projet ogre, j'utilise toujours la classe ConfigFile pour charger une variable que j'ai écrite dans un fichier de configuration.


1

Deux fois où les constantes sont (à mon avis du moins) OK:

  1. Des constantes qui ne concernent rien d'autre; vous pouvez modifier ces constantes quand bon vous semble sans rien changer d'autre. Exemple: La largeur par défaut d'une colonne de la grille.

  2. Constantes absolument immuables, précises et évidentes, telles que "nombre de jours par semaine". days = weeks * 7Le remplacement 7par une constante DAYS_PER_WEEKn'apporte pratiquement aucune valeur.


0

Je suis tout à fait d'accord avec Jonathan mais comme toutes les règles il y a des exceptions ...

"Nombre magique dans la spécification: Nombre magique dans le code"

Fondamentalement, tout code magique qui reste dans la spécification après des tentatives raisonnables pour obtenir un contexte descriptif doit être reflété en tant que tel dans le code. Si des nombres magiques restent dans le code, tout doit être mis en oeuvre pour les isoler et les lier clairement à leur point d'origine.

J'ai effectué quelques contrats d'interfaçage pour lesquels il est nécessaire de renseigner des messages avec des valeurs mappées à partir de la base de données. Dans la plupart des cas, la mise en correspondance est assez simple et correspondrait bien aux directives générales de Jonathan, mais j'ai rencontré des cas où la structure du message cible était tout simplement horrible. Plus de 80% des valeurs devant être transmises dans la structure étaient des constantes imposées par la spécification du système distant. Ceci, ajouté au fait que la structure du message était gigantesque, a obligé à remplir BEAUCOUP de telles constantes. Dans la plupart des cas, ils ne fournissaient pas de sens ni de raison, ils disaient simplement "mettre M ici" ou "mettre 4.10.53.10100.889450.4452 ici". Je n'ai pas non plus essayé de mettre un commentaire à côté d'eux car cela aurait rendu le code résultant illisible.

Cela dit, quand on y réfléchit ... il s’agit en gros de rendre cela évident ...


0

Si vous codez en dur la valeur de la constante gravitationnelle de la Terre, personne ne s'en souciera. Si vous codez en dur l'adresse IP de votre serveur proxy, vous rencontrez des problèmes.


1
Vous aurez peut-être besoin de plus de précision pour la constante gravitationnelle de la Terre. Un codage dur à plusieurs reprises peut donc poser problème.
user281377

1
Peter Noone? Des Hermits d'Herman?
David Conrad

L’accélération gravitationnelle sur la Terre est d’environ 9,81 m / s ^ 2 pour la plupart des latitudes et des altitudes (bien sûr, si vous recherchez du pétrole sous terre ou tirez des ICBM au-dessus du pôle Nord, sachant que la variation de la gravité est très importante pour vous. beaucoup plus de décimales), avec l'accélération gravitationnelle sur les autres planètes étant un nombre différent, mais pour autant que je sache, la constante gravitationnelle est constante autour de l'univers. Il y a beaucoup de physique qui devrait changer si g était variable.
Tangurena

0

Généralement non, mais je pense que cela vaut la peine de noter que vous aurez le plus de problèmes lorsque vous commencerez à dupliquer la valeur codée en dur. Si vous ne le dupliquez pas (par exemple, utilisez-le une seule fois dans l'implémentation d'une classe), le fait de ne pas utiliser de constante peut suffire.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.