Supposons que je propose 4 types de services (il est peu probable qu'ils changent souvent):
- Essai
- Conception
- Programmation
- Autre
Supposons que je dispose de 60 à 80 services réels qui entrent dans l'une des catégories ci-dessus. Par exemple, "un service" peut être "Programme de test utilisant la technique A" et il est de type "Test".
Je veux les encoder dans une base de données. Je suis venu avec quelques options:
Option 0:
Utiliser VARCHAR
directement pour encoder directement le type de service sous forme de chaîne
Option 1:
Utiliser la base de données enum
. Mais, enum est le mal
Option 2:
utilisez deux tables:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
Je peux même profiter de l'intégrité référentielle:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
Ça sonne bien, oui?
Mais je dois encore encoder des choses et gérer des entiers, c'est-à-dire lors du remplissage de la table. Ou je dois créer des constructions de programmation ou de base de données élaborées lors du remplissage ou du traitement de la table. À savoir, les jointures lorsqu’il s’agit de traiter directement avec la base de données ou de créer de nouvelles entités orientées objet du côté de la programmation et de s’assurer que je les exploite correctement.
Option 3:
Ne pas utiliser enum
, ne pas utiliser deux tables, mais simplement utiliser une colonne entière
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
Cela ressemble à une "fausse énumération" qui nécessite plus de temps système du côté du code, comme par exemple savoir le savoir {2 == 'Programming'}
et le gérer de manière appropriée.
Question:
Actuellement, je l'ai implémenté en utilisant l' option 2 , guidée par des concepts
- ne pas utiliser enum (option 1)
- éviter d'utiliser une base de données comme feuille de calcul (option 0)
Mais je ne peux pas m'empêcher de penser que cela me semble une perte de temps en termes de programmation et de surcharge cognitive: je dois connaître deux tables et gérer deux tables au lieu d'une.
Pour un «moyen moins coûteux», je regarde Option 3
. L'informatique est plus légère et nécessite essentiellement les mêmes constructions de code (avec de légères modifications mais la complexité et la structure sont fondamentalement les mêmes mais avec une seule table)
Je suppose que, dans l’idéal, ce n’est pas toujours un gaspillage d’argent et que l’une ou l’autre des options est bien fondée, mais existe-t-il une bonne directive quant au moment où il convient d’utiliser l’option 2 et l’option 3?
Quand il n'y a que deux types (binaire)
Pour ajouter un peu plus à cette question ... dans le même lieu, j'ai une option binaire de service "Standard" ou "Exception", qui peut s'appliquer à l'élément de ligne de service. J'ai encodé cela en utilisant l' option 3 .
J'ai choisi de ne pas créer une nouvelle table uniquement pour contenir les valeurs {"Standard", "Exception"}. Donc, ma colonne ne contient que {0, 1} et mon nom de colonne est appelé exception
, et mon code est en train de faire une traduction {0, 1} => {STANDARD, EXCEPTION}
(que j'ai encodée comme constantes dans un langage de programmation)
Jusqu'ici, je n'aime pas cette façon non plus ..... (ne pas aimer l'option 2 ni l'option 3). Je trouve que l'option 2 est supérieure à 3, mais avec plus de temps système, et je ne peux toujours pas échapper au codage sous forme d'entiers, quelle que soit l'option que j'utilise sur 2 et 3.
ORM
Pour ajouter un contexte, après avoir lu les réponses - je viens de commencer à utiliser (récemment) un ORM, dans mon cas, Doctrine 2. Après avoir défini le schéma de base de données via Annotations, je souhaitais remplir la base de données. Comme tout mon ensemble de données est relativement petit, je voulais essayer d’utiliser des constructions de programmation pour voir comment cela fonctionne.
J'ai d'abord rempli service_type
s, puis service_line_item
s, car il existait une liste provenant d'un tableur réel. Ainsi, les éléments tels que 'standard / exception' et 'Testing' sont tous des chaînes de la feuille de calcul et doivent être codés dans les types appropriés avant de les stocker dans la base de données.
J'ai trouvé ceci SO réponse: Qu'est-ce que vous utilisez à la place d'ENUM dans doctrine2? , qui suggère de ne pas utiliser la construction enum de DB, mais d'utiliser un INT
champ et de coder les types en utilisant la construction 'const' du langage de programmation.
Mais comme le souligne la question SO ci-dessus, je peux éviter d’utiliser directement des entiers et d’utiliser des constructions de langage - des constantes - une fois qu’ils sont définis ....
Mais string
quand même … peu importe comment vous le tournez, si je commence par un type, je dois d'abord le convertir en un type approprié, même si vous utilisez un ORM.
Donc, si $str = 'Testing';
je dis , j'ai toujours besoin d'un bloc quelque part qui fait quelque chose comme:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
La bonne chose est que vous ne traitez pas avec des nombres entiers / magiques (mais avec des quantités constantes codées), mais le problème est que vous ne pouvez pas automatiquement extraire des objets de la base de données sans cette étape de conversion, à mon connaissance.
Et c'est ce que je voulais dire, en partie, en disant des choses comme "il faut encore encoder les choses et gérer les entiers". (D'accord, maintenant, après le commentaire d'Ocramius, je n'aurai pas à traiter directement avec les entiers, mais avec les constantes nommées et une certaine conversion en / à partir de constantes, selon les besoins).