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

Qt Discussion :

[Conception] Héritage en losange : maladresse ou nécessité ?


Sujet :

Qt

  1. #1
    Membre éclairé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Par défaut [Conception] Héritage en losange : maladresse ou nécessité ?
    Bonjour tout le monde,

    cherchant à effectuer une conception propre et optimale de mon application, j'aimerais avoir vos conseils avisés sur un point en particulier.

    La partie de mon application concernée est une vue dans laquelle je vais dessiner des figures (rectangle, polygone, cercle) qui héritent initialement de la class QGraphicsObject.

    (J'ai choisi de ne pas utiliser par exemple QGraphicsRecItem pour mon rectangle par soucis de conception comme vous allez le voir).

    Brièvement, voici les spécificités des figures liées à mon problème :

    Figure :
    i) Possède un état : Création, Sélection, Edition, Désélection.
    ii ) Réimplémentation de mouseMoveEvent pour un mouvement de translation.

    Rectangle :
    i) Formé de 4 points (class Point) et de 4 arêtes (class Edge)
    ii) Gestion de l'événement hoverMoveEvent pour changer l'aspect d'un curseur en mode édition
    iii) Déplacement d'un edge tel que les quatre angles restent droits

    Polygon :
    i) Zone fermée formée d'une liste de points et d'une liste de edges
    ii) Réimplémentation de hoverMoveEvent pour changer l'aspect du curseur en mode édition
    iii) Suppression d'un point
    iv) Insertion d'un point sur un edge
    v) Déplacement d'un edge

    Polyline :
    i) Zone ouverte formée d'une liste de points et d'une liste de edges
    ii) Suppression d'un point
    iv) Insertion d'un point sur un edge
    v) Déplacement d'un edge

    ----------

    Comme vous pouvez l'observer ici, le polygone a un comportement qui me pose problème. Je vous présente tout d'abord mon idée :

    1) Rectangle, Polygon et Polyline sont composés de points et de edges (Composants graphiques) donc je créé une classe parent AbstractPolylineStructure avec certaines méthodes comme addEdge().

    2) Une suppression de points ainsi qu'une insertion est possible avec les polygones et les polylines, je définis donc une class parent AbstractPolylineBehaviour possèdant entre autre ces méthodes.

    3) Rectangle est une polylineStructure particulière avec un déplacement des edges particuliers (conservation des angles droits). Je le mets donc à part dans un premier temps.

    Mon problème cependant, c'est que mon rectangle et mon polygone ont des aspects similaires comme leur "zone de sélection" définit par le polygone formé par les points qui les constituent ou encore le changement d'apparence du curseur au survol de cette zone.

    J'aurais donc envie de les rapprocher... Le problème est que si je le fais, je me confronte à un héritage en losange. Non pas que ça me déplaise mais c'est un héritage assez particulier qui fait l’œuvre de nombreuses critiques. Je me demande donc si le fait de me retrouver confronter à un héritage de ce type vient d'une maladresse dans la conception de mon application ou si je n'ai vraiment pas le choix dans mon cas.

    Voici en pièce jointe une partie du diagramme de classes avec l'aspect des figures.

    J'attends vos précieux conseils afin de progresser dans ma conception et la rendre ainsi plus optimale

    Merci beaucoup !
    Images attachées Images attachées  

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Maladresse ?

    J'ai pas le temps de voir en détail mais j'ai déjà des remarques :
    - QGraphicsObject utilise déjà l'héritage multiple, ça commence à faire beaucoup d'héritage multiple dans l'histoire
    - Pourquoi dériver de QGraphicsObject et pas QGraphicsItem ? Et pourquoi pas de QGraphicsPolygonItem, QgraphicsRectItem, etc. ?
    - Pourquoi rectangle n'hérite pas de polygon ?
    - du coup, les propriétés hérités de abstractpolylinebehavior dans polygon peuvent remonter dans polylinestructure, non ?
    - je suppose que quand tu parles de classes Edge et Point, ce sont des items "à l'écran" permettant de manipuler tes poly point par point ?

    Tu n'aurais pas intérêt à séparer en plusieurs structures pour respecter le SRP ? (comme le fait un peu Qt) :
    - un structure contenant tes points (QPolygon) = représentation mathématique
    - des structures correspondant à tes items (polygonitem, polylineitem, rectitem) = représentation "à l'écran"
    - une (des?) structure pour manipuler tes objet (ajouter, déplacer et supprimer des points)

  3. #3
    Membre éclairé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Par défaut
    Salut gbdivers et merci pour ton intervention

    - Pourquoi dériver de QGraphicsObject et pas QGraphicsItem ?
    Mes figures communiquent également avec leurs composants (points, edges). J'ai donc besoin des signaux et des slots d'où mon besoin d'hériter de QObject aussi et d'où l'héritage de QGraphicsObject ...

    Et pourquoi pas de QGraphicsPolygonItem, QgraphicsRectItem, etc. ?
    Au début, j'avais hérité de QGraphicsPathItem par exemple pour ma polyline. Je me suis ensuite dis que si j'ai besoin de déplacer un segment de ma polyline seulement, se serait plus intuitif de rendre indépendant chaque segment de ma polyline. D'où mes structures construites par composants Edge/Point avec signal/slot.

    Du coup, je n'ai même pas besoin d'avoir un QGraphicsPathItem avec par exemple un méthode path() définies dedans étant donné que je me sers de ces structures simplement comme de conteneurs.

    - Pourquoi rectangle n'hérite pas de polygon ?
    En effet se serait le plus logique. Seulement dans mon cas, le polygon peut par exemple supprimer un de ses points. Je ne peux donc pas hériter directement de lui, mon rectangle n'ayant pas le droit à la suppression de points.

    - du coup, les propriétés hérités de abstractpolylinebehavior dans polygon peuvent remonter dans polylinestructure, non ?
    Je ne comprends pas bien ta question ici. Dans abstractpolylinebehavior, je définis par exemple le slot removePoint() ou encore removeLastEdge() et réimplémente les slots virtuels purs de abstractpolylinestructure comme followPointMotion ou followEdgeMotion (différents pour Rectangle). Pour les membres, ils sont protégés et proviennent surtout de abstractpolylinestructure (QList<Edge*>, la class Edge permettant l'accès à ses deux extrémités Point (Point* getP1() ...)).

    - je suppose que quand tu parles de classes Edge et Point, ce sont des items "à l'écran" permettant de manipuler tes poly point par point ?
    C'est ça oui. Point est un objet graphique qui représente un carré et Edge une arête de mes structures. Ces deux composants connaissent la structure à laquelle ils apprtiennent et une communication signal/slot est établie avec elle pour les déplacements/suivi. Aussi, par exemple, un clic sur un edge sélectionne toute la structure à laquelle il appartient.

    Tu n'aurais pas intérêt à séparer en plusieurs structures pour respecter le SRP ?
    Joker ? :p Qu'entends-tu par SRP ? J'ai encore beaucoup à apprendre

    J'allais te répondre sans lire la dernière phrase : "Si je créé des structures pour mes objets graphiques, je vais être obliger de les manipuler dans ma class Scène, ce qui va l'alourdir énormément. J'ai voulu suivre tes conseils d'un post assez vieux dans lequel tu conseillais de redéfinir les comportements dans les items même". Après en effet, en faisant des structures pour les mouvements/comportements, ma réponse ne sera pas la même :p Mais je ne suis pas très familier de cette manière de faire. Je ne vois pas trop comment m'y prendre pour le moment.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Février 2010
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2010
    Messages : 243
    Par défaut
    Si point et edge sont les seuls à apparaître à l'écran, ce sont les seuls à devoir hériter de QGraphicsObject (item ou autre);

    Tes classes rectangle, polygon et polyline représentent des objets mathématiques, un modèle. Pas une vue graphique. Cette partie devrait avoir son arbre d'héritage à part en dehors des complications liées aux graphics item que sont les points et les edges.

    Un rectangle est constitué de 4 points et 4 bords : agrégation et connexion signaux-slots pour faire évoluer le modèle en réaction au déplacement souris des points, répercussion éventuelle sur les points voisins pour garder les angles droits etc.

    Qu'en penses-tu ?

  5. #5
    Membre éclairé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Par défaut
    Salut ness522

    Ta proposition est tentante!

    Seulement, si j'ai redéfini mes Figures comme des QGraphicsItem, c'est aussi parce que j'ai besoin de leur définir une zone (via shape()) par exemple pour cliquer à l'intérieur et pouvoir gérer les événements souris (clics, déplacements à l'intérieur de la figure ...). J'ai besoin de garder cette "existence physique" dans ma scène pour que celle-ci les considère dans leur globalité.

    Comment garder ce comportement sans hériter de QGraphicsItem ?

    Après c'est clair que justement, la fonction paint de mes figures reste vide car le rendu est déjà effectué par les composants !

  6. #6
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Février 2010
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2010
    Messages : 243
    Par défaut
    Je pense qu'on peut garder la même philosophie, à côté des points et des edges il y a un item supplémentaire qui gère la forme et les interactions voulues.

    Il envoie par signaux les modifications auquels il est soumis (déplacement, clics, etc) et ses copains les points et les edges dans la figure réagissent en conséquence (se déplacent en même temps).

    Mon idée à la base est de ne pas mélanger (via héritage) les classes qui gère l'affiche de celles qui gèrent la logique des formes. (mais c'est vite dit :p)

    A toi de choisir l'idée qui te convient le mieux

  7. #7
    Membre éclairé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Par défaut
    Salut ness522 !

    Ton idée est plaisante mais j'aurais quelques questions pour la préciser un peu plus :

    - En gros tu veux créer un nouveau QGraphicsItem qui va juste être un "shape()" en prenant en compte la position des edges de la structure et gérer aussi les interactions comme un clic dans la zone qu'elle définie et un déplacement de la souris pour translater l'ensemble ?

    - Si oui, En gros ton item est mon Rectangle puisque il aura besoin de la liste de edges pour définir sa zone et des interactions. La class Rectangle dans ton cas n'aurais plus vraiment un rôle à jouer puisque tout serait géré dans la nouvelle class qui définie la zone et qui lui serait au final similaire non?

  8. #8
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Février 2010
    Messages
    243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2010
    Messages : 243
    Par défaut
    1. oui en effet
    2. oui et non, mais tu as raison. A faire trop de conception on tourne en rond

    Du coup essayons de voir les choses de manière pragmatiques :

    Est-ce que ton énoncé (polygon - polyline - rectangle) est complet ?
    Si oui, on arrête de se prendre le chou, on fait 3 classes, on fonce, on copie colle salement ce qu'il faut et basta. Dans ce cas on va essayer de factoriser 3 comportements communs similaires alors qu'on a que 3 objets au final, c'est un peu se chatouiller pour se faire rire.

    Si maintenant, tu veux avoir des triangles, des hexagones réguliers ... et qu'au total on a 25 figures ça devient intéressant de faire les choses comme il faut. Alors on pourrait essayer de commencer par lister les figures, leurs comportements voulus et puis voir ce qu'on peut en sortir comme classes et comme héritage.

    De mon expérience, j'ai jamais eu une conception parfaite dès le départ. T'en prend une qui te va avec les données connues du problème, puis 2 semaines plus tard on vient te dire : "ce serait bien que ..." et t'es bon pour bidouiller un truc de non prévu. Au dixième coup, tu arraches et tu recommences en connaissance de cause

  9. #9
    Membre éclairé
    Avatar de betsprite
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    472
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 472
    Par défaut
    Oui mon énoncé est complet pour l'application que j'envisage de faire. Après tu as raison, dans ce cas je veux peut être sortir "l'artillerie lourde" pour rien :p

    En fait c'est plus dans un soucis de bien faire les choses. Je ne pense pas que j'aurais à revenir sur cette conception pour rajouter un élément mais je veux bien faire les choses pour m'habituer et travailler ma logique de conception en quelque sorte.

    Telle que je l'ai présenté, je peux m'en tirer même sans faire d'héritage en losange avec un comportement identique à celui que j'attends. Mais contrairement à l'utilisateur qui ne voit rien (si ce n'est pas moi ^^), je connais parfaitement la conception et sais donc si elle a été faite proprement ou non. Si ce n'est pas le cas, j'ai toujours ce soucis d'optimisation :p

    Ici par exemple, comme l'a souligné gbdivers dans la première réponse, il semble bien y avoir une maladresse dans la conception pour ce que j'envisage de faire. Et je ressens cette maladresse à plusieurs niveaux dont un que tu as abordé : l'absence de rendu visuel de mes structures.Après il y a aussi ce comportement du polygon qui est partagé entre le rectangle et la polyline, sans que le rectangle puisse être complètement définit comme un polygon dans son comportement...

Discussions similaires

  1. [Conception] héritage et overriding
    Par DranDane dans le forum Algorithmes et structures de données
    Réponses: 5
    Dernier message: 11/02/2008, 10h48
  2. Conception : héritage et instanceof
    Par herve91 dans le forum Langage
    Réponses: 10
    Dernier message: 05/12/2006, 17h11
  3. Conception: héritage d'une classe abstraite
    Par Kikito dans le forum Langage
    Réponses: 19
    Dernier message: 05/10/2006, 17h36
  4. [conception] Héritage comment faire ?
    Par bohor2gannes dans le forum Modélisation
    Réponses: 11
    Dernier message: 15/02/2006, 17h35
  5. [heritage][conception]héritage multiple en java!
    Par soulhouf dans le forum Langage
    Réponses: 9
    Dernier message: 25/08/2005, 20h03

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