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 Delphi Discussion :

OOP : communication des variables fille -> mère


Sujet :

Langage Delphi

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut OOP : communication des variables fille -> mère
    Bonjour,

    Je suis face à un dilemme et j'aimerais connaître votre vision des choses d'un point de vue strictement objet (par opposition au point de vue "c'est plus pratique de faire ainsi " ) :

    Schématisons mon problème :

    • J'ai une TForm A sur laquelle je pose une grille et un certain nombre de composants. A fait quelques traitements de mise en page.
    • Une TForm B et une TForm C héritent de A
    • Ce qui différencie B et C est le nombre de lignes de la grille et l'indexe des champs communs aux deux dans celle ci. La grille dans B comporte 20 lignes et, par exemple, le libellé est sur la ligne 2. La grille dans C comporte 10 lignes et le libellé est sur la ligne 5
    • Dans B et C j'ai défini des constantes pour définir la position de chaque ligne. Par exemple j'ai une constantes POS_LIBELLE = 2 dans B est une POS_LIBELLE = 5 dans C. Ceci me permet de changer l'ordre de mes lignes selon la demande sans avoir à vérifier tout le code de B et C


    J'ai des traitements communs à faire sur B et C (exemple initialiser le libellé). Il serait dommage et inefficace qu'il y ait redondance de code. La logique serait donc de placer le code dans A. Mais comme A ne connaît pas la valeur de POS_LIBELLE il faut que je trouve un moyen de le lui transmettre. Je vois deux moyens :

    • Mettre des variables dans la section protected de A et les initialiser dans B et C. Simple mais à mon avis caca car on va initialiser 20 variables à la création de C alors que seules 10 seront nécessaires.
    • Je peux créer un accesseur en virtual abstract. Dans A j'appelle l'accesseur qui, déclaré dans la fille, me renverrait la valeur de la constante correcpondant. Ca me semble plus propre mais est-ce le cas ?


    Laquelle de ces deux méthodes est à votre avis la meilleur ?
    En voyez vous d'autres ?

    D'avance merci pour votre aide.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    En fait, c'est une bonne question
    Donc A, est une fenêtre fonctionnelle ou juste un modèle abstrait qui en sert qu'à B et C ???
    Si oui, tu peux donc considérer que la Gestion du libellé fait parti du fonctionnement de la fenêtre, ...
    Si tu surcharge la fonction Loaded ou le constructeur CreateNew, tu peux ajouter l'initialisation de POS_LIBELLE qui serait une propriété de A ... que tu modifie dans B et C ...
    Tu peux aussi faire un accesseur, mais si tu as bcp de paramètre, cela va alonger le code ... et finalement redondant car dans B et dans C, l'avantage c'est qui si un jour tu fais D, si tu oubies des trucs, cela te fera uen belle Erreur Abstraite ...

    Sinon, ayant fait de l'héritage de fenêtre, c'est sportif, faut penser que tu as surchargé tel ou tel méthode dans la variante C de A ..., en fait, avec le recul, pour la maintenance, c'est pas si terrible que cela, ... je préfère un modèle MVC, ou tu surcharge un controleur générique, la fenêtre n'étant qu'une coquille vide (Bouton, Grille, Event, tout fait appel au Controleur), et avec un petit jeu de polymorphisme du controleur (class of, constructeur virtuel, surcharge, ...), tu peux faire quelques choses d'assez sympa (et surtout, tu déconnecte le métier des fenêtres, cela éclairci le code ...)

    C'est un grand débat, c'est souvent, le temps, le bugdet, la méthode de travail d'une équipe de développement qui donne la façon de faire, pas forcément la meilleure mais la plus populaire ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Merci pour ta réponse.

    A est un modèle abstrait juste pour B et C

    Si je comprends bien tu me conseilles plutôt de passer la valeur POS_LIBELLE à A via la surcharge du constructeur dans B et C. Le "problème" est que j'ai 20 constantes dans B et 10 dans C. Admettons qu'entre B et C seules 7 constantes désignent le même type de ligne (libelle, valeur, total par exemple) ça ferait donc 7 paramètres + n paramères, 7 propriétés dans A et 7 variables à stocker. Par soucis de lisibilité je peux me débrouiller avec un "record".

    Si techniquement il n'y a pas d'argument "ça pue c'est mal" contre cette solution ou celle des accesseurs, il est vrai que celle ci me forcerait à initialiser mes valeurs sous peine de ne pas compiler. Encore que l'idée du record viendrait annuler cet effet Quelle prise de tête

    Je suis d'accord avec toi par rapport à l'héritage des Forms et les contraintes que ça implique. Ma méthode est d'ouvrir la mère et toutes ses filles avant de commencer quelque chose histoire de voir ce qui est vraiment vraiment commun, ce qui est surchargé et ce qui est propre à chaque fiche. Ca prend un peu de temps mais je le regagne au déboguage. On va dire que c'est mieux que rien

    J'ai découvert les joies du MVC il y a peu grâce à la prog cocoa + IB sur le mac et ça a fait naître en moi une certaine frustration par rapport au projet delphi sur lequel je bosse. Il est un peu tard pour "migrer" mais je sais qu'à mon prochain gros projet ça sera mon "modèle" de développement !

    En tout cas merci pour ton conseil et la rapidité de ta réponse. Ca permet de moins douter

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par Pleinpopossum
    Le "problème" est que j'ai 20 constantes dans B et 10 dans C
    Là c'est un problème de conception, ... faut juste prend du recul

    A à une fonction RemplirGrille, qui ne connait que 7 options communes à B et C, ça c'est le fonction de Base

    B surcharge RemplirGrille, qui appele "Inherited RemplirGrille" puis ensuite gère ses 13 options restantes

    C surcharge RemplirGrille, qui appele "Inherited RemplirGrille" puis ensuite gère ses 3 options restantes

    Bon, RemplirGrille c'est un peu trop large, disons qu'il faut que tu découpes à la fonction la plus unitaire (Insérer Ligne, Modifier Ligne) ...

    A c'est ta boite à outil, les codes génériques (avec paramètres, n'oublie pas que l'on peut passer des paramètres aux fonctions, pas besoins d'avoir des globales hideuses partout), puis B et C appèle ces fonctions les unes après les autres dans l'ordre qu'ils veulent ... c'est tout l'art de la POO, faire un code modulaire qui impose une rigueur souvent la clé de fiabilité et d'une maintenance faible (pense à documenter l'imbrication des classes entre-elles, ...)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Hum en fait j'ai été moins précis dans mon second message que dans mon premier . Je pense à peu près bien maîtriser la notion de "tronc commun" (A) puis de complément dans des méthodes ou fonctions overridées (dans B ou C)

    Je vais te présenter un problème analogue au mien mais simplifié pour que ça ne fasse pas des pages et des pages :


    • A est une TForm avec une grille vierge
    • B hérite de A donc de sa grille vierge. Je la spécialise en mettant par exemple un libellé en row 0, un prix d'achat en row 1, un coef de marge en row 2 et un prix de vente en row 3.
    • C hérite de A et j'ai un libellé en row 0, une marque en row 1, une référence fournisseur en row 2, un prix de vente en row 3, un prix d'achat en row 4, une remise 5, une différence en row 6, un coef de marge en row 7


    Tu remarques qu'il y a des champs communs entre B et C mais qu'ils ne sont pas sur la même row en B et en C. Il n'y a pas non plus de "logique" de placement. On ne peut par exemple pas dire "ce qui est en C est ce qui est en B mais décalé d'une ligne". Je n'ai pas le droit de repositionner les lignes pour que ça m'arrange (ça va sans dire )

    J'ai des traitements analogues à faire sur B et C. Par exemple je veux que si le prix de vente est inférieur au prix d'achat, celui ci s'affiche en rouge. Je veux aussi que lorsqu'on modifie le prix de vente, le coef de marge se recalcule etc etc

    Pour simplifier mon code au cas où on me demanderait de permuter des lignes, j'ai déclaré des constantes représentant le numéro de ligne respectivement dans B et C. exemple : POS_LIBELLE=0 dans B et C. POS_PRIXACHAT=1 dans B et POS_PRIXACHAT=4 dans C.

    Pour faire les traitements j'ai par exemple un événement OnGetCellColor(ACol, ARow, CoulFont). L'idéal serait de l'implémenter dans A et schématiquement de dire "si pour ACol la valeur en POS_PRIXVENTE est inférieure à la valeur en POS_PRIXACHAT alors CoulFont=clRed.

    Actuellement j'ai déclaré en virtual abstract une procédure Compare(ACol,CoulFont) dans A que j'appelle depuis l'événement OnGetCellColor de A. Je l'override dans B et C pour avoir accès à mes constantes. Mais c'est un peu bête car au mieux je redéclare une fonction qui fait la comparaison dans A en lui passant les valeurs récupérées dans la version overridée de B et C, au pire j'ai redondance de code pour faire la comparaison dans Compare(ACol,CoulFont) de B et Compare(ACol,CoulFont) de C

    B et C ont quelques fonctions propres qui les spécialisent donc pas moyen de déporter les constantes dans A.

    Sachant tout ça je reformule ma question initiale : pour remédier à ce charivari ne devrais je pas passer par exemple lors de la création des objets B et C, chaque constante à de B vers A et de C vers A pour que A connaisse la position de mes lignes pour que OnGetCellColor soit implémenté dans A et uniquement dans A ?

    Alternativement ne serait-il pas plus propre de faire deux fonctions virtuelles abstraites dans A : GetPOS_PRIXVENTE et GetPOS_PRIXACHAT. Ces deux fonctions seraient overridées dans B et C pour renvoyer la valeur des constantes POS_PRIXVENTE et POS_PRIXACHAT. Ainsi je pourrais dans A implémenter OnGetCellColor qui s'informerait via GetPOS_PRIXACHAT de la position de la ligne où récupérer la valeur. Je maintiens l'encapsulation et effectivement je n'ai pas plein de variables globales d'un goût douteux...

    J'espère ne pas avoir été trop brouillon dans mes explications. Si tu veux je peux concocter un petit code pour que ça soit plus clair, le projet "réel" étant trop volumineux.

    Merci pour ton avis

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Dans le doute et ayant déjà une base fonctionnant je vais appliquer la règle du TPCM (touche pas ça marche) en attendant d'avoir les idées plus claires.

    a+

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    lol, le TPCM, celui-là, je le note !

    Effectivement, si tu n'as pas les idées claires, mieux vaut ne pas aller trop loin, personnel, j'étais à bout d'idées pour t'aider n'ayant pas l'existant sous les yeux !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Si par curiosité tu veux y jeter un oeil j'ai fait trois exemples

    • Actuellement est une reproduction extrèmement simplifiée du programme tel qu'il est fait aujourd'hui
    • Amélioration A est la version correspondant à ton premier conseil à savoir initialiser des variables et les utiliser depuis la mère
    • Amélioration B est la technique que j'avais suggéré (utilisation de fonctions virtuelles abstraites pour accéder aux valeurs dans la fille)


    Si tu as un nouvel avis je reste preneur pour la prochaine fois où je serai confronté à ce genre de problème.

    A+

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Effectivement, cela me fait penser au code que j'ai pour une application de gestion commerciale ... avec héritage de fenêtre, il y a tellement de méthode abstraite ou virtuelle que c'est quand même compliqué de toujours penser à vérifier que l'un de 3 descendants peu surcharger le traitement par défaut ...

    Que ce soit par Create ou par Accesseur, c'est plus une question de style ou d'humeur, j'aurais utiliser l'un ou l'autre selon la méteo du jour ...

    PS : J'ai vu les zip, tu peux les supprimer, vu que je semble le seul à suivre
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bon je suis content de voir qu'il est normal d'avoir des "humeurs" de programmation

    Merci pour ton attention et j'espère pouvoir un jour te rendre la pareille.

    Bonne continuation

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. conception d'une classe mère et des classe filles
    Par IAGISG dans le forum Diagrammes de Classes
    Réponses: 1
    Dernier message: 19/02/2014, 19h53
  2. Spliter une ligne excel en 1 table mère et des tables filles
    Par Sfeabg dans le forum Développement de jobs
    Réponses: 0
    Dernier message: 15/09/2009, 17h22
  3. Passage variable classe fille -> classe mère
    Par Vincent F dans le forum C#
    Réponses: 4
    Dernier message: 13/07/2009, 17h46
  4. Réponses: 1
    Dernier message: 13/09/2007, 13h25
  5. Réponses: 4
    Dernier message: 18/07/2002, 13h32

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