Supposons que vous écriviez une application pouvant être configurée par l'utilisateur. Pour stocker ces "données de configuration" dans une base de données, deux modèles sont couramment utilisés.
La table à une rangée
CompanyName | StartFullScreen | RefreshSeconds | ... ---------------+-------------------+------------------+-------- ACME Inc. | true | 20 | ...
La table de paires nom-valeur
ConfigOption | Value -----------------+------------- CompanyName | ACME Inc. StartFullScreen | true (or 1, or Y, ...) RefreshSeconds | 20 ... | ...
J'ai vu les deux options à l'état sauvage, et les deux ont des avantages et des inconvénients évidents, par exemple:
- Les tables à une seule ligne limitent le nombre d'options de configuration que vous pouvez avoir (car le nombre de colonnes dans une ligne est généralement limité). Chaque option de configuration supplémentaire nécessite un changement de schéma de base de données.
- Dans une table de paires nom-valeur, tout est "typé de manière stricte" (vous devez encoder / décoder vos paramètres Boolean / Date / etc.).
- (beaucoup plus)
Existe-t-il un consensus au sein de la communauté du développement sur quelle option est préférable?
Réponses:
Personnellement, je préfère les tables à une seule rangée pour la plupart des choses. Bien que ce soit moins flexible, à moins d’attendre un comportement dynamique, il est parfaitement acceptable d’ajouter des colonnes ultérieurement si vous en avez besoin. En un sens, cela équivaut à utiliser un dictionnaire / une carte pour contenir des paires nom-valeur plutôt que d'avoir des membres de classe lors de la programmation. Certes, ce n’est pas une métaphore parfaite, mais de nombreux avantages et inconvénients sont mis en parallèle lorsque vous y réfléchissez.
Alors, utiliseriez-vous un dictionnaire / une carte sur les membres de la classe? Probablement pas, sauf si vous aviez des raisons de penser que la quantité de données à représenter est entièrement adaptable, un peu comme si vous disposiez d'un tableau de paires nom-valeur.
la source
J'irais généralement avec l'option 2 MAIS j'aurais plusieurs colonnes pour appliquer le type de données
L'option 1 présente l'avantage supplémentaire que vous pouvez très facilement "échanger" des configurations entières en ajoutant une
Active
colonne.la source
activatedOn
horodatage afin que vous puissiez savoir quand l' activation a eu lieu. Et si vous choisissez l'option 2 ... que se passera-t-il si vous finissez par stocker des valeurs dans plusieurs colonnes (ou c'est oracle, où (apparemment) null et une chaîne vide sont équivalents)?Pour moi, que vous choisissiez une seule ligne ou EAV dépend de la façon dont vous voulez les consommer.
Le pouvoir d'EAV réside dans le fait que de nouvelles données peuvent être ajoutées sans changement de structure. Cela signifie que si vous souhaitez une nouvelle valeur de configuration, il vous suffit de l'ajouter à la table et de l'extraire à l'endroit souhaité dans le code. Il n'est pas nécessaire d'ajouter un nouveau champ au domaine, au schéma, au mappage ou aux requêtes DAL. , etc.
Son défaut est qu’il n’a que la structure la plus simple qui soit, ce qui vous oblige à traiter les données avec pessimisme. Toute utilisation d’une valeur de configuration doit s’attendre à ce que la valeur ne soit pas présente, ou au format approprié, et se comporte en conséquence lorsque cela n’est pas le cas. Une valeur de configuration peut ne pas être analysable en double, en int ou en char. Cela peut être nul. il peut ne pas y avoir de ligne pour la valeur du tout. Pour contourner ce problème, il suffit généralement d’une seule valeur "par défaut" valide pour toutes les valeurs de configuration d’un type particulier de code ( extrêmement rare; la valeur par défaut est tout aussi problématique pour la consommation de code), ou pour Conservez un dictionnaire codé en dur des valeurs par défaut (qui doit changer chaque fois qu'une nouvelle colonne est ajoutée, rendant le principal avantage du stockage EAV peu utile).
Une seule rangée large est à peu près le contraire. Vous le mappez sur une seule instance d'un objet de configuration avec un champ / une propriété pour chaque valeur de configuration existante. Vous savez exactement quel type ces valeurs doivent être au moment de la compilation et vous "échouez vite" dans le DAL si une colonne de configuration n'existe pas ou n'a pas une valeur du type approprié, ce qui vous donne un emplacement pour capturer les exceptions en fonction sur les problèmes de récupération / hydratation de la configuration.
Le principal inconvénient est qu'un changement structurel est nécessaire pour chaque nouvelle valeur; nouvelle colonne de base de données, nouvelle colonne dans la couche DAL (le mappage ou les requêtes / SP SQL), nouvelle colonne de domaine, nécessaires pour tester correctement l'utilisation.
La situation appropriée pour utiliser l'un ou l'autre est la situation dans laquelle les inconvénients sont atténués. Pour moi, la plupart des situations de codage de configuration ont nécessité une implémentation à une seule ligne. Cela est principalement dû au fait que si vous introduisez une toute nouvelle valeur de configuration régissant le comportement d'une partie de votre programme, vous devez déjà modifier le code pour utiliser la nouvelle valeur de configuration. pourquoi ne pas aller sur l'objet config et ajouter la valeur à utiliser?
En bref, un schéma EAV pour stocker la configuration ne résout pas vraiment le problème qu’il est censé résoudre, et la plupart des solutions de contournement aux problèmes qu’il présente viole DRY.
la source
Spécifiquement pour les valeurs de configuration, je dirais - aller avec la ligne unique. À moins que vous ne réalisiez actuellement le développement, à quelle fréquence ces colonnes vont-elles changer de toute façon?
Il est probablement préférable de sécuriser le type de données des valeurs plutôt que le code pour une extensibilité que vous ne rencontrerez probablement pas dans le temps mort entre les versions importantes (r). En outre, l'ajout ou la suppression d'une seule colonne est la migration la plus simple qui soit. Je ne prévois pas de maux de tête lors de la création d'une nouvelle option de configuration.
De plus, vous avez dit que les "utilisateurs" peuvent configurer ces options sans donner de plafond. S'agit-il de configurations par utilisateur? Si tel est le cas, je soutiendrai encore plus fortement que les options de configuration devraient figurer dans les colonnes - une seule ligne par utilisateur. Cela vous évitera beaucoup de maux de tête plus tard.
la source
Si vos clients peuvent traiter des fragments JSON (non seulement des tableaux et des dictionnaires, mais également des chaînes, des nombres, des booléens, des valeurs null), vous pouvez avoir un tableau à plusieurs lignes avec le nom de l'option et une valeur de chaîne contenant du JSON. Cela vous permet également de stocker des valeurs structurées, et le code pour les traiter devrait déjà être là.
Si vos clients ne peuvent pas traiter les fragments JSON, procurez-vous de nouveaux clients.
la source
Rangée simple Avantages: bien définis. Inconvénients: Changer la configuration peut être une douleur. Migrations de base de données, etc.
Avantages de l'entité: Super flexible, prend en charge l'évolution de votre configuration. Inconvénients: intégrité référentielle? Plus de contrôles dans votre code pour voir si la propriété existe avant que vous puissiez faire quoi que ce soit dessus.
Je prendrais l'approche 2 soutenue par une base de données non relationnelle comme Mongo. S'il y a quelque chose dont vous pouvez être sûr, c'est son changement.
la source
Utilise les deux!
Triez les options pouvant avoir plusieurs instances et les options génériques.
La table simple rangée (configurations)
La table de paires nom-valeur (options)
Je pense que c'est plus flexible.
la source