La meilleure façon de référencer des données de base de données statiques dans le code?

24

De nombreuses applications incluent des «données statiques»: des données qui ne changent pas vraiment pendant la durée de vie de l'application. Par exemple, vous pourriez avoir une liste de zones de vente qui sera probablement une liste fixe dans un avenir prévisible.

Il n'est pas rare de trouver ces données statiques dans une table de base de données (souvent parce que vous voulez vous y référer dans les clés étrangères d'autres tables). Un exemple de table simple aura un identifiant à utiliser comme clé primaire et une description. Par exemple, votre table SalesArea aura (au moins) une colonne SalesAreaId et une colonne SalesAreaDescription.

Maintenant, dans le code, vous ne voudrez peut-être pas traiter chaque ligne de la même table. Par exemple, vous souhaiterez peut-être définir une zone de vente par défaut sur certains écrans, fournir des chiffres différents pour certaines zones ou restreindre ce que les utilisateurs peuvent faire dans d'autres zones.

Quelle est la meilleure façon de faire référence à ces données statiques dans le code? Pourquoi?

  1. Codez en dur les descriptions de votre code. Utilisez-le pour rechercher SalesAreaId dans la base de données lorsque vous en avez besoin.
  2. Codez en dur les identifiants de votre code. Utilisez-le pour rechercher la description SalesArea lorsque vous en avez besoin.
  3. Ajoutez une colonne à la table pour chaque objectif, par exemple une colonne "IsDefaultOnProductLaunchScreen" et ainsi de suite (il pourrait y en avoir beaucoup).
  4. Autre chose.

Y a-t-il d'autres considérations spéciales à prendre en compte lorsque je traite des données de base de données statiques? Par exemple, donner à ces tables un nom spécial?

Kramii Reinstate Monica
la source
1
Duplicata possible: programmers.stackexchange.com/questions/304169/… Je pense que les réponses sur celui-ci (lié)
vont

Réponses:

14

Que diriez-vous de les charger dans un cache (généralement implémenté comme une table de hachage) au démarrage de l'application? Si vous faites cela, vous n'avez même pas à interroger la base de données (enfin, pas plus d'une fois).

Je suggère également d'éviter tout codage en dur. Ajoutez des indicateurs par défaut (initialement dans la table DB et également dans la structure du cache) pour les écrans qui nécessitent des valeurs par défaut. Pour effectuer des recherches sur des non-défauts, essayez de stocker les clés qui seront recherchées dans un fichier de configuration ou de propriétés si vous le pouvez.

FrustratedWithFormsDesigner
la source
La mise en cache est bonne bien sûr, mais comment mettre à jour ces valeurs? Vraisemblablement un redémarrage de l'application ou une sorte de stratégie d'invalidation du cache?
Steve
1
@Steve Oui, exactement. Dépend de l'application. Le redémarrage est bon pour quelque chose qui démarre fréquemment. Pour une application de longue durée, rechargez peut-être le cache une fois par jour pendant les périodes lentes. Ma question serait, qu'en est-il d'un scénario où l'application s'exécute de nombreuses durées très courtes. Comme, peut-être un script PHP ou quelque chose de similaire.
tylermac
La base de données exécutera son propre cache pour les données fréquemment consultées, vous allez donc réimplémenter quelque chose qui est déjà implémenté (et probablement pas aussi bien!)
James Anderson
@JamesAnderson: Mise en cache les moyens d'application , il ne sera jamais être un appel à la base de données. Oui, les bases de données auront leurs propres caches, mais ceux-ci peuvent être invalidés / actualisés par des événements indépendants de la volonté de votre application, et vous devez toujours avoir une connexion à la base de données et effectuer une requête pour obtenir ces données (et espérons qu'elles se trouvent dans le cache de db). Ce n'est vraiment pas si difficile d'implémenter un simple cache intégré à l'application.
FrustratedWithFormsDesigner
7

Une alternative à la base de données ou au codage en dur consiste à utiliser un fichier de configuration lu au moment du démarrage. Vous pouvez ensuite stocker ces données dans une structure en lecture seule dans votre code.

Dans le cas rare (mais pas impossible) où vous modifiez ces données, vous devrez redémarrer l'application. Si cela n'est pas possible, vous pouvez écrire un gestionnaire de configuration plus complexe qui vérifie les changements dans le fichier de configuration à chaque fois que les données sont accédées, cela est en fait assez efficace car il vous suffit de vérifier un horodatage sur le fichier, puis d'invalider toutes les données si le fichier est mis à jour.

Steve
la source
1
Bonne idée pour certains types de données statiques, mais pas si bonne si vous souhaitez appliquer les relations FK comme décrit dans la question.
Kramii Reinstate Monica
La question ne disait pas que c'était une exigence, seulement un scénario. Si ce n'est pas nécessaire, l'approche du fichier de configuration fonctionne bien.
Steve
Tu as raison, je n'étais pas assez clair. Mais je suis content ... parce que j'ai appris quelque chose de votre réponse. Je n'ai jamais rencontré cette approche auparavant.
Kramii Reinstate Monica
3

Si les données se rapportent à des données existantes dans votre base de données, il est probablement aussi efficace de les ajouter à la base de données que de les ajouter au code. Si ce n'est pas le cas, je suis généralement tenté de «prendre cette balle une fois» et de la mettre en code jusqu'à la première modification.

Souvent, ce que nous pensons être statique s'avère ne pas l'être, et lorsque cela se produit, vous ne voulez pas avoir à attendre la publication d'un code pour qu'un changement soit effectué. Dès que cela se produit une fois, mettez-le dans la base de données et écrivez une page d'administrateur pour effectuer d'autres mises à jour.

Pour prendre votre exemple, si vous avez déjà des zones de vente dans la base de données, ajoutez-y une description, ne créez pas de table de hachage pour relier les données de la base de données aux listes codées en dur. Mais si vous ne créez pas une table de hachage des zones de vente par tous les moyens, mais soyez prêt, la première fois que quelqu'un modifie une description ou ajoute une nouvelle zone de vente, déplacez-la dans la base de données.

pdr
la source
"Souvent, ce que nous pensons être statique s'avère ne pas l'être" - c'est vrai.
Kramii Reinstate Monica
3

Pourquoi ne pas tout coder en dur? Le principal problème que j'ai toujours eu est de référencer des valeurs statiques de la base de données dans le code d'application. C'est une chose si vous créez directement une liste déroulante ou quelque chose à partir de valeurs statiques, mais que se passe-t-il si une logique d'application dépend des valeurs de la base de données?

Dans une application simple, j'ai actuellement une liste d'états d'édition pour des éléments de contenu: brouillon, publié, archivé.

Les éléments de contenu doivent être traités différemment selon l'état dans lequel ils se trouvent. Si je devais conserver ces données d'état dans la base de données, avec les valeurs 1, 2, 3, respectivement, comment pourrais-je vérifier si quelque chose se trouve dans le brouillon Etat?

if (content.State == 1)
ou
if (content.State == "Draft")?

Je viens de coder en dur les valeurs!
Même chose si vous utilisez une table de cache / hachage: vous devez toujours utiliser une valeur écrite dans votre code comme clé pour rechercher vos données.

Quels sont les inconvénients de l'approche de codage en dur?

Dave
la source
L'inconvénient est comme l'a dit pdr, "Souvent, ce que nous pensons être statique s'avère ne pas l'être".
tylermac
2
Mais si vous faites réellement référence aux valeurs de données statiques dans le code, vous ne pouvez pas les modifier dans la base de données sans interrompre l'application. Bien sûr, cela dépend de l'utilisation des données: comme je l'ai mentionné ci-dessus, s'il s'agit simplement de remplir un élément d'interface utilisateur afin qu'un utilisateur puisse sélectionner une valeur et la rediriger directement vers la base de données dans le cadre d'un enregistrement dans une autre table , les données statiques de la base de données peuvent changer indépendamment du code d'application. Je suis presque sûr que c'est la situation dont parle @pdr: l'application qui gère l'ensemble des données statiques comme un seul élément.
Dave
2

Semblable à ce que FrustratedWithFormsDesigner a dit, cela se fait généralement avec un cache, car cela signifie que vous ne devez charger les données statiques qu'une seule fois, mais il suit le modèle OAOO, ce qui signifie que nous ne définissons pas les données à deux endroits (base de données et dans votre code).

Je sais que le NHibernate ORM offre cette fonctionnalité via un cache de deuxième niveau . Vous pouvez lui dire de mettre en cache les données d'une certaine table et dire qu'il est en lecture seule. Il sera chargé la première fois qu'il sera requis et ne frappera plus la base de données après cela, même si vous accédez aux données de plusieurs sessions.

Scott Whitlock
la source
+1 pour Once and Only Once. Mais qu'en est-il du traitement différent des différentes lignes?
Kramii Reinstate Monica
1
@Kramii - Vous pouvez utiliser quelque chose comme des classes d'énumération . Si les métadonnées ne concernaient que votre programme, je mettrais la logique métier ( IsDefaultOn...) dans une propriété de l'entité. Faites-le revenir vrai pour la seule entité. Cela vous permettrait de trouver cette entité, compte tenu de l'ensemble de la collection. Ou vous pouvez utiliser une classe de contrôleur qui vous fournira l'entité appropriée avec un appel de méthode.
Scott Whitlock
2

C'est l'optimisation prématurée à son pire.

Tout d'abord, tout SGBD moderne récupérera les données de petites tables à une vitesse fulgurante et ils ont tous des algorithmes de mise en cache allant de bons à superbes (plus vous avez payé pour le SGBD, meilleur est le cache!). Vous optimisez donc quelque chose qui consomme un minimum de ressources.

Deuxièmement, vous avez très peu d'expérience des applications commerciales réelles si vous imaginez que quelque chose comme une «zone de vente» est constituée de données statiques. Ceux-ci sont susceptibles de changer à chaque changement de directeur marketing ou PDG. Vous vous dirigez donc vers un monde de douleur deux ans plus tard.

Il n'y a que deux façons d'aller ici: -

Stockez-le dans une base de données et accédez aux données avec sql "normal".

Stockez-le dans un fichier de configuration XML sophistiqué (éventuellement accessible via REST ou SOAP) qui peut être facilement modifié chaque fois qu'il y a "un changement stratégique de politique".

James Anderson
la source
1

Cela dépend de ce que vous faites avec les données. S'il s'agit d'une liste de quelque chose, je le tire généralement dans un tableau. Si la liste doit s'allonger dans une autre version, il est facile d'ajouter simplement à la base de données et de modifier le code pour gérer les données supplémentaires dans le tableau (ce qui peut même ne pas être nécessaire en fonction du code, par exemple lister les données avec un pour la boucle en utilisant la limite supérieure du tableau). S'il s'agit d'une liste de paramètres, je coderai généralement ceux-ci car ils ne sont généralement pas nombreux et sont plus faciles et plus rapides que l'utilisation d'une instruction SQL. S'il s'agit d'un paramètre que l'utilisateur peut modifier et que je souhaite enregistrer la sélection pour les lancements ultérieurs, je vais créer une table à utiliser comme registre et extraire simplement les entrées individuelles des variables selon les besoins.

MaQleod
la source
1

Je sais que cette réponse a été acceptée mais je voulais partager comment nous l'avons fait dans ma dernière boutique de développement Web où nous avons essayé de réduire autant que possible les E / S de la base de données.

Nous avons utilisé des fichiers d'inclusion côté serveur pour autant de structures de données de type recherche que possible. Il s'agissait principalement de navigation sur le site (pour inclure la sous-navigation) mais nous l'avons également utilisé pour autant de listes déroulantes et de cases à cocher que possible (États, pays, catégories).

À l'origine, nous tirions toutes ces données de la base de données. Étant donné que nous avons donné au client un widget d'administration, il pouvait modifier ces données à volonté et nous ne nous sommes jamais enlisés avec de petits changements. La plupart du temps, ces données n'ont pratiquement jamais changé, mais elles changeraient occasionnellement.

Nous recherchions toujours des temps de chargement plus rapides. Nous avons donc décidé d'implémenter autant de fichiers texte statiques côté serveur que possible. Nous l'avons fait dans le widget d'administration. Chaque fois qu'une table de base de données était mise à jour, nous régénérions le fichier texte statique correspondant. Cela nous a donné un environnement très flexible et rapide.

Michael Riley - AKA Gunny
la source
0

Ma solution à cela, qui peut ne pas fonctionner dans toutes les situations, est de lier les données de la base de données statiques à un code dur enum. Comme le problème vient du fait que les données dynamiques (base de données) sont liées à la logique statique (code), rendez cette liaison explicite (et lâche) en ayant une table de base de données qui s'associe à enum. Ex:

LooseDBCodeBinding (database table)
   ID : Int32 (key)
   Name : String
   HardCodedTypeID : Int32

// in code:
public enum LooseDBCodeBinding
{
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3 // etc...
}

Ensuite, écrivez une interface utilisateur qui vous permet de visualiser facilement la liste des LooseDBCodeBindingenregistrements et de les mapper à des LooseDBCodeBinding enumvaleurs (y compris la prise en charge des liaisons "rompues"). Vous pouvez ensuite programmer autour de enum, et concevoir la base de données autour de la clé de table, et c'est juste cette table qui a connaissance des deux contextes.

Dave Cousineau
la source