Thématiques principales

mardi 8 mai 2018

Iod, l'injection de dépendances

Nous avons vu dans l’article précédent, le principe de l’inversion de contrôle. Ce dernier se base sur les principe de SOLID et est indispensable aux frameworks modernes tels que Spring qui l’utilise, on peut presque le dire, à outrance dans leur système d’injection de dépendances.

Dans cet article, justement, je vous propose de regarder comment fonctionne un mécanisme d’injection de dépendance et vous invite donc si vous ne l’avez pas vu à regarder l’article [1] afin d’en acquérir les pré-requis.

J'aurais peut être dû faire un article commun pour traité les sujets de IOC et de IOD car les deux sont souvent intimement lié et même traité ensemble. Cependant, d’une part, le temps dont je dispose ces derniers temps c’est gravement amoindri donc c'était plus simple d’en faire deux et d’autre part, je trouve que si l’IOD dépendant de l’IOC, l’inverse n’est pas vrai et heureusement (ca serait presque paradoxale…. ^^)

Donc du coup voilà, qu’est que IOD où injection de dépendance [2]. Le principe est simple, il s’agit de donner la responsabilité de la construction de la dépendance entre deux objets a un troisième. A ce stade on peut se dire que ce que nous avions vu sur l’inversion de contrôle est suffisant, on crée une factory pour produire des objets et op on l'appelle lorsqu'il faut construire des objets qui en ont besoin. Si l’idée de base est bien celle-ci, il nous manque un partie importante, l’orchestration.

En effet, dans le principe, l’injection de dépendances repose globalement sur les même mécanismes que l’inversion de contrôle car, l’inversion de contrôle permet de déplacer la problématique de la gestion du cycle de vie d’un objet dont un objet en avait la responsabilité, auprès d’un autre. Du coup forcément, pour permettre la mise en relation, l’objet initial doit toujours pouvoir obtenir l’objet dont il a besoin.

Ainsi dans l’article précédent [1] on avait forcément en plus de l’IOC une forme implicite d’injection de dépendance.

def mFactory=new MoteurFactory()

new Voiture(mFactory.buildMoteurX()).drive()
new Voiture(mFactory.buildMoteurX()).drive()


Mais bon on s’accordera que ça mériterait, un petit peu plus d’outillage.

Ainsi, ce qui manque c’est d’un moyen permettant de faire cette mise en relation de la voiture avec le moteur implicitement. Le premier réflexe, qui n’est pas forcément une mauvaise idée, est de faire appelle à une autre factory. La combinaison des factory est souvent dans un périmètre limité une bonne solution.


class MoteurFactory
{
   def buildMoteurX()
   {
       return new MoteurX()
   }

   def buildMoteurY()
   {
       return new MoteurY()
   }
}

class VoitureFactory
{
   def buildWithMoteurX(MoteurFactory f)
   {
       return new Voiture(f.buildMoteurX())
   }

   def buildWithMoteurY(MoteurFactory f)
   {
       return new Voiture(f.buildMoteurY())
   }
}

def mFactory=new MoteurFactory()
def vFactory=new VoitureFactory()

def v1=vFactory.buildWithMoteurX(mFactory)
def v2=vFactory.buildWithMoteurY(mFactory)

v1.drive()
v2.drive()

Bien ça marche, cool mais en fait on se rend vite compte qu’on a déplacer le problème! ba oui car la on passe en paramètre la factory des moteurs à celle des voitures. On a donc aussi un problème de gestion de dépendance! Mais ne peut on pas faire une factory pour gérer cela? ba si allons jusqu'au bout de l’idée


class MoteurFactory
{
   def buildMoteurX()
   {
       return new MoteurX()
   }

   def buildMoteurY()
   {
       return new MoteurY()
   }
}

class VoitureFactory
{
   MoteurFactory facto

   def VoitureFactory(MoteurFactory facto)
   {
       this.facto=facto
   }
ca 
   def buildWithMoteurX()
   {
       return new Voiture(this.facto.buildMoteurX())
   }

   def buildWithMoteurY()
   {
       return new Voiture(this.facto.buildMoteurY())
   }
}

class MetaFactory
{
   def buildFactoryForCar()
   {
       return new VoitureFactory(new MoteurFactory())
   }
}

def mf=new MetaFactory()

mf.buildFactoryForCar().buildWithMoteurX().drive()
mf.buildFactoryForCar().buildWithMoteurY().drive()

Bien on voit que ça marche, mais ça fait beaucoup de factory! Et bien oui et c’est pour cela que l’on utilise des framework comme Spring [3] ou CDI [4].

Voilà, j'espère qu’avec ces deux articles et cet exemple très simple, on a un peu démystifier l’IOD et IOC et permit de mieux aborder les mécanismes sous jacent a des framework comme SPring et CDI qui se basent eux aussi (aux registres et annotations près) sur ce bon vieux pattern factory. A très vite donc sur Spring et CDI!

Références

[1] https://un-est-tout-et-tout-est-un.blogspot.fr/2018/05/ioc-inversion-de-controle.html
[2] http://igm.univ-mlv.fr/~dr/XPOSE2010/guicespring/di_presentation.html
[3] https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
[4] https://rmannibucau.developpez.com/tutoriels/cdi/introduction-cdi/

Aucun commentaire:

Enregistrer un commentaire