L’année 2005 promet d’être celle des conteneurs légers basés sur l’Inversion of control et des notions de programmation orienté aspect.
Inversion of control comme le décrit Michael Spille ou Dependency injection terme inventé par Martin Fowler? La lecture de ces deux articles permet d’avoir les idées assez claires sur la question. Pourtant j’ai toujours eu le sentiment qu’il restait certains éléments m’échappant concernant ces concepts. Par exemple, quelle est la nature de la relation entre Ioc et depency injection si ce n’est pas la même chose?
Je viens de finir la lecture de “J2EE development without EJB” par Rod Johnson (à lire absolument pour tout architecte J2EE) et j’y ai, entre autre, trouvé la réponse à cette question.
L’Inversion of control est le principe selon lequel ce n’est pas à un objet lui-même de déterminer les dépendances dont il a besoin. Mais c’est à un élément externe et centralisé de déterminer pour l’objet les implémentations des autres objets qu’il va utiliser.
Cette technique permet d’assurer le découplage des objets ainsi qu’une grande souplesse dans les possibilités de paramétrage.
L’Ioc est un principe, il existe plusieurs manières de l’implémenter, on en distingue 2 :
– Dependency lookup
– Dependency injection
Le pattern dependency lookup consiste à utiliser un singleton couplé à une factory ou à un registry pour résoudre les dépendances entre objet. Si vous utilisez un service locator, une factory ou JNDI vous faites déjà de l’inversion of control. Mais cette approche présente un défaut : votre objet a au minimum une dépendance avec JNDI, un singleton ou votre factory.
Le pattern Dependency injecty permet de résoudre ce problème et de supprimer quelques lignes de code superflues. C’est le container qui va assembler les objets entre eux et résoudre les dépendances. Vos objets n’ont plus à “trouver” leurs dépendances, elles sont déjà là. Vos objets sont parfaitement découplés, ils ne dépendent plus d’aucune API.
Il existe un débat pour savoir si il vaut mieux utiliser des setters ou un constructeur pour faire l’injection de dépendance, il est quelque peu stéril, ça n’a pas grande importance. Utilisez la méthode qui vous convient le mieux. Si vous utilisez trop de setter ou si le constructeur d’un de vos objets a trop de paramètres c’est sans doute révélateur d’un problème de conception, un objet doit avoir un nombre limité de responsabilités, dans l’idéal une seule.
Voilà pour moi c’est enfin entièrement clair, et vous?
Clair 🙂
Deux avantages immédiats:
– on code par interface. Un objet est dépendant d’autres objets mais qui sont désignés par leur interface. Ils deviennent donc interchangeables et l’objet X peut être remplacé par une autre implémentation ou par un MockObject.
– Expérience perso: Depuis que j pratique ça,j’ai vraiment compris ce qu’étaient les dépendances, les couches et un peu mieux l’objet. Parce que là on sépare vraiment les “concerns”.
– En revanche, on ôte une partie du code de l’appli -ce qui relie les objets – pour le mettre dans un fichier xml. ça peut choquer.
Tout a fait Clair !
Je trouve qu’avec ce type de pattern on concoint ENCORE plus en utilisant les interfaces sans se dire “faut encore faire une factory bla bla …” tout deviens facile, un vrai légo…!
Je me fait souvent la reflexion “Attention de nos fichiers d’assemblage qui deviennent/contiennent de plus en plus d’informations et qui deviennent presques les clés de voutes de nos applications “!
(j’y ajoute les struts-*.xml bien sur…)
Pour défendre le “dependency lookup” je dirai que beaucoup d’esprits ne sont pas prêt à déclarer l’ensemble de leurs objets dans un fichier xml.
Dans une grosse structure où le niveau global java est plutôt bas, l’injection des dépendances par le conteneur est difficile à vendre: l’intéret est dur à expliquer à la fois aux décideurs et aux développeurs. Les gens voient plus la lourdeur de déclarer tous leurs objets dans un fichier de configuration que le gain pour leur application.
Si spring est le socle ioc choisi des arguments coulent de source car de part couplage IOC/AOP il y a des services avec plus-value: remoting, transaction déclarative.
Si pico est le conteneur je ne vois pas d’argument incontestable: la simplification du test des composant et la propreté théorique du code des composants… Ca semble pas assez vendeur…
Ca doit être pou ça que je préfère spring 🙂
Pour le débat setter/constructeur, la solution que j’applique est d’implémenter les deux dans chaque composant comme c’est fait dans spring.
eric