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

[POO] Demande d'information


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    161
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 161
    Points : 78
    Points
    78
    Par défaut [POO] Demande d'information
    Bonsoir,

    Je me pose plusieurs questions.

    Imaginons trois classes.

    La classe A dépend de la classe B qui dépend de la classe C qui dépend de la classe A.

    Est-qu'il vaut mieux initialiser les classes dans les constructeurs, dans le pramarètre passé au constructeur, d'utilisé un setter ??

    Est-qu'il peux arriver une sorte de récursion dans les objets ?

    Exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    class A {
    	private $var ;
     
    	public function __construct(B $b) {
     
    	}
    }
     
     
    class B {
    	private $var ;
     
    	public function __construct(C $c) {
     
    	}
    }
     
    class C {
    	private $var ;
     
    	public function __construct(A $a) {
     
    	}
    }
    ou bien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class A {
    	private $var ;
     
    	public function __construct() {
    		$this->var = new B() ;
    	}
    }
     
     
    class B {
    	private $var ;
     
    	public function __construct() {
    		$this->var = new C() ;
    	}
    }
     
    class C {
    	private $var ;
     
    	public function __construct() {
    		$this->var = new A() ;
    	}
    }
    Ou encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    class A {
    	private $var ;
     
    	public function __construct() {
     
    	}
     
    	public function setC(B $b) {
    		$this->var = $b ;
    	}
    }
     
     
    class B {
    	private $var ;
     
    	public function __construct() {
     
    	}
     
    	public function setC(C $c) {
    		$this->var = $c ;
    	}
    }
     
    class C {
    	private $var ;
     
    	public function __construct() {
     
    	}
     
    	public function setA(A $a) {
    		$this->var = $a ;
    	}
    }
    Par exemple si la classe A est un User, la classe B un Panier et la classe C un Produit.

    Je veux être en mesure depuis un User de consulter le contenu du panier qui sera une métohde sowContenu() du panier mais appeler du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $user = new User() ;
    $user->showContenu() ;
    Et c'est à ce moment où je me demande comment récupérer cette méthode.

    De même imaginons que la classe C soit des produits dans mon showPanier(), je veux récupérer la description de mes produits qui sera possible avec un getDescription() qui est une méthode de la classe Produit.

    Et on peux très bien envisager une méthode de User qui est besoin d'un objet Article.

    Et voila le serpent qui se mort la queue non ??

    Qu'en pensez vous ?

    Un retour d'expérience sur des projet mettant en relation de nombreuses classes serait le bienvenue.

    Très bonne soirée à tous.

    Fluxy__

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 448
    Points : 2 284
    Points
    2 284
    Par défaut
    Salut,

    Oui tu peux créer une récursion infinie avec des constructeurs qui en appellent d'autres.
    C'est d'ailleurs un problème que j'ai rencontré aujourd'hui même .....

    Par contre il n'y a pas de réponses toutes faites.
    Car c'est en fonction des dépendances émises par tes règles de gestion que tu vas décider comment implémenter la relation entre tes classes.
    En clair des fois tu n'auras pas d'autres choix que de le mettre en paramètre du constructeur, d'autres fois un mutateur sera suffisant.

    Dans un de tes exemples tu instancies dans le constructeur, ce type de situation parfaitement justifiable peut cependant engendrer une récursion.

    Il y à une méthode simple que tu peux utiliser pour éviter ce problème.
    Ne construire ton objet que lorsqu'il est effectivement demandé.
    Au lieu de le construire systématiquement en prévision d'une éventuelle utilisation.

    Pour cela il faut que tu utilises un getter, avec une condition, celle ci déterminera la nécessité, de reconstruire l'objet.
    En procédant ainsi tu ne construis l'objet que si c'est rééllement nécessaire.
    Aussi tu ne le construis qu'une et une fois pour la durée de vie de l'instance (plutôt pratique quand on génère une page web).

    Cette méthode est particulièrement efficace pour des objets qui proviennent d'une base de données.
    Car depuis ta bdd tu ne charges finalement que des identifiants (chaine de caracteres, entier ect).
    Ainsi, au lieu de charger tous les objets liés au moment où tu reçois le tuple sql, et éviter les constructions en cascade incontrolées.
    Il suffit de sauvegarder le tuple dans l'instance, l'instance disposeras alors de toutes les informations nécessaires pour identifier et construire les objets liés.
    Si par la suite l'instance doit fournir un objet avec lequel elle est liée, il suffit d'utiliser l'identifiant stocker plus tôt lors de la réception du tuple pour construire l'objet lié et le rendre.

    un exemple pour illustrer l'idée, non fonctionnel.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class A{
    public $id_b;
    protected $_b;
    public function __construct(){
    $this->id_b = null;
    $this->b = null;
    }
    public function getB(){
    if( $this->_b == NULL ) $this->_b = B::lireParId( $this->id_b );
    return $this->b;
    }
    public function construireDepuistuple( $tuple ){
    $this->__construct();
    $this->id_b = $tuple["id_b"];
    }
    }
    Pareil pour les autres classes.

    a plus

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    161
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 161
    Points : 78
    Points
    78
    Par défaut
    Tout d'abord, je tiens à te remericé d'avoir pris le temps de me répondre.

    J'ai tout de même quelques questions à ta lecture :

    Peux-tu m'expliquer ce qu'est un mutateur ?

    Je ne comprend pas bien l'exemple du tuple.

    Pour reprendre mon exemple, si j'ai besoin d'une description de produit dans mon panier, que me conseil tu ?

    Bonne soirée.

    Fluxy__

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 448
    Points : 2 284
    Points
    2 284
    Par défaut
    Salut,

    pas de souci.
    Mutateur -> setter
    Acesseur -> getter
    tuple -> ligne de résultats sql

    Citation Envoyé par http://fr.wikipedia.org/wiki/Base_de_données_relationnelle
    Dans la table PERSONNE ci-dessous, l’ensemble {PersID, nom, prénom, date_naiss, ville_naiss} est un ensemble d'attributs. Chaque attribut définit une information élémentaire à l’intérieur d’une ligne (aussi appelée tuple) de la table. Il ne peut exister deux fois le même tuple dans une relation. Les attributs sont parfois aussi appelés colonnes.

    C'est du bon français, quoi! Ici cela correspondrait à getB et setB

    Et bien pour suivre ton exemple, il faudrait le préciser. D'abord nous avons un panier, composé de ligne articles. Cet ensemble de ligne définit le contenu du panier.
    Ces lignes forment une composition avec le produit, et pas un héritage.
    On peut imaginer que la ligne article mis à part la description, pu, pt, qte ect, possédera la référence article.

    C'est cette référence qu'il faut que tu sauvegardes à réception du tuple. Ceci à la seule fin de ne pas construire immédiatement l'objet produit.
    Mais seulement, plus tard, au moment opportun.

    Pour ne construire l'objet produit qu'au moment opportun, il faut que tu utilises un getter comme expliqué plus haut.
    C'est lui qui vas se charger d'instancier l'objet et personne d'autre.

    Par la suite si tu veux connaître le visuel produit de la ligne, tu appelleras, par exemple
    $Ligne->getProduit()->someDataFromProduit;

    C'est une solution plutôt efficace, et pas trop moche.
    Mais on peut faire mieux.

    en utilisant les méthodes magiques et notamment __get et __set, tu pourrais imaginer re faire l'appel plus haut ainsi :
    $Ligne-> someDataFromProduit;
    Ou bien utiliser des getters de cette forme :
    $Ligne->someDataFromProduit();

    Chacun de ces deux nouveaux getter ce content d'appeler le getterProduit interne à la ligne pour obtenir l'objet produit, puis de rendre l'information.

    Cependant, une telle construction pose un problème.
    Car si je peux lire 10000 lignes en une requête, chacune de ces lignes provoquerait la création d'une requête supplémentaire si je dois afficher une information produit.
    Au final cela exécuterait pas moins de 1001 requêtes.... Pas idéale.

    Dans ces cas là, j'utilise une requête composé qui sait demander les deux informations simultanément.
    Avec un contrôleur spécifique qui sait construire l'ensemble des objets (ligne+produit) à réception des tuples sans utiliser de requêtes supplémentaire.

    Le reste du temps je me contente de me baser sur un système de cache.
    Ou sur le fait que je rencontre assez rarement ce cas avec une nécessité de performance importante.

    fin voila, en espérant ne pas trop m'éparpillé.

    aplus

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    161
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 161
    Points : 78
    Points
    78
    Par défaut
    Merci pour toutes ces précisions.

    Je vais suivre tes conseils.

    Très bonne soirée.

    Fluxy__

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

Discussions similaires

  1. Demande d'information pour ajout d'API Java dans eclipse
    Par BernardT dans le forum Eclipse Java
    Réponses: 6
    Dernier message: 07/07/2005, 17h08
  2. Demandes d'informations divers sur SGBD
    Par AlexB59 dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 26/05/2005, 12h41
  3. [ATL - ActiveX] demande d informations
    Par venomelektro dans le forum MFC
    Réponses: 7
    Dernier message: 22/03/2005, 20h09
  4. Réponses: 3
    Dernier message: 01/02/2004, 21h24

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