IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Comment bien gêrer des tables de données constantes


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut Comment bien gêrer des tables de données constantes
    Bonjour à tous !

    Je travailles actuellement sur un projet qui m'a amené à la question suivante : "Comment bien gêrer les tables de données constantes ?".

    Je m'explique. Prenons le cas d'une personne. Une personne peut forcemment être soit un homme soit une femme. Elle a aussi en général une catégorie socio-professionnel par exemple. Elle habite aussi dans une ville. (J'essaie d'exagerer le tout pour voir les différents cas de figures).

    De mon point de vue, je créerais un namespace pour chaque cas avec un énum, comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    namespace Gender 
    {
    enum{Homme=1, Femme =2}
    }
     
    namespace SocioProf
    {
    enum{Liberal=1,Medecin=2, Policier=3}
    }
    namespace Ville
    {
    enum{Paris=1,Marseille=2,Lyon=3}
    }
    Je pense qu'on est d'accord pour dire que dans le cas des villes, la structure est mauvaise car il y a trop de possibilités à prendre en compte.
    J'en appelle à vous pour me dire comment gêrer le mieux possible ce type de données.
    Merci d'avance

  2. #2
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 254
    Points : 538
    Points
    538
    Par défaut
    Faire un objet. La programmation objet est l'une des plus intuitives, justement parce qu'elle permet de transcrire des situation réelle en programme en utilisant virtuellement ce qu'on utilise physiquement : des objets.

    Tu pourrais peut-être faire la chose suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class        Person
    {
     private:
      std::string  firstName;
      std::string  lastName;
      eSex         sex;
      std::string  city;
      ...
    }
    Et ça te constitue une personne.
    "L'insanité consiste à répéter la même action dans l'espoir d'aboutir à un résultat différent" Albert Einstein
    ----------------------
    T.O.A.O 6-MarViN

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Je suis complètement d'accord avec toi 6-MarViN. Pour représenter une personne en C++, l'objet reste le meilleur choix. Cependant le sujet du post n'est pas là. J'ai du mal m'exprimer .

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class        Person
    {
     private:
      std::string  firstName;
      std::string  lastName;
      eSex         sex;
      std::string  city;
      ...
    }
    Ceci est une bonne description d'une personne. Mais si on a besoin de limiter les valeurs possibles de sex et city par exemple, il est nécessaire de définir un tableau des valeurs possibles. La question est de savoir comment bien définir en C++ ces tableaux là, en fonction de nombre de possibilités.

    Pour le sexe, comme il n'y a que 2 cas possibles, un enum suffira. Mais comment faire si l'on commence à avoir beaucoup de possibilité ??

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Ben dans le cas de la ville, il faut utiliser un string, et pas un enum.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 254
    Points : 538
    Points
    538
    Par défaut
    Citation Envoyé par gilims Voir le message
    La question est de savoir comment bien définir en C++ ces tableaux là, en fonction de nombre de possibilités.

    Pour le sexe, comme il n'y a que 2 cas possibles, un enum suffira. Mais comment faire si l'on commence à avoir beaucoup de possibilité ??
    Et ben tu fais un tableau de tout les diables avec toutes les possibilités.

    Honnêtement a part définir toutes les possibilités, je vois mal comment tu pourrais procéder.
    "L'insanité consiste à répéter la même action dans l'espoir d'aboutir à un résultat différent" Albert Einstein
    ----------------------
    T.O.A.O 6-MarViN

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par gilims Voir le message
    Mais comment faire si l'on commence à avoir beaucoup de possibilité ??
    Salut

    Je trouve ce post intéressant, car il soulève plusieurs problèmes. enum n'est pas adapté pour les grandes plages de valeur, et surtout enum ne permet de ne représenter que des entiers non signés en mémoire, ce qui est quand même très limitant. Souvent, ce genre de problème est résolu par l'usage d'une base donnée. Les données sont stockées dans une table et on ne peut ne stocker dans les objets qu'une référence à l'entrée correspondante dans la table.

    Si on aborde la chose d'un point de vue programme standalone, il vaut mieux utiliser une véritable structure de donnée runtime que l'on remplira au moment opportun. Une fois ce postulat effectué, il reste plusieurs problématiques :

    Comment gérer l'accès à la table ?

    Avec un enum, l'include du header suffit. Mais avec une donnée construite au runtime, ce n'est pas possible. On a vite fait de tomber dans le piège de l'accès global et d'écrire un singleton. Une solution possible est d'avoir :

    - Une classe qui représente une grande table de valeurs possibles
    - Une factory pour les personnes qui a un membre du type de la classe précédente.
    - En option, un objet table partagé par toutes les personnes.

    Comment maintenir la table ?

    La table va sûrement évoluer et s'enrichir. De plus, il serait idéal de découpler la compilation et le contenu de la table. On peut donc par exemple stocker la liste des entrées possibles dans un fichier.

    Comment stocker la donnée pour chaque personne ?

    Comme le dit oodini : il faut utiliser, pour une ville, le même type que la donnée stockée, soit std::string. Il suffit alors de faire des vérifications de cohérence avec la table lorsque c'est nécessaire. Il ne faut pas stocker l'index (comme on le ferait avec une base de donnée), car il peut se décaler quand la table va évoluer.
    Find me on github

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Citation Envoyé par 6-MarViN Voir le message
    Et ben tu fais un tableau de tout les diables avec toutes les possibilités.

    Honnêtement a part définir toutes les possibilités, je vois mal comment tu pourrais procéder.
    On est forcemment obligé à un moment ou un autre de définir toutes les villes, on est d'accord.

    - Une classe qui représente une grande table de valeurs possibles
    - Une factory pour les personnes qui a un membre du type de la classe précédente.
    - En option, un objet table partagé par toutes les personnes.
    Je n'ai jamais entendu parler de factory auparavant. Aurais-tu quelques liens à me transmettre à ce sujet. J'ai chercher sur Google mais j'ai trouvé que sur le design pattern factory. C'est ca ??

    De plus, il serait idéal de découpler la compilation et le contenu de la table.
    A partir de quelques quantités de données vaut-il mieux passer en données externes (via un fichier) plutot qu'en interne?

    Comme le dit oodini : il faut utiliser, pour une ville, le même type que la donnée stockée, soit std::string. Il suffit alors de faire des vérifications de cohérence avec la table lorsque c'est nécessaire. Il ne faut pas stocker l'index (comme on le ferait avec une base de donnée), car il peut se décaler quand la table va évoluer
    Je suis d'accord, mais seulement dans le cas où les données sont externes. Si elles sont enregistrées lors de la compilation, l'index n'est pas censé changer.

    De mon coté, j'avais fait l'erreur (de jeunesse dira-t-on ) de créer une structure de donnée constante dans un header contenant mes informations. Je recopiais donc pour chaque personne les informations contenues dans la structure plutot que juste garder l'index dans l'objet "personne" et récupérer directement la valeur dans la structure de donnée.
    Rassurer moi juste en me confirmant que c'est une erreur de faire ca

    J'ai donc deux questions me venant à l'esprit :
    Quel est le cout en :
    1. performance à l'execution
    2. temps de compilation
    3. taille de l'executable
    4. cout mémoire
    des cas de figures suivant :
    1. Une énumeration
    2. Une structure de données constante définit dans un header
    3. Un fichier externe
    en extrapolant sur des cas généraux/


    Comment correctement gérer des données plus complexes ?

    Pour mieux situer la problématique, je travaille sur des acides aminés. Chacun possède un nom, une lettre, un poids, un certain nombre d'atome, des propriétés pour chaque atome (qui diffère en fonction des acides aminés), etc etc. Il y en a 22 de bases, plus les acides aminés modifiés que je devrais rajouter au compte goutte. Au final j'essaie de comprendre comment manipuler au mieux ces données là.

    Merci encore

  8. #8
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Salut.

    Citation Envoyé par gilims Voir le message
    Je n'ai jamais entendu parler de factory auparavant. Aurais-tu quelques liens à me transmettre à ce sujet. J'ai chercher sur Google mais j'ai trouvé que sur le design pattern factory. C'est ca ??
    C'est bien ça.
    Tu peux déjà aller voir ce tutoriel: Présentation des principaux design patterns en C++

  9. #9
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par gilims Voir le message
    J'ai chercher sur Google mais j'ai trouvé que sur le design pattern factory. C'est ca ??
    Oui je parlais bien du design pattern factory.

    Citation Envoyé par gilims Voir le message
    Je suis d'accord, mais seulement dans le cas où les données sont externes. Si elles sont enregistrées lors de la compilation, l'index n'est pas censé changer.
    Non, ce n'est pas tout à fait ça. En fait, tu peux stocker l'index si la liste n'évolue pas pendant toute la durée de vie de l'objet personne. Si tu fais de la persistance sur cet objet (stockage dans un fichier), tu comprend qu'il va falloir penser le problème un peu mieux.

    Pour les perfos : Au niveau de la comparaison en terme de perfos, et bien... difficile de te répondre sans mieux connaître ton programme ni la taille des données manipulées. Tu as vraiment des contraintes en terme de perfs et de taille de l'exécutable ? Vu le sujet, ça ne ressemble pas à de l'embarqué.
    Find me on github

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    C'est bien ça.
    Tu peux déjà aller voir ce tutoriel: Présentation des principaux design patterns en C++
    Ok, je vais regarder ca de plus près.

    Non, ce n'est pas tout à fait ça. En fait, tu peux stocker l'index si la liste n'évolue pas pendant toute la durée de vie de l'objet personne. Si tu fais de la persistance sur cet objet (stockage dans un fichier), tu comprend qu'il va falloir penser le problème un peu mieux.
    Si le fichier est externe, il vaut mieux ne pas utiliser l'index on est d'accord.
    Mais recopier toutes les données relative à la personne dans son objet n'est pas forcemment mieux. En particulier si l'on a beaucoup de personnes à gêrer.


    Pour les perfos : Au niveau de la comparaison en terme de perfos, et bien... difficile de te répondre sans mieux connaître ton programme ni la taille des données manipulées. Tu as vraiment des contraintes en terme de perfs et de taille de l'exécutable ? Vu le sujet, ça ne ressemble pas à de l'embarqué.
    Non ce n'est pas de l'embarqué en effet. Mais ce problème là s'inscrit dans les "couches de bases" d'un plus gros projet. Si déjà c'est mal géré dès le départ, la suite ne tiendra pas.

  11. #11
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par gilims Voir le message
    Si le fichier est externe, il vaut mieux ne pas utiliser l'index on est d'accord.
    Mais recopier toutes les données relative à la personne dans son objet n'est pas forcemment mieux. En particulier si l'on a beaucoup de personnes à gêrer.
    Tu n'as pas compris ce que je voulais dire. Bien sûr qu'il ne faut pas recopier les listes dans chaque personne ! Ce que je veux dire, c'est que si tu ne crées des objets personnes qu'à partir de rien au runtime, peu importe que la liste soit dans un fichier ou pas, puisque les objets personnes seront reconstruits (avec les bon indexs) à chaque exécution. Tu vas pas t'amuser à modifier ta liste pendant l'exécution, du moins je pense pas que tu aies ce besoin.

    Citation Envoyé par gilims Voir le message
    Non ce n'est pas de l'embarqué en effet. Mais ce problème là s'inscrit dans les "couches de bases" d'un plus gros projet. Si déjà c'est mal géré dès le départ, la suite ne tiendra pas.
    Early optmization is the root of all evil. Si tu fais un design propre dès le départ, tu identifieras facilement à l'avenir les goulots d"étranglements qui peuvent être améliorés, et tu pourras le faire facilement car ton beau design aura bien découplé les problématiques . Typiquement, on va déléguer la gestion de la structure de donnée à un objet dédié. Si tu dois changer ta technique, il te suffira de modifier l'implémentation de cet objet sans avoir à repenser les autres.

    Edit : je vais te faire une propal de design sur laquelle on pourra discuter.
    Find me on github

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 53
    Points : 24
    Points
    24
    Par défaut
    Bien sûr qu'il ne faut pas recopier les listes dans chaque personne ! Ce que je veux dire, c'est que si tu ne crées des objets personnes qu'à partir de rien au runtime, peu importe que la liste soit dans un fichier ou pas, puisque les objets personnes seront reconstruits (avec les bon indexs) à chaque exécution. Tu vas pas t'amuser à modifier ta liste pendant l'exécution, du moins je pense pas que tu aies ce besoin.
    Si si, j'ai bien compris ca . Je me suis juste mal exprimé . Mais je suis totalement en accord.

    Early optmization is the root of all evil. Si tu fais un design propre dès le départ, tu identifieras facilement à l'avenir les goulots d"étranglements qui peuvent être améliorés, et tu pourras le faire facilement car ton beau design aura bien découplé les problématiques .
    Encore d'accord. En réalité ce n'est pas une "Early optmization" car cela s'inscrit dans une réécriture de mon toolkit. J'essaie juste, à partir du retour sur expérience, d'améliorer le concept.

    Typiquement, on va déléguer la gestion de la structure de donnée à un objet dédié. Si tu dois changer ta technique, il te suffira de modifier l'implémentation de cet objet sans avoir à repenser les autres.
    Dans mon cas, je gérais mes données d'acides aminés sous la forme de const struct, et la gestion des acides aminés (AA) de mes protéines (donc issues de l'execution du programme) sous la forme de structure. Mais il s'est avéré que c'était bien trop limitant. Maintenant j'ai redéfinit la gestion des AA sous la forme d'une classe mais les informations concernant les AA étant plus importante que prévu, j'essaie de comprendre comment les définir au mieux. (Je suis pas sur d'avoir été très clair pour le coup ...)

  13. #13
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Ta structure a l'air assez compliquée, mais je vais rester centré sur le problème de base du post.

    Voici une proposition assez complète avec plein de concepts pour que tu poses plein de questions. Ma propal présente néanmoins quelques défauts :
    - Pas de gestion des erreurs/problèmes. A rajouter toi même, je t'ai quand même fait du RAII dans la mesure du possible.
    - Je t'ai mis un pâté de code, c'est à toi de découper ça en headers et en .cpp.
    - Il faut utiliser la même factory pour tout le monde sous peine de duplication de données. Je ne suis pas sûr que ce soit vraiment un défaut, si quelqu'un a un meilleur design à proposer, je suis tout ouï !

    Fichier villes.txt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Paris
    Marseille
    Lyon
    Nice
    Nancy
    Metz
    Toulouse
    Azelot
    Fichier Test.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    #include <fstream>
    #include <string>
    #include <vector>
    #include <exception>
    #include <boost/smart_ptr/shared_ptr.hpp>
    #include <boost/smart_ptr/scoped_ptr.hpp>
     
    class Enumerations
    {
      std::vector< std::string > m_villes;
     
    public:
      Enumerations()
      {
        std::ifstream fichierVilles("villes.txt");
        if(fichierVilles)
        {
          std::string ligne;
          while(std::getline(fichierVilles, ligne))
            m_villes.push_back(ligne);
        }
        else
        {
          throw std::exception("Le fichier de villes ne peut être ouvert");
        }
      }
     
      virtual ~Enumerations()
      {
      }
     
      std::vector< std::string > const & getListVilles()
      {
        return m_villes;
      }
    };
     
    class Personne
    {
      /**
      * Seule la factory pourra créer des objets "Personne" grâce à l'amitié
      * et à la limitation d'accès au constructeur
      */
      Personne(boost::shared_ptr< Enumerations > donnees) : m_enums(donnees), m_ville(0)
      {}
      friend class PersonneFactory; 
     
      /**
      * Objet de liste partagé
      */
      boost::shared_ptr< Enumerations > m_enums;
     
      /**
      * On peut prendre un index grâce à deux hypothèses :
      * - La liste de ville ne change pas au cours de l'exécution
      * - Les objets personnes sont détruits à la fin et non persistants
      */
      size_t m_ville;
     
    public:
      virtual ~Personne()
      {}
     
      void setVille(std::string const & ville)
      {
        std::vector<std::string> const & m_liste = m_enums -> getListVilles();
        m_ville = std::find(m_liste.begin(), m_liste.end(), ville) - m_liste.begin();
      }
     
      std::string const & getVille()
      {
        return m_enums -> getListVilles()[m_ville];
      }
    };
     
    class PersonneFactory
    {
      boost::shared_ptr< Enumerations > m_enums;
     
    public:
      PersonneFactory() : m_enums(new Enumerations)
      {
      }
     
      Personne * CreerPersonne()
      {
        return new Personne(m_enums);
      }
    };
     
    int main(int argc, char* argv[])
    {
      // On teste tout ce beau monde
      PersonneFactory maFactory;
     
      boost::scoped_ptr< Personne > personne1(maFactory.CreerPersonne());
      boost::scoped_ptr< Personne > personne2(maFactory.CreerPersonne());
     
      personne1 -> setVille("Marseille");
      personne2 -> setVille("Azelot");
     
      std::cout << "Ville de Personne 1 : " << personne1 -> getVille() << std::endl;
      std::cout << "Ville de Personne 2 : " << personne2 -> getVille() << std::endl;
     
      return 0;
    }
    Les stratégies choisies sont discutables. Par exemple, dans cette proposition, setVille sera peu efficace car il faut chercher dans la liste, mais en échange, les objets Personne sont petits en mémoire et tu peux donc bourriner et en utiliser plein. Il y a des tas de manières de faire !

    Edit : Je n'ai pas créé deux types pour les personnes (un type abstrait et un type concret) comme on doit le faire dans le DP Factory idéal. J'ai préféré utiliser l'amitié.
    Find me on github

Discussions similaires

  1. Comment gérer des bases de données multimédia ?
    Par pidlas dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 31/05/2013, 11h25
  2. Comment BIEN gérer des threads?
    Par klakman dans le forum Threads & Processus
    Réponses: 9
    Dernier message: 24/12/2010, 18h34
  3. Comment bien documenter des bases de données
    Par DEV-10 dans le forum Modélisation
    Réponses: 19
    Dernier message: 16/01/2008, 21h37
  4. [JDesktopPane] Comment bien gérer les JInternalFrame ?
    Par calogerogigante dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 05/04/2006, 12h45
  5. Réponses: 12
    Dernier message: 02/03/2006, 14h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo