mardi 2 février 2010 14:35
tja
[.NET 4.0] MEF et les containeurs IoC ?
Depuis la toute première apparition de MEF sur codeplex les ambigüités fusent de tous les côtés. Les questions les plus souvent posées sont :
- Quelle est la différence entre un IoC/MEF?
- Dois-je utiliser MEF comme un IoC?
- Peut-on utiliser MEF avec un autre IoC déjà en place?
- MEF est il un IoC?
Bien que je n’ai pas la prétention d’être un expert de MEF, voici comment je le comprends à travers son utilisation et les projets que j’ai fait (suis en train de faire), les discussions sur twitter et mes lectures :). Ce post ne rentre pas dans les détails techniques, c’est juste un point de départ pour une nouvelle discussion.
1. Trois mots clés “Extensibility”, “Discovery”, “Composition”.
MEF se concentre plus particulièrement sur l’extensibilité et la composition. Son but premier est d’étendre les applications en par exemple ajoutant tout simplement un binaire dans un répertoire prédéfini. MEF propose un mécanisme unifié pour atteindre ce but. Le développeurs n’ont plus besoin de réinventer la roue à chaque fois quand un mécanisme similaire est nécessaire.
Donc, MEF en quelque sort peut-être considéré comme un Framework des “plug-ins” quand l’auteur de l’application n’est pas le même (dans la pratique l’auteur de l’application peut coder le deux) que l’auteur du plug-in et que ni l’application ni le plug-in n’ont aucune autre connaissance à part l’interface publiée (contract).
2. Comment tout ceci se rapporte à IoC ?
Pour moi la principale différence (non technique mais fonctionnelle) est que MEF est généralement utilisé pour gérer les “instances” que vous ne connaissez pas et dont vous n’avez rien à faire quel type concret sera derrière l’interface, alors qu’un containeur IoC sert à gérer les “instances” que vous connaissez.
Vous pouvez par exemple avoir enregistré dans votre containeur un Logger pour l’utilisation dans votre application et un autre Logger pour le besoin des tests unitaires. Potentiellement avec MEF vous pourrez avoir de 1 à N Loggers dont vous ne connaissez pas le type et l’implémentation. Encore une fois, l’intention de MEF est de gérer l’extensibilité par plug-in anonymes ce que le différencie d’un conteneur IoC standard.
La où le conteneur IoC est très bon c’est le contrôle de votre code au bas niveau, contrôle de la dépendance des grappes d’objets, gestion de la vie des instances, gestion de l’AOP et des décorateurs.
3. L’un sait faire ce que l’autre ne sait pas faire (et vice versa :))
Effectivement il y a des fonctionnalités qui peuvent être implémentées avec MEF ou un containeur IoC avec plus ou moins d’effort mais comme je l’ai souligné au début de l’article le but de MEF n’est pas le même.
Même dans mes petits projets je favorise l’utilisation d’un containeur IoC. Une de bonnes pratiques d’utilisation d’un containeur IoC et que vous le référencez uniquement dans un endroit appelé le CompositionRoot. Dans la plupart des applications cela est un code lancé au démarrage d’une application comme par exemple Global.asax ou un HttpModule. Ce la veut dire que votre code ne dois plus jamais référencer le conteneur dans un autre endroit. Tout la magique d’un conteneur IoC est qu’il enregistre les objets et leur dépendances et permet de les construire et nous les fournir dès qu’on en a besoin.
Un petit problème
Cependant cela peut poser un petit problème. Dans les applications très larges la configuration centrale peut donner mal à la tête car elle peut vite devenir très difficile à lire et à comprendre. De plus, la configuration centrale peut-être assimilé à des variables globales qui sont accessibles à tout le monde et vous ne savez plus qui les utilise et quand. Bien que la plupart des containeurs IoC donne la possibilité de gérer les sous containeurs dans la pratique il est très difficile de les gérer indépendamment.
Enfin, dans une large application nous risquons de nous retrouver avec des containeurs IoC qui gèrent des centaines des composants enregistrés alors que la plupart des opérations dans l’application n’en utilise que quelque uns. C’est là où je vois la limitation d’un containeur IoC.
MEF again
Ce que permet MEF c’est de diviser votre système en morceaux plus petits. MEF permet de coder les applications comme une série des applications plus petites et quand on relie toutes les applications nous obtenons l’ensemble des fonctionnalités. Comme on a dit, MEF permet la découverte des plug-ins (extensions). Il dispose d’un mécanisme qui en se servant de la metadata peut accéder aux extensions. MEF permet de décorer les extensions avec une metadata additionnelle qui permet les requêtage et le filtres puissants. Combiné avec une capacité de faire du lazy load sur les extensions, d’interroger la metadata avant de charger l’extension permet de scénarios intéressants comme par exemple le versionning des plug-ins.
Conclusion
Je pense que l’utilisation de l’un n’exclu pas l’utilisation de l’autre. Le containeur IoC et MEF ne sont pas destinés pour faire la même chose. Faire cohabiter les deux est une chose un peu plus difficile car il faut bien réfléchir à des aspects qui ne se posent pas lorsque vous développez avec l’un ou l’autre. Quel containeur prend en charge la vie des instances ? Est-ce que MEF peut accéder aux service IoC et comment ? Est-ce que le containeur IoC peut accéder aux exports MEF ? Cela rajoute de la complexité donc réfléchissez bien avant de vous lancer. Il y a des efforts qui sont fait dans ce sens dans MEFcontrib où par exemple une intégration MEF/Unity est possible. De même Castle Windsor est en train de travailler sur le même genre d’intégration.
A bientôt
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :