Aux spécialistes de la POO

Le
I.G.LOG
Bonjour,

Je m'interroge depuis longtemps sur un problème que je vais essayer de vous
exposer :
J'ai développé une appli commerciale, dans laquelle je gère devis,
commandes, factures etc.
Dans la base, ces documents sont stockés avec un identifiant IDTYPE, qui me
donne le type de document (devis, facture )
Finalement, les documents ont toujours la même structure, cad un corps et
des lignes associées.
J'ai donc créé une classe document "générique", qui mémorise n'importe quel
type de document.

En revanche, lors de l'enregistrement (création, modification ou
suppression) les traitements sont différents selon le type de document.
Pour gérer ces cas, j'ai créé des classes différentes, et au moment de
l'enregistrement je delègue (delegate), avec le code suivant:

// Enregistrement du document
document:mEnregistre()

lObj est un objet dynamique

selon :IDTYPE
cas "Devis"
lObj = allouer un Devis
cas "Facture"
lObj = allouer un Facture

fin

// Delegate
lObj:mEnregistre()

RETOUR


Bref, je ne sais pas si ce mode de fonctionnement est "optimal" (en temps,
lors des instanciations par exemple etc.)

D'où mes questions:
- En POO, peut-on substituer un objet à un autre à un moment donné ? Et, si
oui, comment ?
- Dans la méthode document:mEnregistre(), j'avais initialement testé le
type, et en fonction de ce type appelé différentes méthodes de document (si
:Type = "Devis" alors :mEnregistreDevis() ). La classe document était alors
beaucoup plus conséquente (avec toutes les méthodes pour chaque type).
Quelle méthode est la plus efficace, en matière de performance ?
- Voyez-vous une méthode plus "POO" pour gérer ce cas ?

Merci à tous
Questions / Réponses high-tech
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
JBD
Le #25162552
Le 21/01/2013 17:17, I.G.LOG a écrit :
Bonjour,

Je m'interroge depuis longtemps sur un problème que je vais essayer de vous
exposer :
J'ai développé une appli commerciale, dans laquelle je gère devis,
commandes, factures etc.
Dans la base, ces documents sont stockés avec un identifiant IDTYPE, qui me
donne le type de document (devis, facture ...)
Finalement, les documents ont toujours la même structure, cad un corps et
des lignes associées.
J'ai donc créé une classe document "générique", qui mémorise n'importe quel
type de document.

En revanche, lors de l'enregistrement (création, modification ou
suppression) les traitements sont différents selon le type de document.
Pour gérer ces cas, j'ai créé des classes différentes, et au moment de
l'enregistrement je delègue (delegate), avec le code suivant:

// Enregistrement du document
document:mEnregistre()

lObj est un objet dynamique

selon :IDTYPE
cas "Devis"
lObj = allouer un Devis
cas "Facture"
lObj = allouer un Facture
...
fin

// Delegate
lObj:mEnregistre()

RETOUR


Bref, je ne sais pas si ce mode de fonctionnement est "optimal" (en temps,
lors des instanciations par exemple etc.)

D'où mes questions:
- En POO, peut-on substituer un objet à un autre à un moment donné ? Et, si
oui, comment ?
- Dans la méthode document:mEnregistre(), j'avais initialement testé le
type, et en fonction de ce type appelé différentes méthodes de document (si
:Type = "Devis" alors :mEnregistreDevis() ). La classe document était alors
beaucoup plus conséquente (avec toutes les méthodes pour chaque type).
Quelle méthode est la plus efficace, en matière de performance ?
- Voyez-vous une méthode plus "POO" pour gérer ce cas ?

Merci à tous





Bonjour, mes meilleurs vœux

Pour ta représentation tu peux utiliser la notion d'héritage et les
méthodes virtuel.

Exemple :
----------------------
Class document
// le nécessaire pour gérer un document
fin

méthode virtuel mEnregistre()
// prépare ici tous ce qui commun à la gestion des document
fin
-------------------

Ensuite

----------------
Class devis
hérite de document
// le nécessaire pour gérer les spécificité du devis
// le reste étant issu de document.
fin

méthode virtuel mEnregistre() //surcharge mEnregistre de document
// initialisation propre au devis
ancetre:mEnregistre() //appel à mEnregistre de document
//Cela prépare les éléments génériques
//Ensuit Ici le spécificité de devis.
fin
--------------------

Class facture
hérite de document
// le nécessaire pour gérer les spécificité de la facture
// le reste étant issu de document.
fin

méthode virtuel mEnregistre() //surcharge mEnregistre de document
// initialisation propre à la facture
ancetre:mEnregistre() //appel à mEnregistre de document
//Cela prépare les éléments génériques
//Ensuit Ici le spécificité de la facture.
fin
--------------------

Cela ne sera pas plus rapide en temps de traitement et au niveau
performance, mais cela sera plus claire pour la gestion.
De plus avec la notion de polymorphisme tu peut faire le code suivant :

tbl est un tableau de 10 document

pour i=1 a 10
tbl[i]=genere_interface()//génére un devis ou une facture
fin
//...
pour i=1 a 10
tbl[i]:mEnregistre()
//trouve tous seul si il faut enregistrer un devis ou une facture
fin

Voila...
Bon courage

J.B.D.
I.G.LOG
Le #25163172
Bonjour,
Tout d'abord merci pour ta réponse.
Mais mon problème est d'ordre plus général.
La question serait: peut-on faire un "cast" d'objet !?
Concrètement, voici un exemple de code pour illustrer ce besoin:

Je liste tous les documents d'un même client, que je mémorise dans une
table, grâce à l'identifiant document (IDDOCUM).
En double-cliquant sur une ligne, j'entre en mode saisie document, comme
suit:

// Variables
lDoc est un document // Objet générique

// Affichage
select IDDOCUM from docum where IDCLIENT = 150
tantque sqlfetch("req") = 0
tableajouteligne(TABLE,description,IDDOCUM) // Ident. document
fin
sqlferme("req")

// Double-clic, on ouvre le document pour saisie
lDoc:Charge(IDDOCUM) // à ce moment, pas de type de document !!!
ouvre("fen_Saisie",lDoc) // Saisie

// Validation dans la fenetre de saisie
lDoc:Enregistre() // Il faudrait que lDoc soit un
objet facture, devis...


Le problème est que, lorsque je charge le document, je ne sais pas encore
quel est son type.
Je ne le connais qu'après avoir lu les données.
Bien sûr, j'aurais pu mémoriser le type dans la table initiale. Mais c'est
lourd, et il faudrait que je modifie tous les traitements de l'appli dans
lesquels je parcours les documents.
Voilà pourquoi je cherchais un moyen de transformer un objet en un autre,
dynamiquement, à un moment donné (ici, lorsque je connais le type, cad dans
la méthode lDoc:Charge() )

Je crois finalement que ce n'est pas possible.
Mais je cherchais une solution plus "générale objet".

Encore merci
Phil
JBD
Le #25165332
Le 23/01/2013 08:02, I.G.LOG a écrit :
Bonjour,
Tout d'abord merci pour ta réponse.
Mais mon problème est d'ordre plus général.
La question serait: peut-on faire un "cast" d'objet !?
Concrètement, voici un exemple de code pour illustrer ce besoin:

Je liste tous les documents d'un même client, que je mémorise dans une
table, grâce à l'identifiant document (IDDOCUM).
En double-cliquant sur une ligne, j'entre en mode saisie document, comme
suit:

// Variables
lDoc est un document // Objet générique

// Affichage
select IDDOCUM from docum where IDCLIENT = 150
tantque sqlfetch("req") = 0
tableajouteligne(TABLE,description,IDDOCUM) // Ident. document
fin
sqlferme("req")

// Double-clic, on ouvre le document pour saisie
lDoc:Charge(IDDOCUM) // à ce moment, pas de type de document !!!
ouvre("fen_Saisie",lDoc) // Saisie

// Validation dans la fenetre de saisie
lDoc:Enregistre() // Il faudrait que lDoc soit un
objet facture, devis...


Le problème est que, lorsque je charge le document, je ne sais pas encore
quel est son type.
Je ne le connais qu'après avoir lu les données.
Bien sûr, j'aurais pu mémoriser le type dans la table initiale. Mais c'est
lourd, et il faudrait que je modifie tous les traitements de l'appli dans
lesquels je parcours les documents.
Voilà pourquoi je cherchais un moyen de transformer un objet en un autre,
dynamiquement, à un moment donné (ici, lorsque je connais le type, cad dans
la méthode lDoc:Charge() )

Je crois finalement que ce n'est pas possible.
Mais je cherchais une solution plus "générale objet".

Encore merci
Phil





Dans ce cas tu fait de ta méthode "charge" de la classe document une
méthode de classe qui va fabriquer des instances de classe qui hérite de
document.

ex:
dans la classe document
Methode global charge(identifiant)

// recherche générique en base de données des info
selon nature_du_document
cas "devis"
mon_devis est un devis
mon_devis:charge(identifiant)
renvoyer mon_devis
cas "facture"
ma_facture est une facture
ma_facture:charge(identifiant)
renvoyer ma_facture
...

fin

Je reprend ton exemple :

// Double-clic, on ouvre le document pour saisie
lDoc:Charge(IDDOCUM) // à ce moment, pas de type de document !!!
ouvre("fen_Saisie",lDoc) // Saisie



il devient

ldoc est un document

ldoc= document::charge(IDDOCUM) // le charge te renvoie une instance
// de la nature voulu

// Validation dans la fenetre de saisie
lDoc:Enregistre() // Il faudrait que lDoc soit un objet facture, >


// devis...

et la tu change rien tu bénéficie du polymorphisme.

Je ne sais pas si cela fonctionnera aussi simplement en windev, dans le
doute travail avec des allocation dynamique :

ldoc est un document dynamique

tu gère alors toi même les allocations dans la méthode charge
modifié comme suis :

Methode global charge(identifiant)

// recherche générique en base de données des info
selon nature_du_document
cas "devis"
mon_devis est un devis dynamique
mon_devis=allouer un devis
mon_devis:charge(identifiant)
renvoyer mon_devis
cas "facture"
ma_facture est une facture dynamique
ma_facture=allouer un devis
ma_facture:charge(identifiant)
renvoyer ma_facture
...

fin

il faudra penser alors à libérer la mémoire quand tu n'a plus besoin de
l'objet.

liberer ldoc

Cela correspond au pattern de l'usine. tu as une méthode qui te produit
des instances de classe issu d'une classe mère commune. Ensuite tu
utilise les méthodes défini sur la classe mère sans te soucier de la
nature réel de l'objet que tu as, car le polymorphisme, par la surcharge
des méthodes virtuel, fait le boulot à ta place.

Voila, bon courage.
J.B.D.
I.G.LOG
Le #25167232
tu gère alors toi même les allocations dans la méthode charge
modifié comme suis :

Methode global charge(identifiant)

// recherche générique en base de données des info
selon nature_du_document
cas "devis"
mon_devis est un devis dynamique
mon_devis=allouer un devis
mon_devis:charge(identifiant)
renvoyer mon_devis
cas "facture"
ma_facture est une facture dynamique
ma_facture=allouer un devis
ma_facture:charge(identifiant)
renvoyer ma_facture
...

fin

il faudra penser alors à libérer la mémoire quand tu n'a plus besoin de
l'objet.

liberer ldoc

Cela correspond au pattern de l'usine. tu as une méthode qui te produit
des instances de classe issu d'une classe mère commune. Ensuite tu utilise
les méthodes défini sur la classe mère sans te soucier de la nature réel
de l'objet que tu as, car le polymorphisme, par la surcharge des méthodes
virtuel, fait le boulot à ta place.




Bonsoir,
Oui, c'est une idée géniale !!!
Je vais essayer de la mettre en pratique.
Un grand merci à toi de m'avoir mis sur cette piste.
Cordialement
Phil
Publicité
Poster une réponse
Anonyme