Pourquoi avons-nous besoin d'énums dans des langages à typage dynamique?

32

Je lisais du code ici et j'ai vu qu'une énumération est utilisée pour stocker les noms des balises HTML. Pourquoi avons-nous jamais besoin de faire cela? Quel est le bénéfice de cette stratégie?

Je sais à quel point les énumérations sont utiles dans les langages compilés ou à typage statique, mais lorsque je vois des énumérations dans des langages à typage dynamique, je suis curieux, comme l’exemple de code que j’ai montré ci-dessus. Donc, la question se résume essentiellement à pourquoi avons-nous besoin d'énums dans un langage typé dynamiquement ou en avons-nous besoin du tout?

CodeYogi
la source
38
Cette question est essentiellement "Pourquoi avons-nous besoin de types" .
user11153
1
Avez-vous cherché le repo pour voir comment il s'appelle? Cela vous donnerait probablement une meilleure compréhension des réponses que vous avez reçues.
RubberDuck
si vous avez: enum People { YOU, NPC, FOO, BAR }et une fonction qui veut un (People) int, vous pouvez connecter n'importe quoi, au lieu d'utiliser un nombre.
Evan Carslake,
3
Vous vous interrogez sur le but de cette "énumération" ou sur le but des énumérations en général, dans n'importe quelle langue? Je supposerais le premier, mais toutes les réponses actuelles semblent penser le second ...
meriton - en grève

Réponses:

56

Un avantage est que le compilateur peut vous avertir si vous tapez accidentellement "ADRESS" ou "FEILDSET", et vous permet de le corriger immédiatement au lieu de vous comporter de façon absurde au moment de l'exécution.

Bien que l'avantage soit beaucoup plus utile dans les langages statiques que dynamique, il reste utile même s'il s'agit d'une erreur d'exécution, car vous obtiendrez un message indiquant un problème avec votre déclaration de cas plutôt que vos données.

comment s'appelle-t-il
la source
4
@amon: vous pourriez le faire, mais enums vous donne un mécanisme pratique pour éviter les collisions.
Whatsisname
75
Un endroit où j'avais l'habitude de travailler a passé un mois à chasser un bug causé par l'idée géniale d'utiliser des constantes de chaîne au lieu d'énums, de mauvaises polices d'éditeur et un champ nommé accidentellement"PROF1LE_"
Gort the Robot
8
@amon Go fait exactement cela. Une bonne chose à propos des énumérations, cependant, est que le compilateur peut vérifier que votre instruction switch a une casse pour chaque valeur d’énum possible.
weberc2
15
Ce code a été écrit dans les années 80. Vous ne le réalisez peut-être pas, mais c'était à une époque où certains développeurs ont appris à utiliser des machines à écrire physiques, qui n'avaient peut-être pas de clé unique . Bien que je réalise en réalité que la corde en question était "Profi1e" ... cela fait 25 ans, alors ma mémoire n'est évidemment pas parfaite.
Gort le robot
4
@DarrelHoffman: Je suis surpris que vous soyez surpris. En Perl, je me trouve souvent en train de taper $1quand je veux dire $i. (Certes, je ne tape jamais à la f1leplace de file- l' $1erreur est amorcée par le fait qu'il $1est très courant en Perl - mais néanmoins, des erreurs de toutes sortes sont courantes. Peut-être que le développeur avait un mot de passe prof1ledans celui-ci, les amorçant ainsi à entrer mal profiledans des contextes autres que les mots de passe.)
Ruakh,
22

Les énumérations sont utiles dans les situations où vous avez un ensemble fixe de valeurs / entités sensibles. Elles se documentent d'elles-mêmes et permettent au compilateur de valider des tâches qui seraient autrement laissées à l'exécution. Ils ne doivent jamais être utilisés si l'ensemble de valeurs significatives n'est pas connu ou n'est pas strictement limité.

Un exemple plus utile serait quelque chose comme les codes de réponse HTTP. Au lieu d'avoir une méthode qui prend un nombre et fournit le nom et / ou la description de l'erreur, vous pouvez avoir un ensemble d'énums avec des noms significatifs, un code et une description, etc. dans un seul paquet propre faisant autorité en ce qui concerne les valeurs autorisés et doivent être manipulés.

JimmyJames
la source
1
"L'auto-documentation" est la partie la plus importante. Je vérifierais bien plutôt si status === GEOLOCATION_ACQUIREDque status === 3, de sorte que la personne qui soutient que le logiciel comprend ce qui se passe. Comme vous l'avez dit, cela évite également les valeurs invalides.
Nicolas Bouliane
11

Les énumérations n’ont rien à voir avec la programmation orientée objet et JavaScript n’a pas d’énumération. Au lieu de cela, les énumérations sont utilisées chaque fois que vous avez le choix entre un ensemble fixe de valeurs. Par exemple, un booléen est un choix entre vrai et faux, qui pourrait être implémenté en tant que enum Bool { False, True }. Dans une bibliothèque graphique, nous pourrions avoir un ENUM pour les alignements: enum HAlignment { LEFT = -1, CENTER = 0, RIGHT = 1 }.

La manière dont l’énum est mis en œuvre n’est généralement pas pertinente, l’important étant que chaque valeur possible soit distincte. De nombreuses langues utilisent des entiers pour les énumérations, bien que certaines, comme Java, prennent en charge des objets arbitraires.

Jusqu'à présent, nous aurions tout aussi bien pu utiliser des constantes, par exemple const int LEFT = -1, CENTER = 0, RIGHT = 1. Cependant, un compilateur sait que les valeurs enum vont ensemble. Ainsi, lorsque je permute les valeurs d’énumération switch(value) {case LEFT: ...; case RIGHT: ...;}, le compilateur peut me prévenir que j’ai oublié le CENTERcas. Cela peut vous faire gagner beaucoup de temps. Dans les langues sans énums ou sans construction switch-case, ceci peut être simulé avec le modèle de visiteur, bien que cela soit plus utile en présence de typage statique.

L'autre avantage est que les enums peuvent être traités comme un type séparé. Par exemple, je peux déclarer qu'une méthode prend un HAlignmentparamètre plutôt qu'un entier. La compilation du code échouera si je ne fournis rien d’autre qu’une des trois valeurs possibles de HAlignment. Cependant, les énumérations de C ne sont pas bien encapsulées et les constantes d'énumération peuvent être utilisées indifféremment avec des entiers. Les autres langues sont plus strictes ici.

En JavaScript, nous n'obtenons aucun de ces avantages. L'exemple donné déclare un objet traité comme une énumération. Cela présente certains avantages pour le programmeur: par exemple, cela facilite la documentation, regroupe toutes les «constantes» dans un seul objet,…. Cependant, il est juste une convention qu'un tel objet est semblable à une énumération.

Le point ici est que HTML n'a qu'un ensemble de balises fini et connu. Vous pouvez consulter la spécification HTML5 et insérer ces noms d'éléments dans votre code en tant qu'énumération, et ainsi rendre plus difficile l'insertion d'une <blink>balise dans votre programme. Il est préférable d’encoder ces connaissances à un endroit donné que de mélanger votre code avec des littéraux de chaîne spéciaux (ou pire, des nombres magiques).

Amon
la source
Dans ce cas, si je passe <blink>à une méthode en JavaScript, rien ne peut m'arrêter, non? mais dans javabonjour se déchaîne :)
CodeYogi
@ CodeYogi oui, parce que JS n'a pas de système de type statique, et en particulier n'a pas de concept de types enum. Cependant, je peux documenter un paramètre de méthode comme «prend un TagName», ce qui inciterait un programmeur à l'invoquer comme foo(TagName.STRONG)étant un peu meilleur. Ce serait encore mieux si JS se plaignait si le champ n’existait pas, mais ici nous n’obtenons qu’un échec undefinedsi j’essaie TagName.BLINK. Cela ne vaut pas grand chose chez JS, mais c'est un début.
amon
Hmm, le lien de code que j'ai mentionné ci-dessus utilise un compilateur de fermeture a donc un sens là-bas.
CodeYogi
Clojure est un langage fonctionnel, donc je ne sais pas en quoi la programmation orientée objet est pertinente pour la question, mais cela mis à part, il est important de faire la distinction entre les énumérations qui ne sont généralement qu'un ensemble d'entiers (pas OO) et le modèle 'Typesafe enum' qui est OO et ce que Java supporte.
JimmyJames
@JimmyJames Je parle de JS, pas de Clo j ure (qui, fonctionnant sur la plate-forme Java, prend également en charge la POO dans une certaine mesure). La question a été étiquetée avec oop , c'est pourquoi je le mentionne au début. Je ne vois vraiment pas comment Typesafe énumérations sont connectés à POO, qui est juste une caractéristique du système de type (plusieurs langues non-oop ont des systèmes de type :-))
amon
3

Même si votre langage ne nécessite pas de compilation, vous utiliserez probablement une sorte d’EDI ou d’outils de développement, ce qui peut fournir un meilleur support pour quelque chose comme une énumération que pour des chaînes.

Si vous utilisez par exemple une énumération comme littéral d'objet en javascript, votre éditeur vous indiquera l'achèvement du code et votre vérificateur de code, tel que JSHint ou JSLint, vous en avertira si vous utilisez accidentellement la mauvaise valeur.

hansmaad
la source
Je pense que beaucoup des autres réponses manquent ou battent autour de ce point. Utiliser un 'emum' dans un langage dynamique peut ne rien faire pour un compilateur, mais cela peut vraiment aider certains IDE, outils de documentation, sans oublier les humains qui tentent de comprendre le code.
Robert
2

L'intérêt d'une telle énumération pourrait être de fournir à Js Api (goog) un ensemble / un ensemble de balises autorisées. Lesquels? Celles définies par W3C HTML 4.01 ( consultez la documentation d’enum ). Donc, ce sont les limites des paramètres.

C’est peut-être l’objectif réel ou non, mais cela fonctionnerait très bien à cette fin.

Si vous savez comment fonctionne Javascript, le code définit un tableau indexé par des chaînes :-). Quelle valeur est une chaîne, mais il pourrait s'agir de tout autre composant doté d'attributs, de fonctions, etc. Laissez libre cours à votre imagination et vous verrez des avantages partout.

Mis à part le Javascript, j'utilise beaucoup énums pour la modélisation et la gestion des machines à états .

START> IN_PROGRESS> CONFIRMED> FINISHED> ...

En Java, switch autorise les enums, il est donc assez facile de valider des états dans une machine à états , de les parcourir en boucle, de définir des priorités en effectuant des enums complexes, ...

Je les utilise également pour définir des constantes dactylographiées et non modifiables:

  • Oui Non

Également complexes (ce qui permet de faire des transformations / parseurs sécurisés)

  • Oui (1, vrai), non (0, faux)

En raison des enums appartenant souvent à ma couche de modèles (noyau), ses fonctionnalités sont accessibles à l’ensemble du système, ce qui en fait un modèle fonctionnel tout en conservant un faible couplage.

Ce que les énumérations donnent (entre autres), ce sont des limites et une typification

Laiv
la source