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

Langage C++ Discussion :

Pb interaction classes


Sujet :

Langage C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 15
    Par défaut Pb interaction classes
    Bonjour à tous (et joyeuses fêtes ),


    j'ai un petit problème de conception (enfin ca ressemble à ca ).

    Pour mon petit code de client chat en ligne de commande, je cherche à clairement séparer la partie interface (entree et sortie) de la partie gestion de la des communications.

    Pour la petite histoire, j'utilise ncurses pour l'interface (j'ai pas trouvé de workaround en C++) et gloox pour la partie XMPP.

    Du coup ce que j'aimerai faire:



    INPUT -------> PARSER ------> OUTPUT

    et PARSER <------> CORE

    Je précise que les fleches ne représentent pas de notion d'heritage

    Le PARSER traduit les commandes de l'utilisateur (venant de INPUT) et lance des actions (en autres du CORE) et affiche le résultat sur OUTPUT.
    Par exemple quand je vais taper la commande /lister_contact dans INPUT, le PARSER sera en charge de reconnaitre la commande et de lancer une fonction membre de CORE pour retourner la liste des contacts à OUTPUT.

    Le fait est que je n'ai pas envie que le PARSER soit complétement dépendant d'une implémentation de CORE, je n'ai donc pas envie d'initialiser PARSER avec un objet CORE.

    Pour résoudre ceci j'ai pensé à faire hériter ma classe CORE de ma classe PARSER. Je pourrais donc redéfinir les fonctions membres de PARSER dans ma classe CORE.
    Ca me fait juste bizarre de voir heriter une classe de l'autre alors que je les vois assez indépendantes.
    On m'a aussi proposer d'utiliser des pointeurs de fonction, mais dans tous les cas déclarer un pointeur de fonction sur une fonction membre d'une classe revient à un peu trop lier ma classe et mon pointeur issu d'une autre classe.

    Peut être suis-je un peu trop exigeant concernant cette fameuse indépendance entre mes classes et qu'il faut à un moment donné fournir des informations de l'une sur l'autre...

    Qu'en pensez vous?

    Merci à tous

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    En fait, il n'y a absolument pas d'héritage à avoir:

    Tu devrais avoir une (hiérarchie de) classe(s) pour la (les) commande(s), une classe pour le récepteur, qui envoie ce qu'il a recu vers le parser (qui transforme le texte recu en commande(s), et qui envoie la (les) commande(s) vers le corps du système qui devra les gérer.

    le corps du système sera lui meme sans doute composé de plusieurs classes mise en commun pour générer un "message" qui sera transmis à ... un émetteur pour etre renvoyé vers le correspondant

    Emetteur et récepteur travailleraient tous les deux avec une (hiérarchie de) classe(s) s'occupant de gérer les sockets et connexions diverses
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 15
    Par défaut Petit tour de conception
    En fait j'ai fait un petit diagramme de ma conception...
    http://lutix.org/data/Diagramme.png
    En résumé: je lance une commande d'un objet Input qui envoit l'information à un objet Linker.
    Ce linker la parse et soit l'envoit à un objet Output qui l'affiche à l'écran soit envoit à un objet core qui en fait quelquechose... sauf que cet objet core peut aussi (à l'écoute du serveur XMPP) envoyer une info au linker qui la relayera à l'output...
    J'ai crée une classe interface

    Evidemment je pourrai séparer la classe Linker en 2 objets tous les deux reliés à Output pour séparer les traitements. Mais ca m'empêcherait de résoudre un serpent qui se mord la queue et je pense qu'il faut avoir vu ça au moins une fois dans sa vie de développeur débutant.

    Mes questions:
    1) dans toutes ces relations que j'ai décrit, je ne sais jamais vraiment si je dois créer un objet membre de la premiere classe à l'intérieur de la seconde (du style un Linker dans un Input) ou tout simplement inclure le premier comme argument de fonction de la seconde...?
    2) comment feriez vous pour relier intimement 2 classes (un peu comme Linker et Core) qui doivent communiquer entre elles dans les 2 sens? Qu'est ce qui est le plus propre?

    En vous remerciant!

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    J'aurais à priori inversé ICore_XMPP et Linker puisque ICore_XMPP semble être une classe abstraite et Linker une classe concrète.

    Citation Envoyé par fabthegreat Voir le message
    1) dans toutes ces relations que j'ai décrit, je ne sais jamais vraiment si je dois créer un objet membre de la premiere classe à l'intérieur de la seconde (du style un Linker dans un Input) ou tout simplement inclure le premier comme argument de fonction de la seconde...?
    Ca dépend. Si tu te retrouves à passer l'argument à chaque fonction, c'est que le lien est plus fort. Les questions à se poser sont pour savoir quel lien établir dans A avec B :
    => Que peut faire A sans B ?
    => un B peut il être partagé (simultanément ou successivement) par plusieurs A ?
    => un B doit-il être crée pour un A et détruit avec la destruction de A ?

    Citation Envoyé par fabthegreat Voir le message
    2) comment feriez vous pour relier intimement 2 classes (un peu comme Linker et Core) qui doivent communiquer entre elles dans les 2 sens? Qu'est ce qui est le plus propre?
    Ca dépend essentiellement de la sémantique des canaux de communication. Il se peut que le sens Core->Linker soit plus un DP Observer là où un Linker->Core pourrait relever d'un client/serveur (simple hypothèse de ma part dans les 2 cas). Cela ne s'implémenterait pas forcément de façon symétrique (et nécessiterait peut être de séparer les différents rôles).
    Je pense qu'il faut d'abord identifier à quoi sert l'association entre les deux classes dans chaque sens.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 15
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Ca dépend. Si tu te retrouves à passer l'argument à chaque fonction, c'est que le lien est plus fort. Les questions à se poser sont pour savoir quel lien établir dans A avec B :
    => Que peut faire A sans B ?
    => un B peut il être partagé (simultanément ou successivement) par plusieurs A ?
    => un B doit-il être crée pour un A et détruit avec la destruction de A ?


    Ca dépend essentiellement de la sémantique des canaux de communication. Il se peut que le sens Core->Linker soit plus un DP Observer là où un Linker->Core pourrait relever d'un client/serveur (simple hypothèse de ma part dans les 2 cas). Cela ne s'implémenterait pas forcément de façon symétrique (et nécessiterait peut être de séparer les différents rôles).
    Je pense qu'il faut d'abord identifier à quoi sert l'association entre les deux classes dans chaque sens.
    Merci pour tes réponses!
    Effectivement, ca ressemble un peu à ce que tu dis! ICore_XMPP envoit des signaux et Linker les recoit. Dans l'autre sens c'est + formalisé

    Etant donné que je débute en C++, je me demandais si commencer par des pointeurs en tant qu'objet membre dans mes classes serait pas mal pour définir les liaisons entre les objets. Par contre, je ne peux évidemment pas les initialiser dans le constructeur à cause des interdépendances... je devrais appeler une méthode à part pour associer A à B et vice versa, non?

    Sinon tu me conseilles quoi comme bibliothèque pour les signaux et les slots?

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par fabthegreat Voir le message
    Etant donné que je débute en C++, je me demandais si commencer par des pointeurs en tant qu'objet membre dans mes classes serait pas mal pour définir les liaisons entre les objets.
    En tant que débutant, tu devrais éviter d'utiliser des pointeurs nus et préférer des classes qui s'occupent de tout ça pour toi (vector, smart ptr, etc.).

    Citation Envoyé par fabthegreat Voir le message
    Par contre, je ne peux évidemment pas les initialiser dans le constructeur à cause des interdépendances... je devrais appeler une méthode à part pour associer A à B et vice versa, non?
    Ca ne me choque pas d'avoir une classe builder dédiée à la construction des différents objets et au tissage de leur relation.

    Citation Envoyé par fabthegreat Voir le message
    Sinon tu me conseilles quoi comme bibliothèque pour les signaux et les slots?
    Simple, efficace et une fois installée devenue indispensable : Boost avec Boost.Signal

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 15
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    En tant que débutant, tu devrais éviter d'utiliser des pointeurs nus et préférer des classes qui s'occupent de tout ça pour toi (vector, smart ptr, etc.).
    Pourquoi ça? Je ne vais pas faire quelque chose de bien violent, un membre pointeur tout bête à partir duquel je pourrais appeler les méthodes. A moins qu'il y ait un soucis sous-jacent que je n'ai pas vu?

    Citation Envoyé par 3DArchi Voir le message
    Ca ne me choque pas d'avoir une classe builder dédiée à la construction des différents objets et au tissage de leur relation.

    Simple, efficace et une fois installée devenue indispensable : Boost avec Boost.Signal
    Il faut que je me renseigne sur cette idée de fabrique, mais n'est ce pas disproportionné pour un code qui ne va créer qu'un seul objet de chaque classe?

    Merci encore

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par fabthegreat Voir le message
    Pourquoi ça? Je ne vais pas faire quelque chose de bien violent, un membre pointeur tout bête à partir duquel je pourrais appeler les méthodes. A moins qu'il y ait un soucis sous-jacent que je n'ai pas vu?
    Le problème est toujours le même : lorsque l'on a des pointeurs nus, on pense de manière quasi systématique à la gestion dynamique de la mémoire, et l'on doit donc systématiquement se poser la question de qui prend la responsabilité de la durée de vie de l'objet pointé.

    Si tu "foires" ton coup en réfléchissant à qui est responsable de la destruction de quoi, tu peux très facilement te retrouver avec des fuites mémoires (à cause d'un objet qui n'est jamais détruit) ou avec des tentatives de double libération de la mémoire (parce qu'un premier objet en détruit un autre, puis qu'un troisième objet essaye de détruire à nouveau un objet déjà détruit )

    Le tout, sans compter que ces problèmes se retrouvent aussi dans les mécanismes mis en oeuvre lors de la levée d'exception

    Il est tout à fait possible de gérer tout cela de manière correcte et sans craindre les écueils, mais cela demande une maitrise et un attention telles que, si tu peux t'éviter d'avoir à le faire, tu ne t'en porteras surement pas plus mal
    Il faut que je me renseigne sur cette idée de fabrique, mais n'est ce pas disproportionné pour un code qui ne va créer qu'un seul objet de chaque classe?
    C'est peut etre là que tu te trompes!!!

    Déjà, as tu réellement la certitude qu'il n'y aura jamais qu'une et une seule instance d'une classe particulière

    De plus, l'énorme avantage de passer par un builder ou par une fabrique, c'est que tout le code nécessaire se retrouve centralisé en un point donné, alors qu'autrement, le code va se trouver disséminé un peu partout

    Tu gagneras donc énormément en terme de maintenance et d'évolutivité à utiliser un builder, car, celui-ci étant appelé chaque fois que nécessaire, il te suffira de modifier le seul builder pour l'adapter au lieu de devoir parcourir les 1001 fichiers dans lesquels le code se retrouverait disséminé s'il n'existait pas

    C'est d'autant plus vrai qu'il existe un conseil d'eXtrem Programming qu'on appelle DRY (Don't Repeat Yourself, ou , si tu préfères en francais : ne vous répétez pas ) qu'il est beaucoup plus aisé de respecter en déléguant les tâches (quelles qu'elles soient) à des classes qui n'auront pour seule responsabilité que d'effectuer ces tâches

    Neuf fois sur dix, on peut se rendre compte que, si on a décidé qu'une délégation était disproportionnée par rapport à quelque chose de particulier, l'évolution des choses nous fait constater avec dépit que cette délégation viendrait au final bien à point et que, ne l'ayant pas mise en oeuvre, on se retrouve avec une évolutivité rendue beaucoup plus complexe que si l'on avait directement délégué correctement les taches

    En érigeant en loi le sacrosaint principe de la responsabilité unique, tu te rendras compte que ton projet pourra évoluer de manière bien plus simple et efficace.

    Il arrivera surement un moment où l'évolutivité de ton projet sera bloquée pour une raison ou une autre, mais ce moment arrivera beaucoup plus tard, et généralement pour des points pour lesquels tu auras, justement, jugé inutile de respecter ce principe
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par fabthegreat Voir le message
    Pourquoi ça? Je ne vais pas faire quelque chose de bien violent, un membre pointeur tout bête à partir duquel je pourrais appeler les méthodes. A moins qu'il y ait un soucis sous-jacent que je n'ai pas vu?
    Probablement. Sinon, tu n'aurais pas tant envi de les gérer à la main. Un peu de lecture : Présentation des pointeurs intelligents en C++ par Loïc Joly

    Citation Envoyé par fabthegreat Voir le message
    Il faut que je me renseigne sur cette idée de fabrique, mais n'est ce pas disproportionné pour un code qui ne va créer qu'un seul objet de chaque classe?
    Attention au vocabulaire. Fabrique désigne un DP bien identifié. Je pense plutôt à une classe dédiée à la construction des différents objets et au tissage de leur(s) lien(s). Cela s'apparenterait plus à un DP builder.
    Ce n'est jamais disproportionné de bien séparer les rôles pour : 1/t'y retrouver, 2/ diminuer le risque du bug lié au code spaghetti, 3/ ne pas insulter l'avenir si ton code est amené à évoluer.

Discussions similaires

  1. [Interaction WPF/C#]Reliè un evenement d'une classe a la fonction d'une autre classe
    Par TheBlackReverand dans le forum Windows Presentation Foundation
    Réponses: 9
    Dernier message: 23/11/2008, 22h24
  2. interaction swing et classe
    Par phobos64 dans le forum Agents de placement/Fenêtres
    Réponses: 6
    Dernier message: 11/11/2008, 16h28
  3. [MySQL][ADOdB] Interaction classes ADOdB / classes personelles
    Par Looping2605 dans le forum Requêtes
    Réponses: 10
    Dernier message: 12/03/2007, 21h43
  4. [N00b] Interactions de classes
    Par itechparadise dans le forum C++
    Réponses: 6
    Dernier message: 18/04/2006, 14h42
  5. [Language]Interaction entre class
    Par LordBob dans le forum Langage
    Réponses: 10
    Dernier message: 14/12/2005, 10h14

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