Garder en mémoire les options d'un programme

Garder en mémoire les options d'un programme - C++ - Programmation

Marsh Posté le 25-05-2003 à 15:33:40    

Salut,
 
alors là je fais appel à ceux qui ont déjà codé un logiciel...
 
Je me demandais quelle méthode vous aviez choisi pour accéder aux options de votre programme quand ce dernier est lancé...
 
Je m'explique: en général les options sont enregistrées dans un fichier. (INI ou XML généralement)
 
Mais quand le programme est lancé et qu'il vous faut récupérer des options, à chaque fois vous faites un appel au fichier, ou bien au lancement du programme vous enregistrez toutes vos options en mémoire (et dans ce cas, sous quelle forme en mémoire: tableau, une variable par option?) ?
 
Voilà tout...
 
Merci d'avance


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 15:33:40   

Reply

Marsh Posté le 25-05-2003 à 15:45:23    

haazheel a écrit :

Salut,
 
alors là je fais appel à ceux qui ont déjà codé un logiciel...
 
Je me demandais quelle méthode vous aviez choisi pour accéder aux options de votre programme quand ce dernier est lancé...
 
Je m'explique: en général les options sont enregistrées dans un fichier. (INI ou XML généralement)
 
Mais quand le programme est lancé et qu'il vous faut récupérer des options, à chaque fois vous faites un appel au fichier, ou bien au lancement du programme vous enregistrez toutes vos options en mémoire (et dans ce cas, sous quelle forme en mémoire: tableau, une variable par option?) ?
 
Voilà tout...
 
Merci d'avance


je dirai que ca depend de tes variables. Si tu as 50 entiers comme options, un tableau d'entier semble etre une bonne solution mais si tu as 1 entier, une chaine de char et une structure, ben met tout ca dans des variables normales.

Reply

Marsh Posté le 25-05-2003 à 16:20:37    

ouais, ça ok, merci
 
Mais ce que je voulais savoir, c'est s'il vaut mieux stocker les options dès le début du programme et y accéder en mémoire, ou bien à chaque fois aller chercher l'option dans le fichier...


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 16:25:32    

haazheel a écrit :

ouais, ça ok, merci
 
Mais ce que je voulais savoir, c'est s'il vaut mieux stocker les options dès le début du programme et y accéder en mémoire, ou bien à chaque fois aller chercher l'option dans le fichier...


ca depend du nombre d'acces [:spamafote]
bcp d'acces , tu stokes sinon tu vas lire

Reply

Marsh Posté le 25-05-2003 à 16:27:06    

Dans le cas du ini, j'ai une structure en mémoire que je lis depuis le ini au démarrage et que je vais écrire à la fermeture.
Dans le cas du xml, soit je fais comme le ini, soit je lis le fichier au démarrage puis j'accède au DOM directement (enfin, avec une classe qui sert d'intermédiaire pour ne pas devoir taper les noms des tags partout dans le soft :D).


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 25-05-2003 à 16:51:21    

antp a écrit :

Dans le cas du xml, soit je fais comme le ini, soit je lis le fichier au démarrage puis j'accède au DOM directement (enfin, avec une classe qui sert d'intermédiaire pour ne pas devoir taper les noms des tags partout dans le soft :D).


 
Et comment tu fais ça?
 
Ca m'interresse pas mal cette idée... Surtout cette classe intermédiaire: j'utilise beaucoup les XML et si ça peut me faciliter la vie! :D


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 17:11:11    

Personnellement, une classe singleton appele Configuration comprenant comme attrribut la configuration du logiciel dans ses differents attributs. Lorsque l'on l'intancie, elle commence par valuer tous ses paramètres avec les valeurs par defaut, puis elle va lire la configuration (peu importe que ce soit dans un ini, un XML ou autre chose). Avec cette configuration, elle modifie ses atrtributs avec les elements lus dans le fichiers.
 
Lorsque je veux un parametre de configuration, je fait :  

Code :
  1. Configuration *conf = Configuration::getInstance ();
  2. monParam = conf->getMonPAram ();


 
Et hop \o/ (on peut également ajouter une operation save pour refaire le ficheier de conf en quittant pour la garder).
Enfin, je suis assez conjtre le fait de relire la configuration sur le disque a chaque acces, plus pour une méfiance vis a vis d'un fichier risquant d'etre modifié par des evenements externes que pour des raisons de performances.

Reply

Marsh Posté le 25-05-2003 à 17:15:15    

haazheel a écrit :


 
Et comment tu fais ça?
 
Ca m'interresse pas mal cette idée... Surtout cette classe intermédiaire: j'utilise beaucoup les XML et si ça peut me faciliter la vie! :D  


 
En fait j'avais pas fait attention au fait que c'est un topic C/C++ :D
Je programme en Delphi, je le fais avec des propriétés "indexées" qui redirigent toutes vers une même fonction. J'ai un tableau de chaînes contenant les tags, et des tableaux de chaînes, entier et booléens pour les valeurs par défaut. Selon l'index je sais quel tag lire. Le fait que ce soit une chaîne, un entier ou un booléen est déterminé par le type de la propriété
 
ex:

Code :
  1. property ToolbarSkin: Integer index 0 read GetOptionIntegerIndex write SetOptionIntegerIndex;
  2.     property ToolbarIconSet: string index 1 read GetOptionStringIndex write SetOptionStringIndex;
  3.     property ToolbarColorType: Integer index 2 read GetOptionIntegerIndex write SetOptionIntegerIndex;
  4.     property ToolbarClassic: Boolean index 3 read GetOptionBooleanIndex write SetOptionBooleanIndex;


Code :
  1. function GetOptionStringIndex(const Index: Integer): string;
  2.     procedure SetOptionStringIndex(const Index: Integer; const Value: string);
  3.     function GetOptionIntegerIndex(const Index: Integer): Integer;
  4.     procedure SetOptionIntegerIndex(const Index: Integer; const Value: Integer);
  5.     function GetOptionBooleanIndex(const Index: Integer): Boolean;
  6.     procedure SetOptionBooleanIndex(const Index: Integer; const Value: Boolean);


 
Normalement y a moyen de faire tout ça en C++Builder je pense... mais évidemment c'est pas portable du tout.


Message édité par antp le 25-05-2003 à 17:19:43

---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 25-05-2003 à 18:09:39    

kadreg a écrit :

Personnellement, une classe singleton appele Configuration comprenant comme attrribut la configuration du logiciel dans ses differents attributs. Lorsque l'on l'intancie, elle commence par valuer tous ses paramètres avec les valeurs par defaut, puis elle va lire la configuration (peu importe que ce soit dans un ini, un XML ou autre chose). Avec cette configuration, elle modifie ses atrtributs avec les elements lus dans le fichiers.
 
Lorsque je veux un parametre de configuration, je fait :  

Code :
  1. Configuration *conf = Configuration::getInstance ();
  2. monParam = conf->getMonPAram ();


 
Et hop \o/ (on peut également ajouter une operation save pour refaire le ficheier de conf en quittant pour la garder).
Enfin, je suis assez conjtre le fait de relire la configuration sur le disque a chaque acces, plus pour une méfiance vis a vis d'un fichier risquant d'etre modifié par des evenements externes que pour des raisons de performances.


 
Je pense à un truc en lisant ton post.
 
Pour chaque variable que ta classe doit retourner, tu fais un GetMonParam()...
 
Or moi, à chaque fois que je veux accèder à une variable d'une autre classe, je mets cette variable en public et je fais AutreClasse->MaVariable
 
C'est pas une erreur de faire comme ça?


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 18:19:55    

haazheel a écrit :


C'est pas une erreur de faire comme ça?


 
C'est pas top.
 
En objet, il y a un principe qui s'apelle le principe d'accès uniforme. On accède toujours aux membres d'une classe sans réellement savoir ce qui se cache derrière afin que si l'implémentation change, les clients de cette classe ne soient pas impactés. En précablant comme cela, si un attribut, un jour, doit passé en calculé (ou  encore être validé avant d'être réellement affecté à la classe (genre on v"rifie qu'un age soit pas négatif), il faudrat modifier tous les clients de la classe.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 25-05-2003 à 18:19:55   

Reply

Marsh Posté le 25-05-2003 à 18:27:54    

kadreg a écrit :


 
C'est pas top.
 
En objet, il y a un principe qui s'apelle le principe d'accès uniforme. On accède toujours aux membres d'une classe sans réellement savoir ce qui se cache derrière afin que si l'implémentation change, les clients de cette classe ne soient pas impactés. En précablant comme cela, si un attribut, un jour, doit passé en calculé (ou  encore être validé avant d'être réellement affecté à la classe (genre on v"rifie qu'un age soit pas négatif), il faudrat modifier tous les clients de la classe.


 
OK, mais si on doit accéder à beaucoup de variables d'une autre classe, c'est pas un peu lourdingue de se taper à chaque fois des GetParam()?
 
D'autant plus que si ces variables doivent être modifiées, il faut autant de SetParam()!
 
C'est pourquoi je trouvais plus pratique de passer directement par MaClasse->MonParam...
 
Sinon dans l'exemple que tu as donné:
 

Code :
  1. Configuration *conf = Configuration::getInstance ();


 
A quoi correspond la fonction getInstance? A la récupération des données du fichier?


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 18:38:47    

haazheel a écrit :


C'est pourquoi je trouvais plus pratique de passer directement par MaClasse->MonParam...


 
On trouve ça pratique jusqu'a ce que le projet pête dans les doigts. Sur un projet d'école, on s'en rends pas compte, mais sur un gros projet, qui existe depuis plusieurs années et qui continue à évoluer, ce genre de chose peut couter très cher.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 25-05-2003 à 19:09:19    

bon, ben je vais devoir taper quelques pavés de modification alors...  :fou:  
 
Sinon pour

Code :
  1. Configuration *conf = Configuration::getInstance ();

, elle sert à quoi GetInstance()?


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 19:12:22    

ben c'est pour le singleton

Reply

Marsh Posté le 25-05-2003 à 19:17:52    

++Taz a écrit :

ben c'est pour le singleton


 
Ah, ok...
 
Donc le problème vient du fait que je ne sais pas ce que c'est qu'un singleton... :D


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 19:20:41    

Il existe  une technique en programmation objet : les designs patterns. Un pattern est une solution formalisée face à un problème de programmation courant. Ici le problème est : "comment faire pour n'avoir qu'une instance de classe". Le but est d'avoir la configuration accessible d'un seul endroit, mais que l'on puisse avoir cet endroit facilement accessible de n'importe où dans le programme. La réponse est un design pattern simple (et l'un des plus connu) : le singleton.  
 
Exemple en java ici : http://smeric.developpez.com/java/uml/singleton/


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 25-05-2003 à 19:23:12    

y a Thinking in pattern qui est pas trop mal
 
http://64.78.49.204/TIPatterns-0.9.zip
 
et celui là aussi
 
http://www.patterndepot.com/put/8/JavaPatterns.htm
 
 
 

Reply

Marsh Posté le 25-05-2003 à 19:41:34    


 
En fait c'est un peu comme une variable globale pointant vers l'objet qui gère la config [:tinostar]


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 25-05-2003 à 19:45:04    

antp a écrit :


En fait c'est un peu comme une variable globale pointant vers l'objet qui gère la config [:tinostar]


 
[:tapai]
 
Mais en plus propre


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 25-05-2003 à 22:28:09    

J'ai regardé les différents liens, j'ai essayé de faire quelque chose, mais non, ça marche pas... Voici où j'en suis:
 
Ma classe:
 

Code :
  1. class Configuration
  2. {
  3. private:
  4.         int *ListeCouleurStats,NbreStats;
  5.         AnsiString *ListeNomStats,*ListeStats,PathContenu,PathStats;
  6.         bool InstanceExiste;
  7.         bool EndroitTir,EndroitRebonds,AvecPossessions,AvecStrategies;
  8.         static Configuration instance;
  9.        
  10.         __fastcall Configuration();
  11. public:
  12.         static void getInstance();
  13.         bool __fastcall SetListes();
  14.         bool __fastcall DetruireListes();
  15.         bool __fastcall SetPath();       
  16.         AnsiString __fastcall GetValeurListe(
  17.                 AnsiString Type,
  18.                 int Index);
  19. };


 
Et ma fonction getInstance():
 

Code :
  1. static void Configuration::getInstance()
  2. {
  3. Configuration *instance;
  4. if (!InstanceExiste)
  5. {
  6.         InstanceExiste = true;
  7.         instance = new Configuration();
  8. }
  9. }[cpp]
  10. Et pour appeller ma classe:
  11. [cpp]Configuration *Options = Configuration::getInstance();


 
Alors dans les liens, ils conseillent de mettre getInstance() en static, mais à la compilation, ya une erreur me disant que la classe de stockage static n'est pas admise ici.
Si je l'enlève, l'erreur disparaît(heureusement :D ), mais par contre il y a une erreur sur

Code :
  1. Configuration *Options = Configuration::getInstance();

en me disant Utiliser . ou -> pour appeller Configuration::getInstance().
 
Si je mets un . ou -> nouvelle erreur: Utilisation impropre de typedef 'Configuration'
 
J'ai fait quoi comme connerie?


Message édité par haazheel le 25-05-2003 à 22:55:26

---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 22:31:24    

euh t'es sur de ton coup avec le void
 
 static void Configuration::getInstance()
  {
    Configuration *instance;
    if (!InstanceExiste)
    {
              InstanceExiste = true;
              instance = new Configuration();
    }
  }
 
et faut retrouner quelque chose à chaque fois. passe aussi tes constructeurs en private

Reply

Marsh Posté le 25-05-2003 à 22:58:06    

++Taz a écrit :

euh t'es sur de ton coup avec le void
 

Code :
  1. static void Configuration::getInstance()
  2.   {
  3.     Configuration *instance;
  4.     if (!InstanceExiste)
  5.     {
  6.               InstanceExiste = true;
  7.               instance = new Configuration();
  8.     }
  9.   }


 
et faut retrouner quelque chose à chaque fois. passe aussi tes constructeurs en private


 
Le void, c'était pour tester, j'ai oublié de l'enlever pour copier le code...
 
J'en suis là:

Code :
  1. Configuration::getInstance()
  2. {
  3. Configuration *instance;
  4. if (!InstanceExiste)
  5. {
  6.         InstanceExiste = true;
  7.         instance = new Configuration();
  8. }
  9. return instance;
  10. }


 
et il me met une erreur à la compil' sur

Code :
  1. return instance


 
Impossible de convertir Configuration* en int :(
 
Ah oui, et quels constructeurs en private?


Message édité par haazheel le 25-05-2003 à 22:58:57

---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 23:01:54    

et le type ed retour il est ou?

Reply

Marsh Posté le 25-05-2003 à 23:05:34    

haazheel a écrit :

Code :
  1. class Configuration
  2. {
  3. private:
  4. /* ... */
  5.         static Configuration instance;
  6. /* ... */
  7. };



 
En fait, il faut déclarer instance comme un pointeur de Configuration. En effet, tu le crées avec new !
Ensuite, ta fonction GetInstance doit renvoyer un Configuration * (grillé là dessus)
 
Edit: Dans ton GetInstance, n'oublie pas non plus le else qui renvoie ta variable membre statique instance.


Message édité par gatorette le 25-05-2003 à 23:07:28

---------------
each day I don't die is cheating
Reply

Marsh Posté le 25-05-2003 à 23:16:58    

Alors ça doit ressembler à ça?
 

Code :
  1. class Configuration
  2. {
  3. private:
  4.         int *ListeCouleurStats,NbreStats;
  5.         AnsiString *ListeNomStats,*ListeStats,PathContenu,PathStats;
  6.         bool InstanceExiste;
  7.         bool EndroitTir,EndroitRebonds,AvecPossessions,AvecStrategies;
  8.         static Configuration *instance;
  9.                
  10.         __fastcall Configuration();
  11. public:
  12.         Configuration * getInstance();
  13.         bool __fastcall SetListes();
  14.         bool __fastcall DetruireListes();
  15.         bool __fastcall SetPath();       
  16.         AnsiString __fastcall GetValeurListe(
  17.                 AnsiString Type,
  18.                 int Index);
  19. };


 
Et
 

Code :
  1. Configuration * Configuration::getInstance()
  2. {
  3. Configuration *instance;
  4. if (!InstanceExiste)
  5. {
  6.         InstanceExiste = true;
  7.         instance = new Configuration();
  8. }
  9. else
  10.         return instance;
  11. }


 
C'est ça?
 
SI c'est pas ça, vous pourriez pas m'écrire le bon code s'il vous plait? Parce que là je galère pas mal quand même :fou:  
 
Merci!! :jap:


---------------
Another .Net Blog
Reply

Marsh Posté le 25-05-2003 à 23:31:54    

haazheel a écrit :

Code :
  1. class Configuration
  2. {
  3. private:
  4. /* ... */
  5. static Configuration* instance;
  6. /* ... */
  7. };
  8. Configuration * Configuration::getInstance()
  9. {
  10. static Configuration *instance;
  11. if (!InstanceExiste)
  12. {
  13.         InstanceExiste = true;
  14.         instance = new Configuration();
  15. }
  16. else
  17.         return instance;
  18. }



 
J'ai un doute avec la fonction getInstance. A mon avis tu crées deux fois un pointeur static instance, une fois dans la classe, un autre fois dans la fonction. Une seule variable suffit et j'aurais tendance à garder celle de la classe.
De même, je ne connais pas bien le template Singleton, mais il doit y avoir un moyen de détruire ton objet une fois que tu n'en as plus besoin. J'aurais tendance à utiliser une fonction Release() et un compteur du nombre d'instance de la classe. Quand le compteur arrive à 0, tu fais un delete.


Message édité par gatorette le 25-05-2003 à 23:32:19

---------------
each day I don't die is cheating
Reply

Marsh Posté le 25-05-2003 à 23:44:12    

Bon, exemple de singleton qui marche (normalement, j'ai pas testé), bien sur à adapter suivant l'utilisation  :  
 
 

Code :
  1. class Singleton {
  2. private:
  3.     static Singleton *singleton;
  4. protected:
  5.     Singleton ();
  6. public:
  7.     static Singleton *getInstance () {
  8.         if (! singleton) {
  9.             singleton= new Singleton ();
  10.         }
  11.             return singleton;
  12.     }
  13.     static void release () {
  14.         delete singleton;
  15.         singleton = NULL;
  16.     }
  17. };
  18. Singleton::singleton = NULL;


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 25-05-2003 à 23:48:27    

ah...
 
Merci beaucoup... :jap:  
 
Je vois si ça marche :)


---------------
Another .Net Blog
Reply

Marsh Posté le 26-05-2003 à 00:12:58    

kadreg a écrit :

Bon, exemple de singleton qui marche (normalement, j'ai pas testé), bien sur à adapter suivant l'utilisation  : ...


 
J'ai un doute sur ta fonction Release. En effet, tu fais un delete de ton objet sans vérifier qu'il ne soit pas utilisé par quelqu'un d'autre ! J'aurais tendance à utiliser un compteur pour ça (influence de COM ?). Par contre, il est vrai que ça marche bien si tu ne fais ton Release qu'à la toute fin de ton programme. A voir selon la situation...


---------------
each day I don't die is cheating
Reply

Marsh Posté le 26-05-2003 à 02:41:56    

Bon, impeccable, merci à tous, ça fonctionne très bien...
 
Mais j'aimerais revenir sur cette histoire de fonction GetParam().
 
Prenons le cas d'une classe Options contenant toutes les options d'un programme. Admettons que le programme propose 100 options différentes.
 
Est-ce qu'il faut alors créer 100 fonctions Getxxxx() différentes?
 
Il n'y aurait pas moyen de créer une fonction retournant n'importe uniquement un type, mais pour n'importe quelle variable?
 
Je m'explique: sur ces 100 options, on a 40 valeurs numériques.
 
On peut pas faire un GetParamInt(int MonParam) qui retournerait return MonParam, et ce quel que soit MonParam, tant qu'il est du type int?


---------------
Another .Net Blog
Reply

Marsh Posté le 26-05-2003 à 07:25:01    

gatorette a écrit :


J'ai un doute sur ta fonction Release. En effet, tu fais un delete de ton objet sans vérifier qu'il ne soit pas utilisé par quelqu'un d'autre ! J'aurais tendance à utiliser un compteur pour ça (influence de COM ?). Par contre, il est vrai que ça marche bien si tu ne fais ton Release qu'à la toute fin de ton programme. A voir selon la situation...


 
Mon pointeur est privé, dans une classe dont j'ai la garantie que je n'aurais qu'une seule instance, donc aucun risque (par contre, effectivement, je sais plus le résultat de delete NULL, ça peut faire des surprises si je double release.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 26-05-2003 à 11:15:34    

kadreg a écrit :


Mon pointeur est privé, dans une classe dont j'ai la garantie que je n'aurais qu'une seule instance, donc aucun risque (par contre, effectivement, je sais plus le résultat de delete NULL, ça peut faire des surprises si je double release.


 
Je crois qu'un delete d'un pointeur NULL ne pose pas de problèmes, par contre je pensais plutôt à quelque chose dans le genre :

Code :
  1. {
  2. Singleton *pFirst = Singleton::getInstance(); // création du Singleton
  3. ...
  4. {
  5. Singleton *pSecond = Singleton::getInstance(); // récupération du Singleton
  6. pSecond->getParam();
  7. Singleton::Release(); // je n'ai plus besoin du Singleton donc je le Release
  8. }
  9. ...
  10. pFirst->getParam(); // Erreur ! pFirst n'est plus valide !
  11. Singleton::Release();
  12. }


 
Evidemment, quand on connait l'implémentation, on se rend bien compte qu'il ne faut pas faire de Release à chaque fois. Mais cela me semble plus naturel de faire un Release pour chaque getInstance.
 

haazheel a écrit :


Est-ce qu'il faut alors créer 100 fonctions Getxxxx() différentes?


 
Pas forcemment, tu peux faire un truc dans le genre:

Code :
  1. class Configuration : public Singleton<Configuration>
  2. {
  3. public:
  4. enum
  5. {
  6. param1,
  7. param2,
  8. param3
  9. } listParams;
  10. template<typename T>
  11. bool GetParam( listParams param, T& ret ) const;
  12. };
  13. {
  14. ...
  15. int param1;
  16. pConfig->GetParam( Configuration::param1, param1 );
  17. ...
  18. }


 
Je n'ai pas testé mais l'idée y est.


Message édité par gatorette le 26-05-2003 à 11:15:55

---------------
each day I don't die is cheating
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed