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 :

Bonne pratique POO : Où placer les fonctions communes ?


Sujet :

Langage PHP

  1. #1
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut Bonne pratique POO : Où placer les fonctions communes ?
    Bonjour,

    En matière de bonne pratique en programmation objet, où placez-vous les fonctions utiles à plusieurs classes ?

    Par exemple, j'ai une fonction qui détermine l'année scolaire en cours en fonction de la date et j'ai besoin de cette fonction dans plusieurs contrôleur de l'application que je développe, et même potentiellement dans plusieurs modules.

    Serait-ce une bonne pratique de faire une classe générale Outils avec dedans les fonctions utiles à plusieurs endroits de l'application ?
    Ou bien un simple fichier PHP contenant les fonction et à inclure au besoin dans le code des contrôleurs qui en ont besoin ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 847
    Points : 6 531
    Points
    6 531
    Par défaut
    Si plusieurs classes partagent une ou plusieurs méthodes, tu peux utiliser les traits. Sinon un autre solution consiste à utiliser l'héritage, mais c'est moins souple car il faut que tes classes aient un ancêtre commun qui implémente la ou les méthodes (sans que ça devienne un non-sens total).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Nb
    Nb est déconnecté
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    148
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 148
    Points : 417
    Points
    417
    Par défaut
    En terme de bonne pratique je ne sais pas trop.
    Perso j'aurais mis ca dans une classe AnneeScolaire en tant que methode statique. Classe qui pourrait par ailleurs posseder des methodes non statique plus tard dans le projet (calculer les dates des trimestres..etc).
    Si à aucun moment tu ne penses avoir besoins d objet AnneeScolaire alors mettre ca dans une bibliotheque de fonctions peut être aussi bien qu'une classe Outils.

    Pour les traits je pense que ca dépend, ca va forcément marcher, ca dépend du contexte. Par exemple si tu as besoins de l'année courante dans une classe Eleve, mettre la fonctionnalité dans un trait et faire un use dans Eleve va marcher, mais ca n'a aucun sens car ta classe éléve va "hériter" d'un comportement qui n'a aucun lien avec elle. Pas sur d'avoir ete tres clair là

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 6 690
    Points : 20 211
    Points
    20 211
    Par défaut
    Citation Envoyé par CosmoKnacki Voir le message
    Si plusieurs classes partagent une ou plusieurs méthodes, tu peux utiliser les traits. Sinon un autre solution consiste à utiliser l'héritage, mais c'est moins souple car il faut que tes classes aient un ancêtre commun qui implémente la ou les méthodes (sans que ça devienne un non-sens total).
    Niet pas d'héritage , sinon ça devient de l'héritage fonctionnel et c'est exactement ce qu'il faut éviter en POO.

    Pour moi la bonne pratique c'est la création de ce qu'on va appeler des "helpers". Ce sont des classes le plus souvent statique qui permettent d'encapsuler les fonctions "utilitaires" qui peuvent être utilisée un peu partout mais qui n'ont pas à faire partie d'autre classe sémantiquement parlant.

    Dans ton cas précis on pourrais imaginer un helper "date" dans lequel tu vas venir mettre toutes les fonctions utile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class DateHelper
    {
        public static function getCurrentScolarYear()
        {
            // Ton code
        }
    }
    Et partout où tu en as besoin tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $year = DateHelper::getCurrentScolarYear();
    Si ensuite tu à besoin de fonction pour faire des actions sur les chaines de caractères tu peux faire un helper "StringHelper" ou tu vas venir mettre tout ce qui te permet de traiter tes chaines partout dans ton code.
    Un exemple complet de helper sur les strings extrait de mon framework : https://github.com/grunk/Pry/blob/ma...il/Strings.php

    Tu répètes ensuite l'opération pour toutes les "catégories" de fonctions (string,date ...)
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre éprouvé Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Points : 1 105
    Points
    1 105
    Par défaut
    Je suis étonné de voir autant de personnes proposer une statique...

    Que ce soit les traits ou la statique, au moment de tester unitairement vos classes vous allez galérer...

    Pour moi la vraie "bonne pratique" dans ce cas est l'injection de dépendance.

    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
     
    interface CurrentScolarYearProvider 
    {
        public function getCurrentScolarYear() : ScholarYear;
    }
     
    final class DateHelper implement CurrentScolarYearProvider
    {
        public function getCurrentScolarYear() : ScholarYear
        {
            // Ton code
        }
    }
     
    final class MyController
    {
        private $helper;
     
        public function __construct(CurrentScolarYearProvider $helper)
        {
            $this->helper = $helper;
        }
     
        public function myAction()
        {
            return [
                'current_scolar_year' => $this->helper->getCurrentScolarYear(),
            ];
        }
    }
    Là, ton code est testable, et tu peux changer à la demande l'implémentation de ton provider.

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 6 690
    Points : 20 211
    Points
    20 211
    Par défaut
    Citation Envoyé par tdutrion Voir le message
    Je suis étonné de voir autant de personnes proposer une statique...

    Que ce soit les traits ou la statique, au moment de tester unitairement vos classes vous allez galérer...
    Dans la réalité les gens qui on le temps et/ou le budget d'unit tester tout le code c'est une minorité. (perso je l'ai pas)
    Du coup les statiques ont du sens car il y'a beaucoup moins d'overhead qu'avec une injection de dépendance tout en gardant une organisation relativement propre.

    Peux tu détailler en quoi ca va être un problème au moment d'un test unitaire ? Si la classe statique est testée , on à pas besoin de la retester dans la classe qui l'utilise non ?
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre éprouvé Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Points : 1 105
    Points
    1 105
    Par défaut
    En fait tu as d'une part le problème de la statique dans le test, car ta statique va te donner disons "2017-2018" pour l'exemple, mais lorsque tu passes à l'année "2018-2019" ton test ne passera plus (car la valeur change, donc le résultat change).

    Si tu fais un test ou tu assert = date('Y') . '-' . (date('Y')+1), tu mets du code dans ton test, donc pas essence c'est faussé.
    Ce que tu veux savoir dans le test c'est "si j'entre avec 2017-2018, est ce que mon résultat contient bien cette valeur (transformée correctement). Du coup dans le cas du helper injecté tu peux facilement mocker la valeur.

    Pour le coup, selon ton framework l'injection ne rajoute pas massivement d'overhead, ni en charge de processing, ni en developpement, car tu auras l'autowiring qui s'occupe de ça (dans mon exemple il faut juste binder ton implementation à ton interface en fait)

  8. #8
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut
    Merci pour vos avis.

    Citation Envoyé par CosmoKnacki
    Si plusieurs classes partagent une ou plusieurs méthodes, tu peux utiliser les traits.
    J'avais survolé la description des traits et n'avait pas perçu leur utilité.
    C'est souvent quand on est confronté à un problème qu'on comprend l'utilité de l'outil mystérieux qui traîne dans un coin.

    Citation Envoyé par grunk
    Pour moi la bonne pratique c'est la création de ce qu'on va appeler des "helpers".
    Quel serait l'avantage par rapport au trait ?
    La classe helper ne pourrait-elle pas être un trait ? N'est-ce finalement pas équivalent ?

    Citation Envoyé par tdutrion
    Pour moi la vraie "bonne pratique" dans ce cas est l'injection de dépendance.
    Qu'appelles-tu injection de dépendance ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    interface CurrentScolarYearProvider 
    {
        public function getCurrentScolarYear() : ScholarYear;
    }
    Je n'ai pas encore rencontré cette syntaxe avec le :.
    Ça veut dire quoi ?
    En plus, tu ne réutilise pas ScholarYear plus loin dans le code.

    En matière de test, j'essaie de tester mon code au fur et à mesure et de :
    - déboguer de suite ;
    - ou bien mettre des // FIXME ou // TODO pour déboguer ou améliorer plus tard.


    Je vais essayer les traits.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Membre éprouvé Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Points : 1 105
    Points
    1 105
    Par défaut
    L'inconvénient des traits c'est que c'est un vague copier coller conceptuellement, donc pas forcément propre.

    Pour la parenthèse sur le : Valeur, c'est du PHP 7, c'est une façon de garantir le type de résultat (return types). En gros, si la méthode renvoi autre chose qu'un objet de type ScholarYear, on a une erreur.

    Dans le cas de l'injection par rapport aux autres techniques, c'est que le jour où tu as besoin de changer l'implémentation de façon différente pour les différentes classes l'utilisant, tu n'auras que de la configuration à changer dans ton container (dans les factories).

  10. #10
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par tdutrion
    dans ton container (dans les factories).
    "container", "factories"... voilà des trucs encore trop abstraits pour moi qui m'ont fait abandonné l'étude et l'envie d'utiliser les framework.

    Mais c'est un autre sujet...
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  11. #11
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut
    Ça semble cool, les traits !
    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
    namespace Application\Controller;
     
    trait DateHelper 
    {
    	/**
    	 * Donne l'année universitaire en cours selon la date actuelle (Année 2017-2018 => 2017)
    	 * @return int
    	 */
    	public function anneeUniv()
    	{
    		$today = getdate();
     
    		if($today['mon'] > 7)
    		{
    			$anneeUniv = $today['year'];
    		}
    		else
    		{
    			$anneeUniv = $today['year'] - 1;
    		}
     
    		return $anneeUniv;
    	}
     
    }
    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
    class Ajouter extends Controleur
    {
    	use DateHelper
    	{
    			DateHelper::anneeUniv as anneeUniv;
    	}
     
    	public function index()
    	{
    		session_start();
     
    		/** Vérification que l'utilisateur est connecté et à le droit d'accéder à la page */
    		$this->verifierUtilisateur(); // vient du contrôleur générique Controleur
     
    		/** Données pour la page */
    		$anneeUniv = $this->anneeUniv(); // vient du trait DateHelper
    // ...
    La fonction s'utilise comme si c'était une fonction de la classe ou de la classe mère.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 6 690
    Points : 20 211
    Points
    20 211
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Merci pour vos avis.

    J'avais survolé la description des traits et n'avait pas perçu leur utilité.
    C'est souvent quand on est confronté à un problème qu'on comprend l'utilité de l'outil mystérieux qui traîne dans un coin.
    Un trait à l'avantage d'avoir accès à tous le scope d'une classe qui l'utilise. Ce n'est pas le cas d'une méthode/class statique.
    une classe statique peut induire un couplage fort comme l'explique tdutrion. Celà peut être ennuyeux pour les tests unitaire , mais tu n'en ai pas là.

    Citation Envoyé par CinePhil Voir le message
    La classe helper ne pourrait-elle pas être un trait ? N'est-ce finalement pas équivalent ?
    Elle pourrait. C'est juste que conceptuellement c'est pas vraiment la même chose. Un traits - pour moi - c'est justement là pour éviter l'héritage fonctionnel. Ca te permet d'étendre les fonctionnalité d'une classe sans devoir dériver de quelque choses qui n'a aucun rapport.

    Citation Envoyé par CinePhil Voir le message
    Qu'appelles-tu injection de dépendance ?
    Une injection de dépendance c'est quand tu passe en paramètre une dépendance plutôt que de la coupler fortement :
    Sans injection :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    	public function __construct()
    	{
    		$b = new B();
    		$b->hello();
    	}
    }
    On voit ici que si la classe B n'existe pas , la classe A ne fonctionne plus
    Au contraire avec une injection de dépendance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    	public function __construct($b)
    	{
    		if($b)
    			$b->hello();
    	}
    }
    Je n'ai plus de couplage fort entre A et B , si B n'existe pas , A fonctionne toujours. Et je peux tout à fait passer ce que je veux en paramètre tant que ca répond au besoin de A.

    Citation Envoyé par CinePhil Voir le message
    En matière de test, j'essaie de tester mon code au fur et à mesure et de :
    - déboguer de suite ;
    - ou bien mettre des // FIXME ou // TODO pour déboguer ou améliorer plus tard.
    Les test unitaires dont parle tdutrion sont une autre facette de la programmation.
    Tu écris des tests (des assertions) via un framework de test comme atoum,phpunit,etc ... et donc code finale doit permettre de passer ses tests.
    Donc quand tu commences , aucun des tests ne passent car le code n'est pas ou mal écrit. Et au fur et à mesure on rempli les conditions des tests.
    Ça à le très gros avantage de détecter les bugs rapidement et d'améliorer la qualité du code.


    Citation Envoyé par CinePhil Voir le message
    "container", "factories"... voilà des trucs encore trop abstraits pour moi qui m'ont fait abandonné l'étude et l'envie d'utiliser les framework.

    Mais c'est un autre sujet...
    Ce sont des "design pattern" ou patron de conception en bon français
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut
    ARF !
    Trait method anneeUniv has not been applied, because there are collisions with other trait methods


    Je n'ai qu'un seul trait et une seule méthode anneeUniv utilisée une seule fois dans la classe !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Lister extends Controleur
    {
    	use DateHelper
    	{
    			DateHelper::anneeUniv as anneeUniv;
    	}
    // (...)
     
    	protected function afficherListe($arguments)
    	{
    		$annee_univ_actuelle = $this->anneeUniv();
    // (...)
    	}
    }
    Comment peut-il y avoir conflit ?

    EDIT : Le conflit provenait-il du fait que mon alias avait le même nom que la méthode du trait ?
    En changeant l'alias, ça fonctionne.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  14. #14
    Membre expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 58
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Points : 3 627
    Points
    3 627
    Billets dans le blog
    8
    Par défaut
    Merci d'avoir posé tout haut une question que je me pose régulièrement, Cinéphil...
    Personnellement, j'aime bien la solution des helpers...
    Bon, ce sont des classes, mais au moins... ce n'est pas une classe fourre-tout qui s'appelle Tools et qui me rappellent fâcheusement mon ancien fonctions.php...
    Je vais partir sur Date_helper et Regex_helper... Thx !
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

  15. #15
    Membre éclairé
    Femme Profil pro
    Autre
    Inscrit en
    Janvier 2017
    Messages
    335
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Janvier 2017
    Messages : 335
    Points : 715
    Points
    715
    Par défaut
    Bonjour,
    Citation Envoyé par CinePhil Voir le message
    Le conflit provenait-il du fait que mon alias avait le même nom que la méthode du trait ?
    Oui.
    Cela n'a pas de sens de donner un alias du même nom.
    De plus, il ne s'agit pas de renommer, les deux noms sont utilisables (d'où le conflit s'ils sont les mêmes) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	use DateHelper
    		{
    		anneeUniv as autreNom;
    		}
     
    	protected function afficherListe($arguments)
    		{
    		$annee_univ_actuelle = $this->anneeUniv();
    //ou
    		$annee_univ_actuelle = $this->autreNom();
    Concernant la méthode "anneeUniv", je réduirais bien le code ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $today = getdate();
    return $today['year'] - (int)($today['mon'] < 8); //(int) facultatif
    Cela reste lisible.

  16. #16
    Membre éprouvé Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Points : 1 105
    Points
    1 105
    Par défaut
    Je trouve ça marrant quand même de demander la "Bonne pratique POO" et de se réjouir de la pire pratique en terme de POO (les traits sont de loin la moins bonne pratique de toutes celles exposées).

    Si vous voulez vraiment suivre les bonnes pratiques POO, c'est injection de dépendance et c'est tout. Sinon c'est un choix de développement pour la simplicité sur le moment, je dis pas qu'il faut pas utiliser ces techniques, mais juste être conscient que ce n'est pas de la POO propre.

  17. #17
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par tdutrion
    L'inconvénient des traits c'est que c'est un vague copier coller conceptuellement, donc pas forcément propre.
    En quoi c'est un copier-coller ?
    La fonction est écrite une seule fois dans le trait et utilisée dans plusieurs classes. Je ne vois pas de copier-coller.

    Citation Envoyé par tdutrion
    Si vous voulez vraiment suivre les bonnes pratiques POO, c'est injection de dépendance et c'est tout.
    Bis repetita :
    Citation Envoyé par CinéPhil
    Qu'appelles-tu injection de dépendance ?


    Pour ta remarque :
    Citation Envoyé par tdutrion
    Je trouve ça marrant quand même de demander la "Bonne pratique POO" et de se réjouir de la pire pratique en terme de POO (les traits sont de loin la moins bonne pratique de toutes celles exposées).
    Comme je ne vois pas pourquoi...

    Et comme ce que tu as évoqué plus haut "dans ton container (dans les factories)." reste trop abstrait et obscur pour mon faible niveau en POO...

    Je prends donc ce que j'ai compris et qui semble me convenir pour le moment.

    Moi je trouve un peu désolant de se plaindre qu'on ne choisit pas la bonne technique mais ne pas faire preuve de la pédagogie nécessaire pour expliquer pourquoi et quelle serait concrètement la bonne pratique.

    Grunk a fait l'effort, sans râler.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  18. #18
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 793
    Points : 34 024
    Points
    34 024
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par grunk Voir le message
    Une injection de dépendance c'est quand tu passe en paramètre une dépendance plutôt que de la coupler fortement :
    Sans injection :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    	public function __construct()
    	{
    		$b = new B();
    		$b->hello();
    	}
    }
    On voit ici que si la classe B n'existe pas , la classe A ne fonctionne plus
    Au contraire avec une injection de dépendance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class A
    {
    	public function __construct($b)
    	{
    		if($b)
    			$b->hello();
    	}
    }
    Je n'ai plus de couplage fort entre A et B , si B n'existe pas , A fonctionne toujours. Et je peux tout à fait passer ce que je veux en paramètre tant que ca répond au besoin de A.
    Ah OK ! Ben ça je pratique aussi mais je n'en vois pas trop l'intérêt dans le cadre qui me préoccupe ici.
    Ça pourrait avoir du sens si c'est une classe métier qui possède une propriété valuée par une fonction externe mais là il s'agit d'un contrôleur du module. Ça me semble sémantiquement moins pertinent.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  19. #19
    Membre éprouvé Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Points : 1 105
    Points
    1 105
    Par défaut
    Justement je vois que tu as lu la réponse de Grunk, je n'ai pas répondu sur ce point car sa définition est bonne.

    Le container, c'est ce qui va permettre de connaitre les "recettes" (factory) permettant de construire les différents objets (pour ne pas répéter l'instanciation des objets injectés et de l'objet principal partout).

    Concrètement l'intérêt ici n'existe qu'avec l'utilisation d'une interface, et c'est précisément la substitution de Liskov dans les principes SOLID. Imaginons que tu ais 4 contrôleurs utilisant ton helper, et d'un coup l'un d'entre eux doit reposer sur une implémentation légèrement différente (chercher la donnée ailleurs par exemple), comment fais-tu ?
    Avec un container et de l'injection de dépendance, 3 contrôleurs ne changent pas, et pour le 4ème tu dois juste changer une configuration de ton container pour injecter la nouvelle implementation.

    Pour en revenir au traits, ce n'est pas un pure copier coller dans le sens ou changer l'implementation la changera partout, mais c'est un copier coller conceptuel (je colle ce code dans toutes les classes utilisant le trait). C'est donc un peu moins pire, mais ça introduit un couplage fort (changer l'implementation peut casser le reste).

    Pour ce qui est de ma pédagogie, désolé mais je ne peux pas écrire un bouquin sur l'OOP là, il faut demander des ressources sur les points qui bloquent et pas dire ""container", "factories"... voilà des trucs encore trop abstraits pour moi qui m'ont fait abandonné l'étude et l'envie d'utiliser les framework.". Si les frameworks implémentent ces design patterns, c'est qu'ils ont une utilité. Pour le reste, il existe de très bonnes ressources qui expliquent ces concepts mieux que ce que je ferais ici avec mon temps limité, en info il faut aussi savoir chercher par soi-même.

  20. #20
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Voici une mine d'or que je vais copier/coller de suite sur le pense bête.
    Mais une petite remarque pour tdutrion que je trouve un assez perfectionniste ...
    Citation Envoyé par tdutrion Voir le message
    Concrètement l'intérêt ici n'existe qu'avec l'utilisation d'une interface, et c'est précisément la substitution de Liskov dans les principes SOLID. Imaginons que tu ais 4 contrôleurs utilisant ton helper, et d'un coup l'un d'entre eux doit reposer sur une implémentation légèrement différente (chercher la donnée ailleurs par exemple), comment fais-tu ?
    Il y a le YAGNI qui nous permet de rester sur les classes STATIC (ma préférence) ou le trait (que je découvre ). La volonté de factoriser ou de prévoir nous amène souvent à plus de complexité que de réels besoins.
    Par ailleurs, pour le problème que vous citez
    1->avec une classe STATIC on ajoute la nouvelle implémentation de la fonction et rien n’empêche d'enrichir l'ancienne (c'est en fait un module de fonctions utilitaires)
    2->les TRAITS (tel que je viens de l'apprendre) pareil.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

Discussions similaires

  1. Bonnes pratiques : doit-on supprimer les listeners ?
    Par adiGuba dans le forum Général JavaScript
    Réponses: 22
    Dernier message: 31/07/2014, 08h38
  2. Où placer les fonctions matlab du file exchange
    Par takfa2008 dans le forum MATLAB
    Réponses: 3
    Dernier message: 07/04/2013, 22h44
  3. [POO] Question sur les fonctions
    Par Carb0 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 26/11/2008, 16h18
  4. [POO]Où placer les écouteurs d'évènement utilisateur?
    Par ChriGoLioNaDor dans le forum Langages de programmation
    Réponses: 4
    Dernier message: 03/09/2008, 08h28
  5. [POO] Pb avec les fonctions xml et la POO
    Par QuantuX dans le forum Langage
    Réponses: 1
    Dernier message: 17/06/2006, 15h54

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