J'ai vu plusieurs questions/discussions ici sur la meilleure façon de gérer et de conserver les valeurs de type énumération (par exemple données persistantes adaptées aux énumérations , comment conserver une énumération à l'aide de NHibernate ), et j'aimerais savoir quel est le consulat général.
En particulier:
Remarque: J'ai déplacé les explications initialement incluses dans cette question vers une réponse.
J'ai essayé de résumer ma compréhension. N'hésitez pas à le modifier si vous avez des corrections. Alors ça y va:
Dans le code
Dans le code, les énumérations doivent être gérées en utilisant le type d'énumération natif du langage (au moins dans Java et C #), ou en utilisant quelque chose comme "modèle d'énumération typesafe" L'utilisation de constantes simples (Entier ou similaire) est déconseillée, car vous perdez la sécurité du type (et il est difficile de comprendre quelles valeurs sont légales pour une méthode, par exemple).
Le choix entre ces deux dépend de la quantité de fonctionnalités supplémentaires à attacher à l'énumération:
En particulier, au moins dans Java une énumération ne peut pas hériter d'une autre classe, donc si vous avez plusieurs énumérations avec un comportement similaire que vous aimeriez mettre dans une superclasse, vous ne pouvez pas utiliser les énumérations de Java.
Énumérations persistantes
Pour conserver les énumérations, chaque valeur d'énumération doit se voir attribuer un ID unique. Cela peut être soit un entier, soit une chaîne courte. Une chaîne courte est préférée, car elle peut être mnémonique (permet aux DBA, etc. de comprendre plus facilement les données brutes dans la base de données).
Un problème avec cette approche est que la liste des valeurs d'énumération légales existe à deux endroits (code et base de données). C'est difficile à éviter et donc souvent considéré comme acceptable, mais il existe deux alternatives:
Je suis d'accord avec beaucoup de ce que vous dites. Une chose que j'aimerais ajouter, cependant, à propos de la persistance des énumérations: je ne crois pas que la génération des énumérations au moment de la construction à partir des valeurs de la base de données soit acceptable, mais je pense également que la vérification de l'exécution n'est pas une bonne solution. . Je définirais un troisième moyen: avoir un test unitaire qui vérifiera les valeurs de l'énumération par rapport à la base de données. Cela empêche la divergence "occasionnelle" et évite la surcharge de vérification des énumérations par rapport à la base de données chaque fois que le code est exécuté.
L'article initial me semble bien. Pourtant, sur la base des commentaires, il semble que certains commentaires concernant Java pourraient clarifier peu de choses.
Enum type in Java est une classe par définition, mais de nombreux programmeurs ont tendance à l'oublier, car ils la relient plutôt à "une liste de valeurs autorisées" comme dans d'autres langages. C'est plus que cela .
Ainsi, pour éviter ces instructions switch, il peut être raisonnable de mettre du code et des méthodes supplémentaires dans la classe enum. Il n'est presque jamais nécessaire de créer une "classe réelle semblable à une énumération".
Considérez également le point de la documentation - voulez-vous documenter la signification réelle de votre énumération dans la base de données? Dans le code source reflétant les valeurs (votre type d'énumération) ou dans une documentation externe? Personnellement, je préfère le code source.
Si vous souhaitez présenter les valeurs d'énumération sous forme d'entiers dans la base de données en raison de la vitesse ou pour une raison quelconque, ce mappage doit également résider dans l'énumération Java. Vous obtiendrez le mappage de nom de chaîne par défaut, et Je me suis contenté de cela. Il y a un nombre ordinal associé à chaque valeur d'énumération, mais l'utiliser directement comme mappage entre le code et la base de données n'est pas très clair, car ce nombre ordinal changera si quelqu'un réordonne les valeurs dans le code source. Ou ajoute des valeurs d'énumération supplémentaires entre les valeurs existantes. Ou supprime une certaine valeur.
(Bien sûr, si quelqu'un change le nom de l'énumération dans le code source, le mappage de chaîne par défaut devient aigre aussi, mais cela est moins susceptible de se produire accidentellement. Et vous pouvez plus facilement vous protéger contre cela si nécessaire en mettant une vérification à l'exécution et vérifiez les contraintes dans la base de données comme déjà suggéré ici.)
Dans la gestion du code pour C #, vous avez manqué de définir la suppression de la valeur 0. Je déclare presque sans faute toujours ma première valeur comme:
public enum SomeEnum
{
None = 0,
}
Afin de servir de valeur nulle. Parce que le type de support est un entier et un entier par défaut à 0, il est donc extrêmement utile dans de nombreux endroits pour savoir si une énumération a été définie par programme ou non.
Java ou C # doit toujours utiliser des énumérations dans le code. Avertissement: Mon parcours est C #.
Si la valeur doit être conservée dans une base de données, les valeurs intégrales de chaque membre d'énumération doivent être explicitement définies afin qu'un changement ultérieur de code ne modifie pas accidentellement les valeurs d'énumération traduites et donc le comportement de l'application.
Les valeurs doivent toujours être conservées dans une base de données en tant que valeurs intégrales, pour se protéger contre le refactoring de nom enum. Conservez la documentation sur chaque énumération dans un wiki et ajoutez un commentaire au champ de la base de données pointant vers la page wiki documentant le type. Ajoutez également de la documentation XML au type enum contenant un lien vers l'entrée wiki afin qu'elle soit disponible via Intellisense.
Si vous utilisez un outil pour générer du code CRUD, il doit être capable de définir un type d'énumération à utiliser pour une colonne afin que les objets de code générés utilisent toujours des membres énumérés.
Si une logique personnalisée doit être appliquée pour un membre d'énumération, vous avez quelques options:
Je n'ai pas essayé cela, mais avec SQL Server 2005 ou version ultérieure, vous pouvez théoriquement enregistrer du code C # avec la base de données qui contiendrait des informations d'énumération et la possibilité de convertir des valeurs en énumérations pour les utiliser dans des vues ou d'autres constructions, créant une méthode de traduction de la données d'une manière plus facile à utiliser pour les administrateurs de base de données.
Eh bien, d'après mon expérience, en utilisant des énumérations pour autre chose que pour passer des options (en tant que drapeaux) à un appel de méthode immédiat, il en résulte switch
- à un moment donné.
switch
)switch
- es dans vos méthodes d'extension sinon ailleurs.Donc, pour une entité de type énumération avec un peu plus de fonctionnalités, vous devez prendre un certain temps et la créer en tant que classe, avec plusieurs choses à l'esprit:
Chaque fois que vous vous trouvez en utilisant des "nombres magiques" dans le code, changez en énumérations. Outre le gain de temps (puisque la magie disparaîtra lorsque les bogues arriveront ...), cela économisera vos yeux et votre mémoire (des énumérations significatives rendent le code plus lisible et auto-documenté), car devinez quoi - vous êtes probablement la personne à entretenir et à développer votre propre code
Le stockage de la valeur de texte d'une énumération dans une base de données est moins préférable au stockage d'un entier, en raison de l'espace supplémentaire requis et de la recherche plus lente. Il est précieux en ce sens qu'il a plus de sens qu'un nombre, mais la base de données est destinée au stockage et la couche de présentation sert à rendre les choses agréables.
À mon humble avis, comme pour la partie code:
Vous devez toujours utiliser le type 'enum' pour vos énumérations, en gros, vous obtenez beaucoup de cadeaux si vous le faites: Tapez la sécurité, l'encapsulation et l'évitement des commutateurs, le support de certaines collections telles que EnumSet
et EnumMap
et clarté du code.
quant à la partie persistance, vous pouvez toujours conserver la représentation sous forme de chaîne de l'énumération et la recharger à l'aide de la méthode enum.valueOf (String).
Je sais que c'est un ancien forum, que se passe-t-il si la base de données peut avoir d'autres choses qui s'y intègrent directement? Par exemple. lorsque la base de données résultante est le seul objectif du code. Ensuite, vous définirez les énumérations à chaque intégration. Mieux vaut alors les avoir dans la DB. Sinon, je suis d'accord avec le message d'origine.