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

Design Patterns Discussion :

Dependecy injection, qu'en pensez vous


Sujet :

Design Patterns

  1. #1
    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 Dependecy injection, qu'en pensez vous
    Bonjour,

    J'ai lu cette présentation de la dependecy injection, http://components.symfony-project.or.../documentation.
    Concept à la mode dans le monde php ces temps ci.

    C'est fort intéressant.

    Cependant ça ressemble beaucoup à de la factory, avec des fonctionnalités supplémentaire concernant l'instanciation, et l'injection.

    Par ailleurs, je tend à penser que pour l'utilisateur final il devient très compliqué de connaitre l'interface des classes manipulés, puisque la DI pousse toute la définition dans une configuration externe.
    Je me rend compte en lisant ceci, http://picocontainer.org/introduction.html, que cet argument n'est valable que pour le PHP.

    D'un autre côté je comprend bien, pour un framework l'utilité de tout mettre dans des fichiers de configuration que l'on peut surcharger.

    Mais, est ce si judicieux que cela ?
    Ai je raison de penser que cela ressemble à une super factory multi fonctions de la mort qui tue des pets de mouches ?

    Avez vous simplement des avis sur ce pattern ?

    merci,
    a plus

  2. #2
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par kaymak Voir le message
    Cependant ça ressemble beaucoup à de la factory, avec des fonctionnalités supplémentaire concernant l'instanciation, et l'injection.
    Sans doute parce que c'est exactement ça !

    L'intérêt de passer par une factory, c'est de centraliser le code d'instanciation de la classe pour pouvoir par la suite substituer facilement une classe à une autre.
    De plus, tu peux écrire tout le code sur la base d'une classe abstraite générique, sans inclure la moindre dépendance sur la classe finale, et sans jamais savoir quelle sera cette classe.
    Au final, seule la factory a besoin de connaitre la classe finale et d'y être liée pour pouvoir l'instancier.
    Cependant, le pattern de la factory ne prévoit aucun mécanisme pour que la factory sache quelle classe doit être instanciée ni comment rendre cette instanciation paramétrable.

    Les frameworks d'injection de dépendance servent à mettre en place ce mécanisme, en reposant sur une configuration généralement externe.
    Dans les langages compilés, on peut utiliser ce principe pour lier le code à des classes qui étaient inconnues au moment de la compilation : Le coeur de l'appli ne connait que la définition de l'interface. Il n'y a aucune ligature aux classes qui implémentent les interfaces.
    Puis on peut définir des librairies externes qui implémentent ces classes et les utiliser par une simple configuration.

    Je ne connais pas le framework que tu cites, et je suis loin d'être un expert en PHP, mais il me semble que quoi que tu fasses, il faudra bien que tu fasses l'include de la définition de la classe finale. Même avec l'autoload de classe.
    Donc personnellement, mis à part l'aspect paramétrage de la factory, j'ai un peu l'impression que c'est comme souvent lorsqu'on parle de POO en PHP : Comment appliquer les solutions des problèmes qu'on rencontre dans les autres langages alors qu'on n'ait pas concerné !

    D'un autre côté je comprend bien, pour un framework l'utilité de tout mettre dans des fichiers de configuration que l'on peut surcharger.

    Mais, est ce si judicieux que cela ?
    Ai je raison de penser que cela ressemble à une super factory multi fonctions de la mort qui tue des pets de mouches ?
    Ca dépend de tes besoins et de ce que tu fais.
    Personnellement, je fais essentiellement du Progi en Delphi. Moins il y a de choses à configurer à l'installation, moins il y a de trucs dans lequel un utilisateur peut aller mettre les mains pour tout casser, mieux c'est...
    Donc en ce qui me concerne, je ne vois pas l'intérêt d'un fichier de configuration externe qui ne doit surtout pas être modifié pour que ça marche !
    Je préfère que la configuration soit faite par code, à un endroit centralisé, mais surtout pas externalisée !

  3. #3
    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
    Merci pour ta réponse.

    Je précise simplement mon propos vis-à-vis du cas particulier de PHP.
    En java, lorsqu'on obtient un objet, on peut préciser son type en accord avec la hiérarchie des classes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Juicer juicer = (Juicer) y.getComponent(Juicer.class);
    Ce qui n'est pas possible en PHP, par le langage.
    D'un autre côté en PHP on utilisera un commentaire.
    /* @var $instance Juicer */
    $instance = $DI->juicer;
    Mais l'un dans l'autre, il faut avoir mis les mains dans la configuration pour connaitre la classe concrète qui est manipulée, et partant de là, on peut déterminer son interface (qui est à la base de la DI il me semble).
    C'est assez bizarre.

    Alors qu'en factory on se contente d'indiquer l'interface implémenté par l'instance retournée et zou.


    Donc personnellement, mis à part l'aspect paramétrage de la factory, j'ai un peu l'impression que c'est comme souvent lorsqu'on parle de POO en PHP : Comment appliquer les solutions des problèmes qu'on rencontre dans les autres langages alors qu'on n'ait pas concerné !
    Je ne suis pas d'accord avec toi sur ce point, l’intérêt de la DI, que j'y voit, quelque soit le langage.
    Réside dans le ploymorphisme que l'on donne à sa factory dans le cadre d'un framework qui se veut modulaire, et donc interchangeable.

    Bon, je ne suis pas encore tout à fais décidé, les louanges chanter par la DI continue de me titiller le fond des oreilles.

    Par ailleurs, je me demande si la solution (DI) n'est pas simplement mauvaise, et si les traits ne pourraient pas venir pallier à tout cela... Mais c'est une idée en passant qui nécessiterait des réflexions.

    Merci bien en tout cas,
    a plus

  4. #4
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par kaymak Voir le message
    Mais l'un dans l'autre, il faut avoir mis les mains dans la configuration pour connaitre la classe concrète qui est manipulée, et partant de là, on peut déterminer son interface (qui est à la base de la DI il me semble).
    C'est assez bizarre.
    Je ne suis pas sûr de te suivre... Tu définis une interface. Tu as un code qui a besoin de quelque chose qui implémente l'interface. La DI te renvoie l'instance de l'implémentation qui a été configurée. Tu n'as pas besoin de connaitre la classe réelle, tu n'as pas a faire de cast vers la classe réelle, tu ne manipule que l'interface.

    Je ne suis pas d'accord avec toi sur ce point, l’intérêt de la DI, que j'y voit, quelque soit le langage.
    Réside dans le ploymorphisme que l'on donne à sa factory dans le cadre d'un framework qui se veut modulaire, et donc interchangeable.
    Ce qui doit être interchangeable, c'est l'implémentation de l'interface, pas l'interface elle même. Ce n'est pas la factory qui doit être polymorphe, bien au contraire. Lorsque tu l'appelles, il faudrait qu'elle ne puisse te renvoyer que le type correspondant à ce que tu as demandé.
    Or l'inconvénient de la DI (telle qu'elle est implémentée), c'est justement que tu peux configurer un type incompatible avec ce que le code utilisateur attend.

  5. #5
    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
    hello,

    Hmm OK en effet.

    Donc si je reprend mon exemple Php, c'est plus ressemblant par rapport au DP de l'écrire ainsi (fnmt comme l'exemple java)
    /* @var $instance Juicer */
    $instance = $DI->getComponent( "Juicer" );
    Où Juicer est une interface comme une autre, et $instance doit respecter son implémentation.
    Surtout on interroge la DI en lui donnant une interface, charge à elle de concrétiser le contrat.

    A contrario dans l'exemple que j'avais donné, que j'avais imaginé par rapport à l'implémentation donné de SF.
    Je ne pouvais pas connaitre le type manipulé, puisque j'utilisais un getter dynamique, donc non documenté, si ce n'est dans la déclaration du service d'injection (le fichier de configuration).

    Ok ok.

    Mais dès lors, si je réclame à la DI qu'elle me donne une instance concrète de l'interface que j'indique, comment le résultat peut il être incompatible ?
    En fait peux tu préciser, stp, l'implémentation qui te semble poser problème ?
    Ce n'est pas bien clair pour moi.

    En tout cas merci beaucoup de tes précisions.

    a+

  6. #6
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par kaymak Voir le message
    Où Juicer est une interface comme une autre, et $instance doit respecter son implémentation.
    Surtout on interroge la DI en lui donnant une interface, charge à elle de concrétiser le contrat.
    ...
    Mais dès lors, si je réclame à la DI qu'elle me donne une instance concrète de l'interface que j'indique, comment le résultat peut il être incompatible ?
    En fait peux tu préciser, stp, l'implémentation qui te semble poser problème ?
    Non ce n'est pas exactement ça. Lorsque tu fais le "getComponent", tu lui donne une chaine de caractère qui n'est rien d'autre qu'un identifiant.
    Cet identifiant peut-être le nom d'une interface si tu veux, mais ça peut-être n'importe quoi. Par exemple "Id1".
    Ensuite, c'est dans la configuration de la DI que tu dis ce qu'il faut renvoyer lorsqu'on te demande "Id1".
    Si dans le code, tu attends une implémentation de l'interface Juicer, il faut que tu configures une classe qui implémente Juicer.
    Le problème, c'est que tu peux très bien en configurer une autre, qui ne correspond à rien. getComponent renverra une instance incompatible avec le type attendu tu obtiendras une erreur lors du cast...
    Sauf si tu es en PHP, où il faudra attendre que tu essaie d'appeler une méthode qui n'existe pas pour avoir une erreur, sans en connaître précisemment l'origine...

  7. #7
    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
    ok. Donc effectivement je ramais... J'essayais de me raccrocher à des branches qui définitivement n'existe pas.

    Mais, alors, pourquoi n'ont ils pas fait comme je l'ai présenté ?
    Je veux dire, quel intérêt à utiliser un nom d'accesseur lambda qui n'à aucune signification particulière.
    Juste comme ça pour le plaisir de rendre plus compliqué ce qu'il l'est déjà ?

    Ou doit on y voir un désir de laisser au fournisseur de service la possibilité de déclarer le même service avec différents comportements ?
    Par exemple si j'ai un service `user`, on pourrait imaginer avoir user / user_cached / user_threadsafe / user_tout_cela_a_la_fois.

    En plus, j'imagine qu'au niveau des outils d'analyse de code, ce DP les rend hors d'usage (si tant est qu'il fut utile) ??

    Et par ailleurs pourquoi le comportement de consommation est laissé à la discrétion du provider et non du consommateur ??
    Ce sont des raisons techniques ou conceptuelles ?

    Encore merci de tes réponses.


    a+

  8. #8
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par kaymak Voir le message
    Mais, alors, pourquoi n'ont ils pas fait comme je l'ai présenté ?
    Tout dépend de tes besoins.
    L'identifiant utilisé peut servir à identifier une instance d'un singleton.
    Tu peux aussi vouloir utiliser différentes implémentations en fonction du contexte d'exécution. Dans le cas 1, tu veux un certain type d'implémentation. Dans le cas 2 tu veux un autre type.
    Dans ce cas, tu prévois deux identifiants différents, puis tu demandes l'un ou l'autre en fonction de tes besoins.
    Je pense que c'est ton exemple avec "user".

    Et par ailleurs pourquoi le comportement de consommation est laissé à la discrétion du provider et non du consommateur ??
    En fait, c'est la raison d'être de ce pattern. A la base, il a été introduit sous le nom d'"inversion de control" (Spring-IoC). Ce n'est pas le code utilisateur qui à la controle de la classe à instancier, c'est le fournisseur à travers la configuration, qui en a le controle.
    Ca permet par exemple, de casser l'ordre des dépendances. Ca permet d'obtenir une factory paramétrable, ce qui quelque part, est le but d'une factory.
    Ensuite certains ont trouvés que le nom n'était pas correcte, et qu'il vallait mieux parler d'injection de dépendances.

    Ce sont les raisons techniques qui font qu'il n'est pas possible de typer explicitement le type de données retourner par "getComponent", si on veut que getComponent soit une méthode d'un framework générique qui ne connait pas le type du résultat attendu...

    Maintenant tu peux mettre en oeuvre ce principe à la main, sans passer par un framework générique : Tu crées des factory qui retournent des données bien typées. Dans l'implémentation de la factory, tu prévois un paramétrage externe pour indiquer la classe à instancier... ou encore, tu utilises le framework générique pour implémenter les factory en question...

  9. #9
    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
    hmm ok ok.

    C'est décidément beaucoup plus clair grâce à tes réponses, merci !!

    Effectivement s'ils avaient utilisé, ma naïve, idée de conduire la demande par l'interface, de facto, il n'était plus possible de proposer plusieurs implémentations d'un même contrat.
    Puisqu'en attachant une implémentation à une interface, la relation est bien 1:1.


    En fait ce qui ne me plait pas c'est cet aspect complètement dé typé pour l'utilisateur, je trouve ce DP déstructurant pour l’application.
    En plus du problème que tu as donné sur l'incompatibilité des types entre la demande et la proposition.


    La base même du DP, est de dire que lorsqu'une application utilise un service `mail`, tous les appels dans le code utilisateur s'effectue sur `mail`, le jour où on décide de changer l'implémentation de `mail` depuis `smtp vers `imap`, il n'y à que la configuration du service à changer.
    Ok, pourquoi pas, vu comme cela, c'est sympa.
    Cependant, dans cet exemple, si on drive la demande par l'interface sa fonctionne.

    D'un autre côté si l’application utilise les deux, on doit définir deux alias de services `mail_smtp` et `mail_imap`.
    On utilisera l'un l'autre dans le code utilisateur, toujours sans aucune notion de type.
    On est toujours sur une relation 1:1, mais comme il partage tous les deux la même interface, ce discriminant n'est plus suffisant.
    Et c'est là que je ne peux m’empêcher qu'il manque une notion de domaine / spécialisation.

    Du coup on aurait plus `mail_smtp` et `mail_imap`, mais `IMail` qui pointe sur celui configuré par défaut, et si on le besoin se présente `(IMail, smtp)`, `(IMail, imap)`.
    En plus du coup on peut vérifier le type (au runtime..).

    Je suis assez choqué tout de même qu'ils aient fait sauter la notion de typage, c'est ce qui me pousse à reformuler l'idée de base, même si cela peut sembler impertinent au vu de mes compétences en conception..

    a+

  10. #10
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Pour le php, je sais pas. Mais en java, c#... Tu peux typer. Tu as des génériques.

  11. #11
    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
    Citation Envoyé par davcha Voir le message
    Pour le php, je sais pas. Mais en java, c#... Tu peux typer. Tu as des génériques.
    Par exemple :
    Juicer juicer = (Juicer) y.getComponent(Juicer.class);
    ?


    Citation Envoyé par http://picocontainer.org/inversion-of-control.html
    It is the deployer’s, embeddor’s or container maker’s choice on which to use.
    Simply put, a component designed according to IoC does not go off and get other components that it needs in order to do its job. It instead declares these dependencies, and the container supplies them. Thus the name IoC/DIP/Hollywood Principle. The control of the dependencies for a given component is inverted. It is no longer the component itself that establishes its own dependencies, but something on the outside. That something could be a container like PicoContainer, but could easily be normal code instantiating the component in an embedded sense.
    Donc, clairement c'est pour faire de la configuration. De la configuration. Et encore de la configuration.

    Ils auraient pu appeler cela Configurable Injection and Resolution.... alala

    a+

  12. #12
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539

Discussions similaires

  1. Que pensez-vous des générateurs de doc PHP ?
    Par Nonothehobbit dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 64
    Dernier message: 10/07/2007, 11h17
  2. Que pensez vous du nouveau kernel 2.6 ?
    Par GLDavid dans le forum Administration système
    Réponses: 58
    Dernier message: 02/08/2004, 16h45
  3. Borland prépare un EDI pour C# - qu'en pensez vous ?
    Par Marc Lussac dans le forum Actualités
    Réponses: 24
    Dernier message: 23/07/2003, 11h32
  4. Que pensez vous du mariage ASP Flash?
    Par tyma dans le forum Flash
    Réponses: 4
    Dernier message: 09/07/2003, 16h00
  5. Réponses: 13
    Dernier message: 11/05/2003, 14h25

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