Thématiques principales

samedi 5 mai 2018

Ioc, Inversion de controle

Dans les articles précédents, nous avons à traiter des sujets se rapportant à l'écosystème Java et entre autre a JEE avec JMS. Bien sûr nous ne nous arrêterons pas là et nous nous intéresserons à JPA, le JSP, les Servlet et les EJB. Cependant si ces concepts sont le cœur de JEE, il serait dommage de ne pas traiter également des alternatives possibles à JEE, comme par exemple Spring.

Dans cet article, nous n’allons pas traiter directement Spring mais introduire quelques concepts clefs afin d'appréhender au mieux les mécanismes qui en sont les fondamentaux : l’inversion de contrôle et l’injection de dépendance.

Commençons par l’inversion de contrôle. Nous l’avions évoqué dans un article précédent traitant des principes SOLID [1], nous avions traité de la problématiques de l’inversion de dépendances (principe D) qui par la construction d’entité abstraite, nous permet de découpler le code afin qu’il respecte au mieux le principe de responsabilité unique (principe S). Nous avions évoqué justement qu’en poussant le raisonnement plus loin, ce principe nous permet d’aller jusqu'à l’inversion de contrôle.

Bien sur il existe des patterns très bien fait qui nous permettent facilement de faire de l’inversion de contrôle comme par exemple le pattern Visiteur [2] ou le pattern Stratégie [3] couplé à un pattern factory [4]. C’est par cette deuxième approche que nous allons présenter l’inversion de contrôle (et donc implicitement de dépendances)

Posons le problème. Imaginons une voiture capable de rouler et pour cela, bien sur la voiture va employer un moteur. La première approche qui aura le mérite de marcher sera probablement d'écrire un code proche de celui ci (en groovy):


class Voiture{

   Moteur moteur=new Moteur()

   def drive() {
       this.moteur.active()
       println("la voiture avance")
   }
}

class Moteur
{
   def active() {
       println("le moteur tourne");
   }
}

def voiture=new Voiture()
voiture.drive()

Même s’il respecte une certaine décomposition, ce code souffre d’un problème de couplage fort entre les classes Voiture et Moteur. En effet, dans ce cas, il est impossible de prévoir une voiture avec un moteur qui serait différent en sortie d’usine! Il faudrait ajouter un moyen permettant de changer ce moteur après la construction comme une méthode supplémentaire du type changeMoteur. Ce n’est pas acceptable.

Ainsi pour répondre à cela, on va suivre le principe I de SOLID en rendant abstrait le moteur dans la voiture modélisant ainsi qu’il sera possible d’utiliser des moteurs différents.

Cela donne donc ceci:


class Voiture{

   Moteur moteur;

   def Voiture(Moteur m)
   {
       this.moteur=m;
   }

   def drive() {
       this.moteur.active()
       println("la voiture avance")
   }
}

abstract class Moteur{
   def abstract active()
}

class MoteurX extends Moteur{
   def active() {
       println("le moteur X tourne");
   }
}
class MoteurY extends Moteur{
   def active() {
       println("le moteur Y tourne");
   }
}

new Voiture(new MoteurX()).drive()
new Voiture(new MoteurY()).drive()

On a réussi à découpler le moteur de la voiture lors de sa création mais on a pas vraiment rationalisé la construction des moteurs pour les voitures. C’est donc la que va intervenir le pattern Factory en fournissant une entité unique permettant la création des moteurs (et cela nous permet de respecter le principe S). Voici donc comment évolue notre code, suite a l’ajout d’une factory:

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

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

def mFactory=new MoteurFactory()

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

Voilà, les voitures n’ont plus la responsabilité de construire leur moteur, c’est la factory qui s’en chargera nous permettant de choisir le moteur le plus adapté. Du point de vue de la voiture, pour elle, cela reste transparent, puisque tous les moteurs que l’on peut lui donner respecte la charte d’utilisation (on respecte alors le principe I).

L’inversion de contrôle et l’inversion de dépendances ne sont pas des principes très complexe à appréhender ni à mettre en oeuvre pour le peu qu’on les démystifient . Il s’agit surtout d’un principe de décomposition [5], dont le but est le respect des principes SOLID.

Pour l’injection de dépendances, je vous invite au prochain rendez vous, dans un article suivant.

Références

[1] http://un-est-tout-ethttps://blog.imirhil.fr/2013/05/19/inversion-de-controle-cest-bon-mangez-en.html-tout-est-un.blogspot.fr/2018/04/solid.html
[2] https://un-est-tout-et-tout-est-un.blogspot.fr/2017/12/design-pattern-visiteur.html
[3] https://un-est-tout-et-tout-est-un.blogspot.fr/2017/11/design-pattern-strategie.html
[4] https://un-est-tout-et-tout-est-un.blogspot.fr/2017/11/design-pattern-factory.html
[5] https://blog.imirhil.fr/2013/05/19/inversion-de-controle-cest-bon-mangez-en.html

Aucun commentaire:

Enregistrer un commentaire