[C++ débutant] Génération d'instances dynamique (?)

Génération d'instances dynamique (?) [C++ débutant] - C++ - Programmation

Marsh Posté le 01-03-2006 à 14:52:12    

Bonjour (chrisbk, slash133 ... :hello:  [:ddr555] )
 
Rappell du sujet: http://orgasm.free.fr/hfr/sujetc++.jpg
+/- Toutes les operations sur les formes demandées dans le sujet fonctionnent dans mon main, quand je fais des tests a la main.
 
Exemple:

Code :
  1. Triangle *monTriangle = new Triangle("Le Triangle", 7, coord1, coord2, coord3);


 
puis
 

Code :
  1. maListe.ajout(monTriangle );


 
Tout marche nickel jusqu'a la, mais ...  quand ça sera au parser de découper la chaine entrée par l'utilisateur, il va devoir instancier un Triangle comme je l'ai fait à la main. Sauf que moi, j'ai choisi "monTriangle" comme nom, puis pour le 2eme ça sera "monTriangle2" etc ... mais quand le parser va devoir faire ça, il va bien falloir un nom physique au triangle instancié. Comment choisir ? Il me faut un nom différent pour chaque triangle, sinon il va etre écrasé à chaque fois.  
 
Pour résoudre ce problème, on m'a conseillé de ne pas donner de nom, mais simplement de faire:
 

Code :
  1. maListe.ajout( Triangle("Le Triangle", 7, coord1, coord2, coord3) );


 
Bien, ça marche. Sauf que maintennant, ça se complique :
 
ça casse un peu tout mon systeme de groupes. Autant avec des formes ça marche, maListe principale ayant un nom (définie dans le main() avec Liste maListe). Mais mes groupes sont eux-aussi des Listes, sauf que leur instance n'aura pas de nom si je fais comme en haut. Exemple:
 

Code :
  1. maListe.ajout(new Triangle("Le Triangle", 7, coord1, coord2, coord3));


--> OK
 

Code :
  1. maListe.ajout(new Groupe("Groupe 1" ));


--> Toujours OK
 
mais maintenant, comment j'ajoute des formes dans mon groupe 1 ? Avant, je faisais

Code :
  1. groupe1->ajout(monCarre2);


 
Mais maintenant, groupe1 n'a plus de nom. Du coup, je ne peux pas appeller une méthode de classe ... si ? :sweat:


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 14:52:12   

Reply

Marsh Posté le 01-03-2006 à 15:30:33    

ParadoX a écrit :

Code :
  1. maListe.ajout(new Groupe("Groupe 1" ));


 
Mais maintenant, groupe1 n'a plus de nom. Du coup, je ne peux pas appeller une méthode de classe ... si ? :sweat:


 
groupe1 n'a peut-être plus de nom, mais tu devrais quand même y avoir accès grâce à un itérateur sur ta liste, non ?
En plus, tu peux distinguer facilement "groupe 1" dans la liste grâce à son étiquette (ce que j'appelle "étiquette", c'est le premier argument du constructeur)

Reply

Marsh Posté le 01-03-2006 à 15:37:26    

Son nom donné par l'utilisateur, alors ! hmm jy ai pensé, mais alors ça serait une méthode de classe itérateur que je dois écrire ... 'vais tester ça. :)


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 15:46:09    

ParadoX a écrit :

Bonjour (chrisbk, slash133 ... :hello:  [:ddr555] )


C'est slash33  :o  
 
Est-ce une bonne idée de découper ton problème en plusieurs topics? Se reporter aux autres topics pour avoir une vision d'ensemble du problème est une démarche fastidieuse.
 
Bon après cette entrée en matière, voyons tes problèmes.
 
Maintenant tu dois coder ta gestion des commandes.
 
En fonction de la commande saisie par l'utilisateur, tu dois manipuler des objets existants ou en créer de nouveaux. En cas de création, tu dois instancier l'objet de la classe approprié.
 
Une façon simple pourrait être, après l'analyse lexicale de la commande, de coder la création de la forme pour chaque cas possible.
 
Par exemple, la commande pourrait être:

CREER_TRIANGLE "le triangle"; 7; 0.5, 0.2; 0.8, 1.6; 2.7, 3.6; #FF0000


Syntaxe de la commande:

  • CREER_TRIANGLE nom du triangle; ?; coord1; coord2; coord3; couleur
  • chaque paramètre est séparé du précédent par un point-virgule
  • l'abscisse de la coordonnée est séparée de l'ordonnée par une virgule. Le séparateur de décimale est le point.


Code :
  1. // lève une BadCommandException si la commande n'est pas valide
  2. void CommandParser::Parse(const char* aCommand)
  3. throw BadCommandException
  4. {
  5.     // interpréter la commande
  6.     StringTokenIterator it (aCommand);
  7.     // extraire l'action de la commande
  8.     const char* action = it.next();
  9.    
  10.     // demande de création d'un objet
  11.     if (strcmp(action, KACTION_CREER_OBJET) == 0)
  12.     {
  13.         const char* forme = it.next();
  14.        
  15.         // traite la forme à créer
  16.         if (strcmp(forme, KFORME_TRIANGLE) == 0)
  17.         {
  18.            // récupérer et contrôler les paramètres et les passer au constructeur
  19.            objet = new Triangle(...);
  20.         }
  21.         /* else if ... autres formes disponibles
  22.         {
  23.         }
  24.         */
  25.         else // forme inconnue
  26.         {
  27.             throw new BadCommandException("Forme inconnue!" );
  28.         }
  29.         GetList().AppendTail(objet);
  30.         // surtout pas de delete objet!
  31.     }
  32. }


 
C'est un peu romancé (copier le code ne te sera d'aucune utilité).
 
Pour ton histoire de nom, je ne vois pas le problème. Le nom d'un objet n'est qu'un attribut de la classe. Ton programme fonctionnerait aussi sans les noms. Les noms sont simplement là pour indexer les objets de manière unique et simple pour l'utilisateur. Tu auras probablement a gérer une contrainte d'unicité sur le nom d'ailleurs. Pour la peine, il est peut être nécessaire de revoir le design de Liste selon le principe d'une hashmap (table indexée).


Message édité par slash33 le 01-03-2006 à 15:57:40
Reply

Marsh Posté le 01-03-2006 à 19:59:52    

:hello:  
[HS]
Tu (paradox) serais pas à la fac de Nantes par hasard? (meme s'il semblerait que non d'apres le profil...)
[/HS]

Reply

Marsh Posté le 01-03-2006 à 20:03:43    

Désolé ce n'est pas moi :jap:  :D  
 
slash33 --> existe-t-il un moyen de tester si une variable existe ? Je m'explique:
Je suis en train d'ajouter des exceptions, et je dois tester un Objet. Si cet objet est un groupe, c'est ok. Sinon, je dois lever une erreur. Alors je me suis dit que je pourrais peut etre tester qu'une donnée membre existe, qu'un groupe aurait et pas une forme. C'est possible ?
 
 :jap:


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 20:15:40    

tu peux montrer le code ou tu dois ajouter le test ?

Reply

Marsh Posté le 01-03-2006 à 20:24:45    

Bah ... j'ai une fonction:
 

Code :
  1. void ajouterAuGroupe(char*, char*, Liste& );


 
qui s'appelle comme ça
 

Code :
  1. monIterateur.ajouterAuGroupe("Cible", "Destination", maListe);


 
Cible peut etre un groupe ou une forme, peu importe .... mais destination ne doit être qu'un groupe, obligatoirement. Maintenant, ce sont tous 2 des Objets, dont si je donne une forme comme destination, il va le prendre, mais ça va tout faire planter.
 
Alors avant de procéder à l'ajout, dans la fonction, je voulais tester la présence de destination->monGroupe (qui est une donnée membre propre à un groupe, et pas à une forme)
 
La ligne critique est:

Code :
  1. this->ajouter(aInserer, (groupeDestination->monGroupe));


 
Des idées ?
 
Sinon, j'ai utilisé un truc un peu barbarre avant, je voulais savoir s'il y a une maniere plus élégante de le faire (jvois déjà chrisbk- arriver en courant [:ddr555] )
 

Code :
  1. Groupe *groupeDestination =  reinterpret_cast<Groupe*> ((*actuel)->getValeur());

Message cité 1 fois
Message édité par ParadoX le 01-03-2006 à 20:25:01

---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 20:32:34    

Code :
  1. Groupe *groupeDestination =  reinterpret_cast<Groupe*> ((*actuel)->getValeur());


 
En fait, toi ausis tu peut aller te pendre avec ton prof.
Je crosi que les bases du ++ et du polymorphisme ne sont pas acquise, ca sert  à rien de bisouiller dans le vide !

Reply

Marsh Posté le 01-03-2006 à 20:35:57    

Joel F a écrit :

Code :
  1. Groupe *groupeDestination =  reinterpret_cast<Groupe*> ((*actuel)->getValeur());


 
En fait, toi ausis tu peut aller te pendre avec ton prof.
Je crosi que les bases du ++ et du polymorphisme ne sont pas acquise, ca sert  à rien de bisouiller dans le vide !


 
Si tu me proposes autre chose, tant mieux, sinon, merci de ton intervention  :jap:


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 20:35:57   

Reply

Marsh Posté le 01-03-2006 à 21:06:22    

ParadoX a écrit :

Bah ... j'ai une fonction:
 

Code :
  1. void ajouterAuGroupe(char*, char*, Liste& );


 
qui s'appelle comme ça
 

Code :
  1. monIterateur.ajouterAuGroupe("Cible", "Destination", maListe);


 


 
probleme au niveau du typage, remplace les 'char*' par 'const char *' dans le prototype
 
ensuite je ne comprends pas comment tu passes "Cible" à un objet ?? peut etre que tu n'as pas tout montrer
 

Citation :

Alors avant de procéder à l'ajout, dans la fonction, je voulais tester la présence de destination->monGroupe (qui est une donnée membre propre à un groupe, et pas à une forme)


 
si t'en arrives à ce genre de besoin c'est que tu n'a pas vraiment compris le polymorphisme, tu devrais prendre au serieux la remarque de JoelF, sincerement :)
 
autre chose, quand je vois ca

Code :
  1. monIterateur.ajouterAuGroupe("Cible", "Destination", maListe);


je ne peu m'empecher de repeter pour la 100ieme fois que ton model OO d'iterateur est foireux (il en fais trop, pas générique, typiquement en c++ l'interface d'un itérateur c'est que de la surcharge d'opérateur pour qu'il puisse s'utiliser comme un pointeur) et pete l'encapsulation (tout ces friends)
ca pourrait etre tellement plus simple et plus robuste
http://fr.wikipedia.org/wiki/It%C3 [...] ception%29

Reply

Marsh Posté le 01-03-2006 à 22:12:29    

C'est vrai que tu as un problème. Tu as défini une classe de base Objet dont héritent les classes Groupe, Triangle, etc. Tu gère la liste des objets avec des Objet*, ce qui est cohérent. Tu as une relation de composition entre Groupe et Objet qui finalement te pose un problème car les opérateurs de manipulation des membres du groupe sont au niveau de la classe Groupe... et toi tu n'a accès qu'à des Objet*.


Message édité par slash33 le 01-03-2006 à 22:12:59
Reply

Marsh Posté le 01-03-2006 à 22:17:26    

mais oui mais c'était la seule solution pour avoir ET des formes ET des groupes en meme temps ... sinon je n'aurais pas pu faire des groupes de groupes, et tout ça !
 
J'ai ajouté une donnée membre à la classe objet, un char *type, dans lequel je mets soit "forme" soit "groupe". .. ça va peut etre m'avancer. Sinon, je voulais juste préciser que je n'ai jamais vraiment fait de C ni de C++, et que du coup je trouve le sujet assez balèze !


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 22:34:19    

Ben un groupe est un conteneur de figures et de groupes.
 
Le défaut est peut-être d'avoir considéré qu'un groupe est un objet...
 
Un groupe est une sélection d'objets et est identifié par une étiquette.
 
Ca ressemble a une erreur de conception : identifier, par erreur, une composition comme une entité à part entière.


Message édité par slash33 le 01-03-2006 à 22:35:09
Reply

Marsh Posté le 01-03-2006 à 22:38:00    

ParadoX a écrit :

je n'ai jamais vraiment fait de C ni de C++


 
le langage n'i y est pour peu de chose dans tes blocages, c'est surtout un probleme de conception
tu as éjà fait de la modelisation objet (avec uml par exemple) ?


Message édité par skelter le 01-03-2006 à 22:38:20
Reply

Marsh Posté le 01-03-2006 à 22:42:39    

Que penses tu de son problème conceptuel skelter ? A t-il intérêt à considérer un groupe comme un objet particulier (Groupe hérite de la classe Objet) ?

Reply

Marsh Posté le 01-03-2006 à 22:45:40    

La différence entre Groupe et Forme est que le premier est issu d'une composition d'objets alors que le second est atomique.


Message édité par slash33 le 01-03-2006 à 22:50:26
Reply

Marsh Posté le 01-03-2006 à 23:09:28    

C'est pourtant le prof qui nous a dit oui à cette conception la !
Enfin, j'y retourne ^^
 
Merci en tout cas :)


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 01-03-2006 à 23:15:10    

slash33 a écrit :

Que penses tu de son problème conceptuel skelter ? A t-il intérêt à considérer un groupe comme un objet particulier (Groupe hérite de la classe Objet) ?


 
deja on peut toujour tout faire heriter d'une classe objet, ca aura toujours un sens car c'est le niveau maximun d'abstraction (tout objet est un objet) donc ca ne dois pas etre pris en compte dans la conception
 
pour en revenir au probleme, sans rentrer dans les details on a
une classe abstraite forme qui definie l'interface minimale d'une forme
des classes héritant de forme (triangle, cercle...)
une classe groupe qui herite également de forme et aggrege une liste de formes, ca semble tordu mais comme c'est dit dans l'énnoncé l'interface de forme dont groupe hérite servira à la redistribution des actions sur chaque forme de sa liste (un group est considèré comme une forme dans ce probleme)
 
je sais pas si c'est top mais cette conception ne devrais pas poser de probleme

Message cité 1 fois
Message édité par skelter le 01-03-2006 à 23:15:44
Reply

Marsh Posté le 01-03-2006 à 23:36:09    

skelter a écrit :

deja on peut toujour tout faire heriter d'une classe objet, ca aura toujours un sens car c'est le niveau maximun d'abstraction (tout objet est un objet)


 
... Alors les types fondamentaux et compounds sortent du niveau maximal d'abstraction. Bref.
 

skelter a écrit :

pour en revenir au probleme, sans rentrer dans les details on a
une classe abstraite forme qui definie l'interface minimale d'une forme
des classes héritant de forme (triangle, cercle...)
une classe groupe qui herite également de forme et aggrege une liste de formes, ca semble tordu mais comme c'est dit dans l'énnoncé l'interface de forme dont groupe hérite servira à la redistribution des actions sur chaque forme de sa liste (un group est considèré comme une forme dans ce probleme)
 
je sais pas si c'est top mais cette conception ne devrais pas poser de probleme


 
(J'ai pas eu le courage de lire les threads en entier)  
pourquoi est-ce qu'un groupe est une forme ? Un groupe aggrege une liste de forme, ça me parait suffisant non ?

Reply

Marsh Posté le 01-03-2006 à 23:46:59    

Citation :

Alors les types fondamentaux et compounds sortent du niveau maximal d'abstraction. Bref.


 
focalises par sur cet aspect du c++ surtout que c'est un langage multi-paradigmatique donc l'oo ne peut etre imposé, et il y a des langages tout objets au niveau des types
 

Citation :


(J'ai pas eu le courage de lire les threads en entier)  
pourquoi est-ce qu'un groupe est une forme ? Un groupe aggrege une liste de forme, ça me parait suffisant non ?


 
je suis partie de ca (lien du premier post)
 
http://orgasm.free.fr/hfr/sujetc++.jpg
 
si tu as une meilleur solution n'hesite pas :)

Reply

Marsh Posté le 02-03-2006 à 00:19:49    


De toutes façons je vais garder cette configuration, c'est trop tard pour tout changer... Je lutte depuis 1 heure sur une recherche récursive :/ si vous avez une idée:
 

Code :
  1. // Test
  2. Liste::Node* Liste::estPresentFull(char *nomRecherche, Liste &uneListe)
  3. {
  4. if(!estVide())
  5. {
  6.  Iterateur monIterateur(*this);
  7.  while(!monIterateur.finDeListe())
  8.  {
  9.   // Le noeud actuel est une forme
  10.   if(strcmp(monIterateur.valeur()->getType(), "forme" ) == 0)
  11.   {
  12.    if(strcmp(monIterateur.valeur()->getNom(), nomRecherche) == 0)
  13.    {
  14.     return monIterateur.getActuel(); // Si le nom est le meme, on retourne un pointeur sur ce Noeud
  15.    }
  16.   }
  17.   else
  18.   // Sinon le noeud actuel est un groupe
  19.   {
  20.    if(strcmp(monIterateur.valeur()->getNom(), nomRecherche) == 0)
  21.    {
  22.     return monIterateur.getActuel(); // Si le nom est le meme, on retourne un pointeur sur ce Noeud
  23.    }
  24.    else // sinon, on relance la recherche sur la liste du groupe (donnée membre d'un groupe)
  25.    {     
  26.     Groupe *tmp =  reinterpret_cast<Groupe*> (monIterateur.valeur());  // Voir annotation après le code !
  27.     estPresentFull(nomRecherche, tmp->getMonGroupe());
  28.    }
  29.   }
  30.   monIterateur.avance();
  31.  }
  32. }
  33. else
  34. {
  35.  return NULL;
  36. }
  37. return NULL;
  38. }


 
Pour l'annotation: Je suis obligé de faire le cast, parce qu'actuellement, monIterateur.valeur() est un OBJET, et je 'nai donc pas acces au groupe de formes (car il se trouve dans un Groupe, et non pas ds un Objet de base).
 
Ensuite, on relance la recherche, mais en spécifiant la Liste contenue dans le groupe cette fois.  
 
 
Mais j'ai droit à un Stack Overflow ^^
ya une couille qqpart :/


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 02-03-2006 à 00:21:48    

skelter a écrit :

c'est un langage multi-paradigmatique donc l'oo ne peut etre imposé


justement !
 

skelter a écrit :

je suis partie de ca (lien du premier post)
 
http://orgasm.free.fr/hfr/sujetc++.jpg
 
si tu as une meilleur solution n'hesite pas :)


 
Je ne sais pas. Je dirais que le sujet introduit une grosse bourde : un groupe est une forme.
pour résoudre ce problème, j'utiliserai probablement une liste générique de groupe. Un groupe pouvant contenir une forme, ou plusieurs.
typedef std::vector<Shape*> Group;
std::list<Group>  

Reply

Marsh Posté le 02-03-2006 à 00:23:36    

Jep, c'est peut etre ce que j'aurais du faire :/ Au lieu de "Tout es objet", "Tout est groupe", avec 1 ou plusieurs Formes dedans :/


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 02-03-2006 à 00:53:13    

ParadoX a écrit :

De toutes façons je vais garder cette configuration, c'est trop tard pour tout changer... Je lutte depuis 1 heure sur une recherche récursive :/ si vous avez une idée:
 

Code :
  1. // Test
  2. Liste::Node* Liste::estPresentFull(char *nomRecherche, Liste &uneListe)
  3. {
  4. if(!estVide())
  5. {
  6.  Iterateur monIterateur(*this);
  7.  while(!monIterateur.finDeListe())
  8.  {
  9.   // Le noeud actuel est une forme
  10.   if(strcmp(monIterateur.valeur()->getType(), "forme" ) == 0)
  11.   {
  12.    if(strcmp(monIterateur.valeur()->getNom(), nomRecherche) == 0)
  13.    {
  14.     return monIterateur.getActuel(); // Si le nom est le meme, on retourne un pointeur sur ce Noeud
  15.    }
  16.   }
  17.   else
  18.   // Sinon le noeud actuel est un groupe
  19.   {
  20.    if(strcmp(monIterateur.valeur()->getNom(), nomRecherche) == 0)
  21.    {
  22.     return monIterateur.getActuel(); // Si le nom est le meme, on retourne un pointeur sur ce Noeud
  23.    }
  24.    else // sinon, on relance la recherche sur la liste du groupe (donnée membre d'un groupe)
  25.    {     
  26.     Groupe *tmp =  reinterpret_cast<Groupe*> (monIterateur.valeur());  // Voir annotation après le code !
  27.     estPresentFull(nomRecherche, tmp->getMonGroupe());
  28.    }
  29.   }
  30.   monIterateur.avance();
  31.  }
  32. }
  33. else
  34. {
  35.  return NULL;
  36. }
  37. return NULL;
  38. }




 
Ya une boucle infinie sur le dernier else:
 

Code :
  1. Groupe *tmp =  reinterpret_cast<Groupe*> (monIterateur.valeur());  // Voir annotation après le code !
  2. estPresentFull(nomRecherche, tmp->getMonGroupe());


 
 
 :sweat:


Message édité par ParadoX le 02-03-2006 à 00:53:35

---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 02-03-2006 à 09:05:45    

ParadoX a écrit :

Code :
  1. // Test
  2. Liste::Node* Liste::estPresentFull(char *nomRecherche, Liste &uneListe)
  3. {
  4. /* ... */
  5. }



 
Je ne comprends pas trop la signature de ta fonction : à quoi sert le deuxième argument "uneListe" ?
 
visiblement, tu recherches ton objet dans l'objet Liste pour lequel tu appelles la méthode estPresentFull (en particulier, tu écris "Iterateur monIterateur(*this);" )
Par contre, dans ton appel récursif, c'est le deuxième argument que tu changes : estPresentFull(nomRecherche, tmp->getMonGroupe());
 
Finalement, je crois que tu passes ton temps à rechercher sur la même liste, sans jamais descendre dans les listes des groupes.
 
Tu n'aurais pas ce genre de problème si la signature de ta fonction de recherche était plutôt :

Code :
  1. Liste::Node* Liste::estPresentFull(char *nomRecherche)

Reply

Marsh Posté le 02-03-2006 à 09:29:22    

Il faudrait peut être éviter de se disperser non ?
 
L'information un groupe est une forme est valable pour la modélisation conceptuelle. Au niveau logique, juste avant la réalisation, cela pose un problème.
 
En fait, ce qui se dégage du problème est une structure arborescente dont un noeud terminal est une Forme non décomposable (Triangle, Cercle, etc) alors qu'un noeud hiérarchisé est un groupe. Chaque noeud possède une étiquette (à l'exception du noeud racine ??)
 
Ainsi, il faut à mon avis un mode de parcours vertical transcendant les niveaux hiérarchiques et horizontal sur un même niveau. De cette manière, le groupe n'existe plus en tant que concept mais comme choix de structuration des formes.

Reply

Marsh Posté le 02-03-2006 à 09:39:17    

++fab a écrit :

Je ne sais pas. Je dirais que le sujet introduit une grosse bourde : un groupe est une forme.
pour résoudre ce problème, j'utiliserai probablement une liste générique de groupe. Un groupe pouvant contenir une forme, ou plusieurs.
typedef std::vector<Shape*> Group;
std::list<Group>


Dans ce cas tu ne peux pas créer un groupe par accrétion de formes et de groupes... et tu n'attribues pas d'étiquette au groupe (mais peut être qu'un un std::hashmap<string, Group> ferait l'affaire) :o


Message édité par slash33 le 02-03-2006 à 09:49:29
Reply

Marsh Posté le 02-03-2006 à 09:47:33    

slash33 a écrit :

En fait, ce qui se dégage du problème est une structure arborescente dont un noeud terminal est une Forme non décomposable (Triangle, Cercle, etc) alors qu'un noeud hiérarchisé est un groupe. Chaque noeud possède une étiquette

Entièrement d'accord avec toi là dessus
 

slash33 a écrit :

Le groupe n'existe plus en tant que concept mais comme choix de structuration des formes.

Euh...  :??:  
Comment tu traduis ça en UML ?

Reply

Marsh Posté le 02-03-2006 à 09:52:24    

franceso a écrit :

Euh...  :??:  
Comment tu traduis ça en UML ?


Justement j'y réfléchi (je ne suis pas un habitué d'UML... :o )  :pt1cable:
 
(manip. sur Poseidon...)


Message édité par slash33 le 02-03-2006 à 09:56:01
Reply

Marsh Posté le 02-03-2006 à 10:21:26    

Ah je crois que j'arrive à quelque chose. Le truc est de voir un Groupe comme une entité à part entière n'héritant pas de Forme - sans agrégation non plus.
 
Traduction littérale du diagramme UML que j'ai sous les yeux:

  • Un triangle, un cercle... est une forme,
  • Une forme possède une étiquette,
  • Un groupe possède une étiquette,
  • (Les deux affirmations ci-dessus incitent à mutualiser le comportement dans une classe/interface IfcIdentifiable gérant l'attribut "etiquette" ),
  • Un groupe regroupe (association simple) des formes n'appartenant pas déja à un groupe.
  • Une forme est incluse à un groupe ou aucun. La visibilité du groupe d'appartenance au niveau de la forme permet de gérer simplement la contrainte "un groupe ne peut pas contenir deux fois la même forme" mais induit une complexité supplémentaire pour le maintien de la cohérence dûe à la dépendance Forme->Groupe (qui n'est peut être pas souhaitable d'ailleurs). Une autre solution consiste à parcourir les groupes afin de voir si la forme appartient à l'un d'eux ou non. Cette seconde solution invalide la proposition (1)
  • Un groupe peut regrouper d'autres groupes (agrégation/composition à discuter).
  • Contrainte sur groupe : le groupe doit contenir au moins deux formes ou deux groupes (état transitoire discutable)

Conceptualiser ceci dans une classe Groupe. Finalement, la classe Groupe se comporte comme un noeud (non terminal) de l'arborescence.
 
Le truc c'est de gérer deux listes différentes au niveau du groupe:

  • Une liste de groupes
  • Une liste de formes
  • Gérer les accesseurs/mutateurs séparément


Je pense que de cette façon, il est possible de parcourir l'arborescence des groupes et des formes. Bien sûr il faut gérer une liste globale de formes et de groupes...
(1) ce qui ressemble à la classe Groupe sans être identique! Hé oui, une forme ne doit pas se considérer incluse à groupe racine sinon elle ne peut plus être intégrée à un autre groupe ! Je pense qu'il faut définir une classe Racine dont Groupe dériverait. Reste que la classe Groupe en elle-même risque de ne rien apporter de plus à la classe Racine mais cette séparation est nécessaire...


Message édité par slash33 le 02-03-2006 à 10:59:12
Reply

Marsh Posté le 02-03-2006 à 10:58:26    

Si j'ai bien compris, ça donne à peu près ça en UML : http://fevotte.free.fr/Downloads/uml.pdf
http://fevotte.free.fr/Downloads/uml.jpg
 
(je suis pas un expert UML, hein -> pataper)
 
 
Tu aurais une liste globale de formes, et un groupe "root" qui serait racine de ton arborescence. Chaque groupe contiendrait une liste de pointeurs vers ses les instances de ses formes filles dans la liste globale ? Par contre, je ne comprends pas pourquoi tu dois gérer une liste globale de groupes :??:
 
Ca me paraît pas mal, mais j'ai comme l'impression que ça va donner beaucoup de boulot à ParadoX...

Reply

Marsh Posté le 02-03-2006 à 11:01:27    

dans la réalité un groupe n'est pas une forme, c'est une collection de groupe et de forme
mais le sujet impose que groupe possede les memes opérations de bases qu'une forme et ca ca se traduit directement par la relation d'heritage groupe->forme, je vois pas en quoi c'est ingérable (un groupe aggrege une collection de formes qui peuvent etre un groupe -> structure arborescente) ?? et le schema est plus simple
 
sous unix un repertoire c'est bien un fichier, et ca contient d'autre fichiers

Reply

Marsh Posté le 02-03-2006 à 11:10:49    

franceso a écrit :

Si j'ai bien compris, ça donne à peu près ça en UML : http://fevotte.free.fr/Downloads/uml.pdf
http://fevotte.free.fr/Downloads/uml.jpg


 
Oui à quelques différences dans la façon de modéliser :

  • j'ai représenté les associations Groupe->Forme et Groupe->Groupe et non sous la forme de listes membres.  
  • l'attribut Forme:: parent ne devrait pas apparaître en tant qu'attribut mais comme rôle d'association si mes souvenirs en UML sont bons


Sinon, dans la logique, c'est pareil. ;)  
 
Ton graphique représente ma première proposition qui consiste à créer une dépendance Forme->Groupe concrétisée par l'attribut Forme:: parent.
 

franceso a écrit :

Tu aurais une liste globale de formes, et un groupe "root" qui serait racine de ton arborescence. Chaque groupe contiendrait une liste de pointeurs vers ses les instances de ses formes filles dans la liste globale ? Par contre, je ne comprends pas pourquoi tu dois gérer une liste globale de groupes :??:


En fait si on retire la dépendance Forme->Groupe, on peut utiliser un groupe comme racine ! Sinon il faut ruser un peu...
 

franceso a écrit :

Ca me paraît pas mal, mais j'ai comme l'impression que ça va donner beaucoup de boulot à ParadoX...


Ben il est passablement mâché quand même...  :whistle:  
 
Bon d'autres critiques à formuler sur ce design ?

Reply

Marsh Posté le 02-03-2006 à 11:17:30    

skelter a écrit :

dans la réalité un groupe n'est pas une forme, c'est une collection de groupe et de forme


C'est là toute la subtilité du problème, nous sommes d'accord.
 

skelter a écrit :

mais le sujet impose que groupe possede les memes opérations de bases qu'une forme


Oups j'ai dû sauter un passage alors.
 

skelter a écrit :

et ca ca se traduit directement par la relation d'heritage groupe->forme, je vois pas en quoi c'est ingérable (un groupe aggrege une collection de formes qui peuvent etre un groupe -> structure arborescente) ?? et le schema est plus simple


Effectivement, on peut ou non faire hériter Groupe de Forme si on respecte la séparation Forme/Groupe au niveau de Groupe. N'ayant pas de prétexte à faire l'un de l'autre - quoique la gestion de l'étiquette pourrait rentrer dans ce cadre là, je me suis abstenu. A la lumière des précisions apportées sur les opérations communes aux formes et aux groupes, il faut effectivement envisager une relation d'héritage mais peut être pas directement Groupe->Forme et passer par une classe abstraite (la fameuse classe Objet de paradox ?)
D'ailleurs l'interface IfcLabelled devrait devenir la classe de base (le nom par forcément n'est pas bien choisi dans ce cas...)


Message édité par slash33 le 02-03-2006 à 11:20:41
Reply

Marsh Posté le 02-03-2006 à 11:35:24    

skelter a écrit :

sous unix un repertoire c'est bien un fichier, et ca contient d'autre fichiers

Je dirais plutôt qu'un répertoire contient des "pointeurs" vers d'autres fichiers. L'analogie est super intéressante et je pense qu'on peut la pousser plus loin :
 
-classe de base : forme <-> fichier
 
-spécialisations de cette classe :

  • triangle, cercle, ... <-> différents types de fichiers ordinaires
  • groupe <-> répertoire


on dispose d'une grande liste de formes (<->le disque dur)
le premier élément de cette liste est le groupe root (<-> répertoire /)
les groupes contiennent une liste de pointeurs vers d'autres éléments de la liste, et c'est ce qui constitue l'arborescence du système (mais les formes sont toutes stockées dans une seule liste sans hiérarchie)
 
Qu'en pensez vous ?

Reply

Marsh Posté le 02-03-2006 à 11:42:21    

skelter a écrit :

mais le sujet impose que groupe possede les memes opérations de bases qu'une forme et ca ca se traduit directement par la relation d'heritage groupe->forme, je vois pas en quoi c'est ingérable (un groupe aggrege une collection de formes qui peuvent etre un groupe -> structure arborescente) ?? et le schema est plus simple


Et comment tu fais pour modifier le contenu d'un groupe si tu ne manipules que des formes et que l'interface pour manipuler le membres du groupe sont justement définies au niveau de la classe Groupe ?
 
Comment tu gères cette contrainte : "le groupe doit contenir au moins deux formes ou deux groupes (état transitoire discutable)" ?
 
J'ai une proposition :

  • regrouper l'interface commune aux formes et au groupes.
  • gérer au niveau des classes Groupe et Forme un accès public à cet opérateur.
  • implémenter deux versions différentes de l'interface pour les formes et les groupes (pourrait même être des membres statiques de la classe...)
  • un groupe initialisera sa référence avec l'opérateur qui est le sien, idem pour une forme
  • mais, et c'est là l'intérêt, l'interface sera commune aux deux.


Message édité par slash33 le 02-03-2006 à 11:47:27
Reply

Marsh Posté le 02-03-2006 à 11:56:29    

Bon voilà ça me semble correct:

  • On garde ma définition de Groupe
  • Groupe hérite de Forme
  • Forme fournit une interface de manipulation partagée avec groupe ; soit sous forme de méthodes soit comme un objet compagnon. Groupe implémente sa propre version de l'interface. Ces surcharges seront equivalentes à foreach objet do objet.monOperation(les paramètres)

Message cité 1 fois
Message édité par slash33 le 02-03-2006 à 11:59:11
Reply

Marsh Posté le 02-03-2006 à 12:11:31    

[:mlc]  [:mlc] Vous êtes à bloc, dites-moi ^^
 

franceso a écrit :

Je ne comprends pas trop la signature de ta fonction : à quoi sert le deuxième argument "uneListe" ?
 
visiblement, tu recherches ton objet dans l'objet Liste pour lequel tu appelles la méthode estPresentFull (en particulier, tu écris "Iterateur monIterateur(*this);" )
Par contre, dans ton appel récursif, c'est le deuxième argument que tu changes : estPresentFull(nomRecherche, tmp->getMonGroupe());
 
Finalement, je crois que tu passes ton temps à rechercher sur la même liste, sans jamais descendre dans les listes des groupes.
 
Tu n'aurais pas ce genre de problème si la signature de ta fonction de recherche était plutôt :

Code :
  1. Liste::Node* Liste::estPresentFull(char *nomRecherche)



 
Le 2eme argument sert effectivement à changer de liste DANS laquelle on cherche. Lors du 2 appel, l'iterateur sur this sera placé sur la nouvelle liste, non ? :sweat:  
 
CORRECTION: L'iterateur ne doit pas être placé sur this, mais sur "uneListe" ! Bp,; ça marche tjrs pas, m'enfin ^^
 
Jvais tenter de faire comme tu m'as dit :)

Message cité 1 fois
Message édité par ParadoX le 02-03-2006 à 12:38:54

---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 02-03-2006 à 12:45:21    

ParadoX a écrit :

[:mlc]  [:mlc] Vous êtes à bloc, dites-moi ^^


C'est le métier qui veut ça. Tu es sûr de vouloir devenir développeur ?  :whistle:


Message édité par slash33 le 02-03-2006 à 13:02:12
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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