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 :

structure d'une classe qui communique avec une autre [POO]


Sujet :

Langage PHP

  1. #1
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut structure d'une classe qui communique avec une autre
    Bonjour,

    j'ai une classe (C1) dont une méthode doit lancer une méthode d'une autre classe (C2). Pour ce faire la classe C1 instancie l'autre classe (C2) pour en créer un référent puis appelle sa méthode :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ref_model_CVSImport = new CSVImport();
    $ref_model_CVSImport->uploadFile($this->filepath);
    Par contre, j'ai lu, donc me demande si ça serait mieux que si une classe C1 communique avec une autre (C2), il vaudrait mieux que le référent vers C2 soit un attribut de C1. Quel est votre avis ?

  2. #2
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    submergé par les réponses , j'ai finalement décidé de mettre tous les référents de classe en attributs car quand on relit le code, c'est beaucoup plus clair : on voit des attributs private $ref_xxx, donc on sait tout de suite avec quelles classes la classe présente communique.

  3. #3
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 692
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 692
    Points : 20 243
    Points
    20 243
    Par défaut
    C'est important d'éviter de lier tes classes entre elle trop fortement.

    Quand C1 fait un new C2 dans une de ses méthode tu créer un couplage fort entre ces 2 classes. (sous entendu que C1 ne peut plus exister sans C2)
    Au contraire quand tu injecte C2 dans C1 (via le constructeur par exemple) ta classe C1 n'as pas besoin de connaitre les problématiques d'instanciation de C2 et ne sera pas impactée en cas de changement.

    Donc :
    Pas bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class C1 {
    	public function foo() {
    		$c2 = new C2();
    		$c2->bar();
    	}
    }
    Mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class C1 {
        private C2 $c2;
     
    	public __construct(C2 $c2) {
    	    $this->c2 = $c2;
    	}
     
    	public function foo() {
    		$this->c2->bar();
    	}
    }

  4. #4
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Ouh là, là, tu me fais prendre conscience d'une grosse erreur de conception

  5. #5
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Je suis embêté pour implémenter ta solution : en effet dans ta solution "mieux" tu passes en argument du constructeur de C1 un référent vers C2. Autrement dit, il faut avoir créé C2 avant C1 pour que ce référent existe. Donc même si le new C2(); n'est pas dans C1, il faut le mettre quelque part. Mais où ?

  6. #6
    Membre expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 793
    Points : 3 063
    Points
    3 063
    Par défaut
    Un truc du genre...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $c1 = new C1(new C2());$c1->run();
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $c2 = new C2();
     
    $c1 = new C1($c2);
    $c1->run();

  7. #7
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Merci pour ta réponse, cavo789, que je vois que ce matin.

    Mais pour faire comme tu dis, compliqué : en effet, supposons que C1 soit appelé par le routeur suite à une demande utilisateur mais que C2 (dont C1 a besoin pour s'exécuter) n'est qu'une classe utilitaire que l'utilisateur ne voit jamais (donc ne va pas provoquer sa création), qui va avoir la responsabilité de faire $c2 = new C2(); ? (sachant que quand l'utilisateur va faire sa demande qui va conduire à la création de C1, il faudra que C2 soit déjà créée).

  8. #8
    Membre expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 793
    Points : 3 063
    Points
    3 063
    Par défaut
    Bonjour

    Désolé mais ça, c'est ta logique métier qui va définir cela.

    Sur le plan technique, dès l'instant où tu as découplé C2 comme grunk l'a suggéré; il faut donc que, lors de l'appel à C1, tu lui passes une instance de C2.

  9. #9
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 420
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 420
    Points : 15 789
    Points
    15 789
    Par défaut
    Citation Envoyé par cavo789 Voir le message
    Désolé mais ça, c'est ta logique métier qui va définir cela.
    pour illustrer cela, s'il s'agit par exemple d'une classe utilitaire instanciée une seule fois, cette classe va utiliser le modèle singleton et donc elle s'instancie elle même.

  10. #10
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    je ne vois pas comment je vais m'en sortir.

    Prenons un exemple : suite à la demande de l'utilisateur d'importer un fichier CSV, on va exécuter la méthode uploadFile de la classe CSVImport. Celle-ci va demander le parsage du fichier ; pour l'instant :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $this->ref_parser = new CSVParser();
     
    $this->ref_parser->parse($this->filepath,4096);
    Il est clair que ce n'est pas l'utilisateur qui va demander la création de la classe CSVParser. Donc, qui va s'en charger ?

  11. #11
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par mathieu Voir le message
    pour illustrer cela, s'il s'agit par exemple d'une classe utilitaire instanciée une seule fois, cette classe va utiliser le modèle singleton et donc elle s'instancie elle même.
    Je ne te lis que tout de suite. Si je reprend ma classe CSVParser, on va l'utiliser plusieurs fois (à chaque import d'un fichier), mais y a pas d'objet. Est-ce que ça va le faire ?

  12. #12
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 692
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 692
    Points : 20 243
    Points
    20 243
    Par défaut
    Le passage dans le constructeur de la référence vers C2 n'est pas obligatoire , tu peux le faire via un setter quelconque.

    Donc en admettant que ton router instancie C1 tout seul.
    Il y'a bien à un moment donné un endroit où tu vas utiliser cette instance. C'est à cette endroit qu'il faudra "injecter" C2.

    Quoi qu'il arrive , il y'aura forcément un moment donné l'instanciation de C2 pour la passer à C1 , a toi de déterminer l'endroit le plus propice pour le faire.

  13. #13
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 420
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 420
    Points : 15 789
    Points
    15 789
    Par défaut
    Citation Envoyé par laurentSc Voir le message
    Si je reprend ma classe CSVParser, on va l'utiliser plusieurs fois (à chaque import d'un fichier), mais y a pas d'objet. Est-ce que ça va le faire ?
    avez-vous cherché des exemples de "modèle singleton" ?

  14. #14
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Désolé, mais j'étais pas dispo pour répondre plus tôt.

    J'ai réfléchi à vos réponses ; dans tous les cas, on suppose l'existence d'un objet de la classe C2. Si on crée une méthode statique de C2, C1 pourra appeler cette méthode sans créer d'objet : C2::une_methode_statique(xxx);. Qu'en pensez-vous ?

  15. #15
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 420
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 420
    Points : 15 789
    Points
    15 789
    Par défaut
    oui c'est ce qui se fait habituellement pour une classe "utilitaire" qui n'a besoin d'être instanciée une seule fois (ou parfois même sans être instanciée si tout passe par des méthodes statiques).

    et comme l'ont dit grunk et cavo789, la façon de lier et d'instancier les classes dépend de leur but. l'utilisation d'un singleton était juste un exemple pour les classes utilitaires.

  16. #16
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    OK,
    j'ai regardé comment était fait une classe singleton, et comme code minimal, j'ai trouvé :
    Code php : 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
    37
    38
    <?php
     
    class Singleton {
     
      /**
       * @var Singleton
       * @access private
       * @static
       */
       private static $_instance = null;
     
       /**
        * Constructeur de la classe
        *
        * @param void
        * @return void
        */
       private function __construct() {  
       }
     
       /**
        * Méthode qui crée l'unique instance de la classe
        * si elle n'existe pas encore puis la retourne.
        *
        * @param void
        * @return Singleton
        */
       public static function getInstance() {
     
         if(is_null(self::$_instance)) {
           self::$_instance = new Singleton();  
         }
     
         return self::$_instance;
       }
    }
     
    ?>
    Donc là, il va y avoir un objet de cette classe (unique).
    Dans les cas, où y a pas besoin de constructeur, je vais me limiter à des méthodes statiques.
    Dans les cas où y a besoin d'un constructeur (par exemple la classe travaille sur des données et il faut commencer par mettre ces données dans un attribut), je vais adopter le modèle du singleton et toutes les méthodes de la classe (à part le constructeur) vont travailler sur l'instance retournée par la méthode statique getInstance (besoin d'un seul objet car quand la classe va travailler sur de nouvelles données, elle aura fini de traiter les données précédentes).
    On est d'accord ? J'attends votre réponse avant de me lancer dans des modifs (car c'est assez lourd).

  17. #17
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 692
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 692
    Points : 20 243
    Points
    20 243
    Par défaut
    Attention le singleton est souvent utilisé à tord et à travers pour combler des lacunes de conception.

    La seule raison d'être d'un singleton c'est de limiter une classe à une seule instance.
    En PHP c'est très discutable du fait de la durée de vie très faible des scripts et du fait que chaque requête est indépendante.

    Ca du sens dans des projets ou le code s'exécute longtemps et où on veux garantir l'unicité d'un instance.
    Exemple type : J'ai un programme C++ qui tourne pendant des mois (quand ca plante pas ), dans ce programme j'ai une classe "App" qui représente l'application et contrôle tout. Il est critique dans ce cas de ne pas avoir 2 instances de cette classes , et le singleton rentre alors en jeu.
    L'autre exemple typique c'est une classe qui contrôle un matériel bien particulier qui ne peux pas recevoir 2 ordres à la fois , on s'assure alors qu'une seule instance de la classe existe.

    Donc la question à se poser avant d'utiliser un singleton est la suivante :
    - Que ce passe t'il si une seconde instance de mon objet est créée ?

    Si la réponse à la question est "C'est la merde" alors oui le singleton est probablement justifié. Sinon c'est non.

  18. #18
    Expert confirmé
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 470
    Points : 5 831
    Points
    5 831
    Billets dans le blog
    1
    Par défaut
    Dans le cas d'une classe utilitaire, y a pas besoin de l'instancier. Mon idée est donc de rendre toutes ses méthodes statiques ainsi que ses attributs. Est-ce une bonne idée ?

  19. #19
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 692
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 692
    Points : 20 243
    Points
    20 243
    Par défaut
    oui , les classes utilitaire sont très généralement des classes statiques

  20. #20
    Membre expert
    Avatar de cavo789
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2004
    Messages
    1 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 793
    Points : 3 063
    Points
    3 063
    Par défaut
    Bonjour

    Je pense qu'il faut faire la distinction entre une classe et ... un helper (qui est aussi une classe ).

    Un helper, commençons par le plus simple, est une liste de fonctions p.ex. pour gérer des fichiers (créer un fichier, écrire un texte, s'assurer que le fichier existe, déplacer, etc.). Ces fonctions n'ont rien à voir l'une avec l'autre : elles sont indépendantes càd qu'elles ne partagent pas la moindre propriété. Tu passes des paramètres à la fonction et tu reçois une valeur de retour. Cela s'arrête à ça. Tu peux en voir un exemple avec le framework de Laravel : https://github.com/laravel/framework...Filesystem.php. Tu peux y voir qu'il n'y a rien de commun entre les fonctions qui sont, donc, toutes autonomes. Ca, c'est un helper. Une librairie de fonctions. Et ici, tu pourrais déclarer toutes les fonctions comme statique et ne pas t'embêter à instancier une classe pour utiliser telle fonction.

    Un helper, avec un fichier autoload, pourrait être chargé immédiatement par composer.json (section autoload) et même pas besoin de faire un quelconque require ou use du coup.

    Pour le concept du singleton; perso, je l'utilise parfois (mais très rarement) pour une classe où j'aurais des attributs communs et l'exemple auquel je pense en cet instant serait une classe Configuration qui, selon mes projets, peut être assez importante. Cette classe irait lire un fichier settings.json et aurait autant de getter (et parfois de setter) pour rendre accessible telle variable de configuration dans mon projet. L'idée du singleton ici serait de ne faire qu'un seul __construct() qui se chargerait de l'initialisation de tout càd de lire le fichier [c]settings.json[c] et de faire certains prétraitement (convertir le json en array p.ex.).

    Le singleton permettrait de ne faire ce prétraitement qu'une seule fois mais comme le mentionne grunk; ce n'est vraiment pas un souci s'il le fait plus d'une fois; juste que c'est plus optimisé ici.

    Du coup, je fais appel à ma classe Configuration en début de projet afin de la créer et quand je dois appeler une autre classe, j'injecte $config comme étant un paramètre du constructeur de cette nouvelle classe.

    Pour en revenir à ton besoin, si ta classe utilitaire est une librairie de fonction, songe à en faire un helper càd, oui, des méthodes statiques.

    Bonne journée.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Applications Java qui communiquent avec une servlet
    Par 11mad11 dans le forum Général Java
    Réponses: 7
    Dernier message: 09/01/2015, 01h11
  2. Réponses: 3
    Dernier message: 12/06/2014, 18h31
  3. Réponses: 6
    Dernier message: 21/06/2012, 17h49
  4. [PHP-JS] Applet qui communique avec PHP
    Par darkbob dans le forum Langage
    Réponses: 1
    Dernier message: 18/12/2006, 07h16
  5. Réponses: 2
    Dernier message: 17/03/2006, 09h26

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