web-dev-qa-db-fra.com

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

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

45
Edward

Oui, mais faites-le évident.

Faire:

  • utilisez constantes
  • utilisez un descriptif nom de variable

Ne pas:

64
J.K.

Ce que je trouve étrange à propos de cette Q&R jusqu'à présent, c'est que personne n'a réellement 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 coder en dur les valeurs, mais il n'y a pas de règle simple quant à lorsque ; cela dépend complètement du contexte.

La question la réduit aux valeurs , ce que je veux dire nombres magiques , mais la réponse à la question de savoir si c'est une bonne idée est par rapport à à quoi ils sont réellement utilisés!

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

  • Valeurs de configuration

    Je grince des dents chaque fois que je vois des instructions comme command.Timeout = 600. Pourquoi 600? Qui a décidé ça? Est-ce que cela expirait avant, et quelqu'un a soulevé le délai d'attente comme un hack au lieu de résoudre le problème de performance sous-jacent? Ou s'agit-il en fait d'une attente connue et documentée pour le temps de traitement?

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

  • Formules mathématiques

    Les formules ont généralement tendance à être assez statiques, de sorte que la nature des valeurs constantes à l'intérieur n'est pas vraiment particulièrement importante. Le volume d'une pyramide est de (1/3) b * h. On se soucie d'où vient le 1 ou le 3? Pas vraiment. Un commentateur précédent a souligné à juste titre que diameter = radius * 2 Est probablement meilleur que diameter = radius * RADIUS_TO_DIAMETER_CONVERSION_FACTOR - mais c'est une fausse dichotomie.

    Ce que vous devez faire pour ce type de scénario est de créer une fonction . Je n'ai pas besoin de savoir comment vous avez élaboré la formule mais j'ai encore besoin de savoir à quoi cela sert . Si, au lieu de n'importe quel non-sens écrit ci-dessus, j'écris volume = GetVolumeOfPyramid(base, height), alors soudainement tout devient beaucoup plus clair, et il est parfaitement normal d'avoir des nombres magiques à l'intérieur du (return base * height / 3) car il est évident qu'ils ne font partie que 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 calculs. Utilisez la composition de fonction ou les constantes dans ce cas.

  • Règles de domaine/métier

    Celui-ci est toujours la zone grise car cela dépend de la valeur exacte. La plupart du temps, ce sont ces nombres magiques particuliers qui sont susceptibles de se transformer en constantes, car cela rend le programme plus facile à comprendre sans compliquer la logique du programme. Considérez le test if Age < 19 Contre 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 à l'abstraction de fonction, par exemple function isLegalDrinkingAge(age) { return age >= 19 }. La seule chose est que souvent votre logique métier est beaucoup plus compliquée que cela, et il pourrait ne pas être logique de commencer à écrire des dizaines de fonctions avec 20-30 paramètres chacune. S'il n'y a pas d'abstraction claire basée sur des objets et/ou des fonctions, le recours aux constantes est OK.

    La mise en garde est que si vous travaillez pour le service des impôts, cela devient vraiment vraiment pesant et honnêtement inutile d'écrire AttachForm(FORM_CODE_FOR_SINGLE_TAXPAYER_FILING_JOINTLY_FOR_DEPRECIATION_ON_ARMPIT_HAIR). Vous n'allez pas le faire, vous allez à AttachForm("B-46") parce que chaque développeur qui a déjà travaillé ou qui y travaillera va savoir que "B-46" est le code de formulaire pour un un seul contribuable dépose bla bla bla - les codes de formulaire font partie du domaine lui-même, ils ne changent jamais, donc ce ne sont pas vraiment des nombres magiques.

    Vous devez donc utiliser les constantes avec parcimonie dans la logique métier; fondamentalement, vous devez comprendre si ce "nombre magique" est en fait 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 de très bonnes chances qu'il change.

  • Codes d'erreur et indicateurs d'état

    Ce n'est jamais correct de coder en dur, comme tout pauvre salaud qui a déjà été frappé avec le Previous action failed due to error code 46 Peut vous le dire. Si votre langue le prend en charge, vous devez utiliser un type d'énumération. Sinon, vous aurez généralement un fichier/module entier plein de constantes spécifiant les valeurs valides pour un type d'erreur particulier.

    Ne me laissez jamais voir return 42 Dans 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 en dur. Ne soyez pas paresseux à ce sujet; ce devrait être une décision consciente plutôt qu'un simple vieux code bâclé.

27
Aaronaught

Il existe différentes raisons pour attribuer un identifiant à un numéro.

  • 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 s'il doit être changé en 8. (Notez que les chaînes visibles par l'utilisateur il faudra peut-être changer si le logiciel doit être utilisé dans une langue différente, et c'est difficile à prévoir à l'avance.)
  • Si le nombre est difficile à taper de quelque façon que ce soit. Pour les constantes comme pi, il est préférable de donner une définition de précision maximale que de la retaper à plusieurs endroits, peut-être de manière inexacte.
  • Si le nombre apparaît à différents endroits. Vous ne devriez pas avoir à regarder deux utilisations de 45 dans les fonctions adjacentes et à vous demander si elles signifient la même chose.
  • Si le sens n'est pas immédiatement reconnaissable. Il est sûr de supposer que tout le monde sait ce qu'est 3.14159265 .... Il n'est pas sûr de supposer que tout le monde reconnaîtra la constante gravitationnelle, ou même pi/2. ("Tout le monde" ici dépend de la nature du logiciel. On peut s'attendre à ce que les programmeurs de systèmes connaissent la représentation octale des bits d'autorisation Unix ou similaires. Dans les logiciels d'architecture navale/marine, vérifier le nombre Froude d'une coque et la vitesse proposées pour voir si c'est 1.1 ou plus pourrait être parfaitement explicite à quiconque devrait y travailler.)
  • Si le contexte n'est pas reconnaissable. Tout le monde sait qu'il y a 60 minutes dans une heure, mais la multiplication ou la division par 60 peut ne pas être claire s'il n'y a pas d'indication immédiate que la quantité est une valeur de temps ou une valeur de taux .

Cela nous donne des critères pour les littéraux codés en dur. Ils doivent être immuables, ne pas être difficiles à saisir, se produire dans un seul endroit ou un seul contexte et avoir un sens reconnaissable. Il est inutile de définir 0 comme ARRAY_BEGINNING, par exemple, ou 1 comme ARRAY_INCREMENT.

7
David Thornley

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

const string server_var="server_var";

mais tu aurais dû

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

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

En dehors de cela, utilisez des constantes pour tout nombre autre que 0 (généralement). Si vous avez besoin d'un masque de bits 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 s'intégrerait probablement bien dans un cas.

5
Earlz

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

I valeurs codées en dur niquement si les valeurs sont spécifiées dans la spécification (sur une version finale de la spécification), par ex. La réponse HTTP OK sera toujours 200 (à moins que cela ne 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 des constantes dans le fichier de propriétés.

La raison pour laquelle j'ai spécifié des spécifications, c'est que la modification des constantes dans les spécifications nécessite une gestion du changement, dans laquelle les parties prenantes examineront le changement et approuveront/désapprouveront. Cela ne se produit 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 (par exemple HTTP), donc la changer signifie casser des millions de systèmes.

4
Buhake Sindi

Cela dépend de ce que vous considérez comme un codage en dur. Si vous essayez d'éviter toutes les choses codées en dur, vous vous retrouvez sur le territoire softcoding , et créez un système que seul le créateur peut gérer (et c'est le code dur ultime)

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

La règle de base que j'utilise est que tout ce qui peut et va changer, sans affecter l'état de l'ensemble du système, doit être configurable.

Donc, à mon humble avis, il est stupide de ne pas coder en dur des choses qui ne changent jamais (pi, constante gravitationnelle, une constante dans une formule mathématique - pensez au volume d'une sphère).

Il est également stupide de ne pas coder en dur des choses ou des processus qui auront un impact sur votre système 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, si un champ ajouté nécessite que le développeur de maintenance entrer et écrire un script qui fera fonctionner cette chose. De plus, il est stupide (et je l'ai vu plusieurs fois dans des environnements d'entreprise) de créer un outil de configuration, donc rien n'est codé en dur, pourtant, seuls les développeurs du service informatique peuvent l'utiliser, et il est à peine plus facile à utiliser que pour le faire dans Visual Studio.

Donc, en fin de compte, si une chose doit être codée en dur est fonction de deux variables:

  • la valeur changera-t-elle
  • comment un changement de valeur affectera le système
4
SWeko
  • si la valeur peut changer, et pourrait en effet changer, alors codez-la autant que possible tant que l'effort impliqué ne dépasse pas le rendement attendu
  • certaines valeurs ne peuvent pas être codées en douceur; suivre les directives de Jonathan dans ces (rares) cas
3
Steven A. Lowe

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 considérez pas cela comme une règle stupide, pensez-y comme une opportunité de mieux coder.

Le plus grand avantage serait la façon dont vous pourriez trouver des constantes similaires étant la seule différence dans les groupes de code - les résumer dans des tableaux m'a aidé à réduire certains fichiers de 90% de leur taille et à corriger plusieurs bugs de copier-coller entre-temps .

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

3
Bill K

J'ai récemment codé une fonction MySQL pour calculer correctement la distance entre deux paires lat/long. Vous ne pouvez pas simplement faire du pythagore; les lignes de longitude se rapprochent à mesure que la latitude augmente vers les pôles, donc il y a un peu de trig poilu impliqué. Le fait est que j'étais assez déchiré pour savoir s'il fallait 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/lng sont beaucoup plus rapprochées, disons, sur la lune. Et ma fonction sous-estimerait considérablement les distances entre les points sur Jupiter. J'ai pensé que les chances que le site Web que je construisais d'avoir un emplacement extraterrestre entré soient assez minces.

2
Dan Ray

Ça dépend si votre langue est compilée. Si ce n'est pas compilé, ce n'est pas grave, il vous suffit d'éditer 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 grande perte de temps si vous voulez ajuster cette variable.

Vous n'avez pas besoin de faire de curseur ou d'interface pour changer 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
jokoon

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

  1. Constantes qui ne concernent rien d'autre; vous pouvez changer ces constantes quand vous le souhaitez sans avoir à changer quoi que ce soit d'autre. Exemple: largeur par défaut d'une colonne de grille.

  2. Constantes absolument immuables, précises et évidentes, comme "nombre de jours par semaine". days = weeks * 7 Remplacement 7 avec une constante DAYS_PER_WEEK n'apporte pratiquement aucune valeur.

1
user281377

Je suis entièrement d'accord avec Jonathan mais comme toutes les règles, il y a des exceptions ...

"Numéro magique dans la spécification: Numéro magique dans le code"

Indique essentiellement que tous les nombres magiques qui restent dans la spécification après des tentatives raisonnables pour obtenir un contexte descriptif pour eux doivent être reflétés comme tels dans le code. Si des nombres magiques restent dans le code, tous les efforts doivent être faits pour les isoler et les rendre clairement liés à leur point d'origine.

J'ai effectué quelques contrats d'interfaçage où il est nécessaire de remplir les messages avec des valeurs mappées à partir de la base de données. Dans la plupart des cas, le mappage est assez simple et s'inscrit dans les lignes directrices 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 qui devaient être transmises dans la structure étaient des constantes imposées par la spécification du système distant. ceci couplé avec le fait que la structure du message était gargantuesque, il a fallu remplir BEAUCOUP de constantes. Dans la plupart des cas, ils n'ont pas fourni de sens ou de raison, ils ont simplement dit "mettez M ici" ou "mettez 4.10.53.10100.889450.4452 ici". Je n'ai pas non plus tenté de mettre un commentaire à côté de tous, cela aurait rendu le code résultant illisible. J'ai cependant veillé à ce que les sections de code où ces valeurs magiques apparaissent soient correctement isolées et que leurs conteneurs (classes, packages) soient nommés de manière appropriée pour pointer directement vers la spécification qui les applique.

Cela dit, quand on y pense ... il s'agit à peu près de le rendre évident ...

0
Newtopian

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 avez des ennuis.

0
jwenting

Surtout 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), ne pas utiliser de constante peut être correct.

0
user22908