SlideShare uma empresa Scribd logo
1 de 71
13 juillet 2013© Invenietis 2012-2013
Injection de Dépendances
…les bases
13 juillet 2013© Invenietis 2012-2013
Les Concepts
 Un de 5 principes SOLID
 Dépendances
 IoC – Inversion of Control
 Objets
 « Stateful » ou « Stateless »
 Cycle de vie
 Seam & Composition Root
2
13 juillet 2013© Invenietis 2012-2013
Le discours que vous allez subir…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
3
13 juillet 2013© Invenietis 2012-2013
La conception SOLID
 SRP – Single responsibility principle
• Un objet ⇒ Une responsabilité
 OCP – Open/Closed principle
• Un composant doit être extensible, pas modifiable.
 LSP – Liskov substitution principle
• N’importe quel type compatible doit être substituable.
 ISP – Interface segregation principle
• Des interfaces spécialisées plutôt qu’une générale.
 DIP – Dependency injection principle
• Hollywood principle: « Don’t call us, we’ll call you »
4
13 juillet 2013© Invenietis 2012-2013
Principe fondamental
- Bénéfices
- Conception clarifiée
- Evolution facilitée
- Réutilisabilité élevée
- Mise en œuvre
- Définir des interfaces (ou des classes abstraites) et les utiliser
- Eviter le « new »
Depend on Abstractions, not Concretions
5
13 juillet 2013© Invenietis 2012-2013
Le discours que vous subissez…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 La résolution de dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
6
13 juillet 2013© Invenietis 2012-2013
Qu’est-ce qu’une dépendance ?
 Tout composant, module ou objet « D » qui est extérieur au
composant, module ou objet « C » et dont « C » a besoin pour
fonctionner.
 C’est bien ou c’est mal ?
 Ça dépend…
 …et des fois, ça dépasse.
7
Objet C
(un Contrôleur par exemple)
ConcludeSubscription()
{ Cette méthode doit envoyer un mail… }
Objet D
(un Service d’envoi de Mail par exemple)
SendMail( recipient, body )
{ Cette méthode sait envoyer un mail… }
Dépendance
13 juillet 2013© Invenietis 2012-2013
Le Grand Bazar des Dépendances
8
13 juillet 2013© Invenietis 2012-2013
Le Grand Bazar des Dépendances
• J’utilise « new D() » quand j’en ai besoin.
• Je n’utilise pas « new ».
9
13 juillet 2013© Invenietis 2012-2013
Le Grand Bazar des Dépendances
• J’utilise « new D() » quand j’en ai besoin.
• Je n’utilise pas « new ».
• J’ai un champ qui contient le D à utiliser.
• Je n’ai pas de champ pour D.
10
13 juillet 2013© Invenietis 2012-2013
Le Grand Bazar des Dépendances
• J’utilise « new D() » quand j’en ai besoin.
• Je n’utilise pas « new ».
• J’ai un champ qui contient le D à utiliser.
• Ce champ est exposé en tant que Propriété.
• Ce champ est configuré via une méthode.
• Ce champ ne peut être configuré que depuis le
constructeur.
• Je n’ai pas de champ pour D.
11
13 juillet 2013© Invenietis 2012-2013
Le Grand Bazar des Dépendances
• J’utilise « new D() » quand j’en ai besoin.
• Je n’utilise pas « new ».
• J’ai un champ qui contient le D à utiliser.
• Ce champ est exposé en tant que Propriété.
• Ce champ est configuré via une méthode.
• Ce champ ne peut être configuré que depuis le
constructeur.
• Je n’ai pas de champ pour D.
• Il m’est passé en paramètre de méthode.
• Je vais chercher D dans le « Grand Extérieur »
quand j’en ai besoin.
12
13 juillet 2013© Invenietis 2012-2013
Le discours que vous subissez…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
13
13 juillet 2013© Invenietis 2012-2013
Je n’utilise pas « new » : Inversion of Control
 Je ne contrôle plus la création de la ressource.
 Je me contente d’utiliser un objet (idéalement une Abstraction)
 Je ne contrôle plus son Cycle de Vie
J’ai abandonné le contrôle…
Je viens de vivre une inversion de contrôle.
Ce n’est ni la première, ni la dernière.
A chaque IoC, les développeurs souffrent.
14
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
public void Method()
{
D dep = ???
dep.Run();
}
}
15
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
public void Method()
{
D dep = new D();
dep.Run();
}
}
16
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
D _dep;
public void Method()
{
_dep.Run();
}
}
17
???
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
D _dep;
public D Dep
{
get { return _dep; }
set { _dep = value; }
}
public void Method()
{
_dep.Run();
}
}
18
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
D _dep;
public void Init( D dep,
int rate )
{
_dep = dep;
...
}
public void Method()
{
_dep.Run();
}
}
19
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
readonly D _dep;
public C( D dep, int rate )
{
_dep = dep;
...
}
public void Method()
{
_dep.Run();
}
}
20
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
public void Method( D dep )
{
dep.Run();
}
}
21
13 juillet 2013© Invenietis 2012-2013
Concrètement, simplement.
• « new »
• Pas « new »
• Champ pour D
• Propriété
• Méthode
• Constructeur
• Pas de champ pour D
• Paramètre de méthode
• Le « Grand Extérieur »
public class C
{
public void Method()
{
D dep = ???
dep.Run();
}
}
22
13 juillet 2013© Invenietis 2012-2013
New is NOT dead! (Faut-il tout “externaliser” ?)
 Une Entité est “stateful”
 Elle porte de la donnée (qui, souvent, la définit).
 Une entité est (souvent) créée lorsque l’on en a besoin via “new”
 Un Service est “stateless”
 Plusieurs objest (instances) de MailService représentent, de fait, le même service
 Les Services sont (très souvent) “injectables”
 Les Services dependent des Entités
 En théorie, le contraire est faux
23
Ce que j’aime dans le développement, c’est que, parfois, c’est plus
subtil que cela, et que ces règles doivent s’accomoder d’exceptions.
13 juillet 2013© Invenietis 2012-2013
Le discours que vous subissez…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
24
13 juillet 2013© Invenietis 2012-2013
Le Grand Extérieur ou « How to not new? »
 Ambiant Context
 Et son méchant associé le Singleton
 Service Provider
 Et son collègue le Service Locator
 Factory Method
 Et son grand frère l’Abstract Factory Method
25
Si l’on injecte pas, il faut aller chercher D “dans le Grand Extérieur”.
13 juillet 2013© Invenietis 2012-2013
Les (très) mauvais Singletons
 Très mauvais
 Acceptable… Mais uniquement car accepté (opinion personnelle)…
SuperConfig cfg = (SuperConfig)ConfigurationManager.GetSection( "SuperApp" );
public static class Connection
{
static SqlConnection _con;
static public SqlConnection Default
{
get { return _con ?? (_con = new SqlConnection( "…" ) ); }
}
}
static ILogger _log = LogManager.GetLogger<Connection>();
26
13 juillet 2013© Invenietis 2012-2013
Le bon Singleton : Ambiant Context
 Un Ambiant Context est une Abstraction
 Qui ne fait que fournir de la donnée (lecture seule) ou agir sur
une information « totalement globale ».
 Cette donnée (très globale) étant susceptible d’intéresser
n’importe quel sous-système, n’importe quand.
 Un Ambiant Context par excellence
 Le TimeProvider
À consommer sans modération en lieu et place de
DateTime.UtcNow.
27
13 juillet 2013© Invenietis 2012-2013
The good old Service Provider
 Since .Net framework 1.0
 Au cœur du Component Model, mais aussi de XAML.
 Simple, efficace et souple
 si le Service demandé n’existe pas, null est retourné.
namespace System
{
public interface IServiceProvider
{
object GetService( Type serviceType );
}
}
28
13 juillet 2013© Invenietis 2012-2013
Le Service Locator : une aberration
 « Un Anneau pour les gouverner tous. »
 Tentative d’Abstraction de l’IoC, qui réussit le tour de force d’être à la fois « sur
et sous-designé »…
 ne respecte même pas le contrat du Service Provider (qu’il spécialise).
 A oublier!
namespace Microsoft.Practices.ServiceLocation
{
public interface IServiceLocator : IServiceProvider
{
object GetInstance( Type serviceType );
object GetInstance( Type serviceType, string key );
IEnumerable<object> GetAllInstances( Type serviceType );
TService GetInstance<TService>();
TService GetInstance<TService>( string key );
IEnumerable<TService> GetAllInstances<TService>();
}
}
29
13 juillet 2013© Invenietis 2012-2013
Le Grand Extérieur : L’Usine Center
 Exemple de Factory Methods (2 méthodes statiques, 2 méthodes d’instances)
 En pratique, on appelle une méthode statique:
string fileName = @"C:TempGoogleHomeDownloaded.htm";
WebRequest req = WebRequest.Create( "http://www.google.com" );
using( WebResponse resp = req.GetResponse() )
using( Stream stream = resp.GetResponseStream() )
using( Stream file = File.Create( fileName ) )
{
stream.CopyTo( file );
}
30
public class C
{
public void Method()
{
D dep = DFactory.CreateOneD();
dep.Run();
}
}
13 juillet 2013© Invenietis 2012-2013
Le Grand Extérieur : L’Usine Center
 Mais?! DFactory est donc un singleton!
 Si son fonctionnement doit pouvoir être paramétré, on introduit une Abstract Factory.
 Abstract Factory
public class C
{
public void Method()
{
D dep = theFactory.CreateOneD();
dep.Run();
}
}
public class C
{
public void Method()
{
D dep = DFactory.CreateOneD();
dep.Run();
}
}
Mais ?!
theFactory… est une
dépendance à résoudre !
31
13 juillet 2013© Invenietis 2012-2013
Pour le Grand Extérieur, donc…
 Ambiant Context
 Et son méchant associé le Singleton
 Service Provider
 Et son collègue le Service Locator
 Factory Method
 Et son grand frère l’Abstract Factory Method
Les dépendances sont masquées, implicites,
invisibles sauf à inspecter l’implémentation.
32
13 juillet 2013© Invenietis 2012-2013
Le discours que vous subissez…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
33
13 juillet 2013© Invenietis 2012-2013
L’Injection des Dépendances (Dependency Injection)
• J’utilise « new D() » quand j’en ai besoin.
• Je n’utilise pas « new ».
• J’ai un champ qui contient le D à utiliser.
• Ce champ est exposé en tant que Propriété.
• Ce champ est configuré via une méthode.
• Ce champ ne peut être configuré que depuis le
constructeur.
• Je n’ai pas de champ pour D.
• Il m’est passé en paramètre de méthode.
• Je vais chercher D dans le « Grand Extérieur » quand j’en ai besoin.
Parameter
Injection
Contructor
Injection
Method
Injection
Property
Injection
34
13 juillet 2013© Invenietis 2012-2013
« Don’t call us, we’ll call you. »
 Notion de « Graphe de Dépendances »
 Ces dépendances sont fournies
class C
{
public C( D dep ) { ... }
}
35
13 juillet 2013© Invenietis 2012-2013
« Don’t call us, we’ll call you. »
 Notion de « Graphe de Dépendances »
 Ces dépendances sont fournies
class C
{
public C( D dep ) { ... }
}
class D
{
public D( E e, G db2 )
{ ... }
}
36
13 juillet 2013© Invenietis 2012-2013
« Don’t call us, we’ll call you. »
 Notion de « Graphe de Dépendances »
 Ces dépendances sont fournies
class C
{
public C( D dep ) { ... }
}
class D
{
public D( E e, G db2 )
{ ... }
}
class G
{
public G( string dbName ) { ... }
}
class F
{
public F( string dbName ) { ... }
}
class E
{
public E( F db, G db2 ) { ... }
}
37
13 juillet 2013© Invenietis 2012-2013
static C GiveMeC()
{
var g = new G( "db1" );
var f = new F( "db2" );
return new C( new D( new E( f, g ), g ) );
}
« Don’t call us, we’ll call you. »
 Notion de « Graphe de Dépendances »
 Ces dépendances sont fournies
class C
{
public C( D dep ) { ... }
}
class D
{
public D( E e, G db2 )
{ ... }
}
class G
{
public G( string dbName ) { ... }
}
class F
{
public F( string dbName ) { ... }
}
class E
{
public E( F db, G db2 ) { ... }
}
38
13 juillet 2013© Invenietis 2012-2013
Programming to Abstractions
 Qui décide des implémentations ?
class C : IC
{
public C( ID dep ) { ... }
}
39
?
13 juillet 2013© Invenietis 2012-2013
Programming to Abstractions
 Qui décide des implémentations ?
class C : IC
{
public C( ID dep ) { ... }
}
class D2 : ID
{
public D( IE e, IG db2 )
{ ... }
}
class G : IG
{
public G( string d ) { ... }
}
class FGoogle : IF
{
public FGoogle( int ratio ) { ... }
}
class EV3 : IE
{
public EV3( IF db, IG db2 )
{ ... }
}
40
13 juillet 2013© Invenietis 2012-2013
static IC GiveMeC()
{
var g = new G( "db1" );
var f = new FGoogle( 42 );
return new C( new D2( new EV3( f, g ), g ) );
}
Programming to Abstractions
 Qui décide des implémentations ?
class C : IC
{
public C( ID dep ) { ... }
}
class D2 : ID
{
public D( IE e, IG db2 )
{ ... }
}
class G : IG
{
public G( string d ) { ... }
}
class FGoogle : IF
{
public FGoogle( int ratio ) { ... }
}
class EV3 : IE
{
public EV3( IF db, IG db2 )
{ ... }
}
41
13 juillet 2013© Invenietis 2012-2013
Résoudre les Dépendances
 Abstraction  Concretion
 Gestion des instances : le Cycle de Vie
 FGoogle et G sont des « Singletons », C, D et EV3 sont « Transients »
 Singleton: toujours la même instance retournée à chaque fois que l’on en a besoin.
 Transient: toujours un nouvel objet à chaque fois que l’on en a besoin.
static FGoogle _f;
static G _g;
static IC GiveMeC()
{
if( _f == null ) _f = new FGoogle( 42 );
if( _g == null ) _g = new G( "db1" );
return new C( new D( new EV3( _f, _g ), _g ) );
}
42
13 juillet 2013© Invenietis 2012-2013
 EV3 n’est plus Transient: il est lié à la requête en cours.
 En remplaçant HttpContext.Current.Items par
HttpContext.Current.Session, EV3 sera associé à la Session de l’utilisateur.
static FGoogle _f;
static G _g;
static IC GiveMeC()
{
if( _f == null ) _f = new FGoogle( 42 );
if( _g == null ) _g = new G( "db1" );
IE e = (IE)HttpContext.Current.Items[typeof(IE)];
if( e == null )
{
e = new EV3( _f, _g );
HttpContext.Current.Items[typeof(IE)] = e;
}
return new C( new D( e, _g ) );
}
Entre « Singleton » et « Transient »
43
13 juillet 2013© Invenietis 2012-2013
Le discours que vous subissez…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
44
13 juillet 2013© Invenietis 2012-2013
La règle d’or de la Gestion des Ressources
 Ou encore : celui qui obtient un Objet doit prévenir lorsqu’il n’en a plus besoin.
 Pas si simple en pratique (voire un peu naïf)
 Comment gérer le partage d’objets ?
 La nouvelle implémentation d’un objet requiert une destruction alors que ce n’était pas le cas avant ?
 C’est un des points clés de la conception à surveiller de près.
Celui qui crée un Objet
est celui qui le détruit.
45
13 juillet 2013© Invenietis 2012-2013
Les « Scopes » de Vie
 Une règle simple à respecter (exemple en environnement Web)
 C’est, entre autre, ce qu’un Container de DI facilite
 Mais en pratique, trop souvent, les Scopes ne s’emboitent pas gentiment
comme cela.
Application
Session
Requête
Méthode
X
46
13 juillet 2013© Invenietis 2012-2013
Cycle de Vie et réutilisabilité
 A tout Objet concret est associé un Cycle de Vie, ou Style de Vie.
 Aux extrêmes, les plus simples :
• Transient
• Singleton
 Mais aussi :
• Per Thread
• Per Request
• Per User
• Per Session
• Per Graph
• Per Scope
• …
47
static G _g;
…
return _g ?? (_g = new G( "db1" ));
return new G( "db1" );
13 juillet 2013© Invenietis 2012-2013
Cycle de Vie et réutilisabilité
 A tout Objet concret est associé un Cycle de Vie, ou Style de Vie.
 Aux extrêmes, les plus simples :
• Transient
• Singleton
 Mais aussi :
• Per Thread
• Per Request
• Per User
• Per Session
• Per Graph
• Per Scope
• …
48
IE e = (IE)HttpContext.Current.Items[typeof(IE)];
if( e == null )
{
e = new EV3( _f, _g );
HttpContext.Current.Items[typeof(IE)] = e;
}
return e;
static G _g;
…
return _g ?? (_g = new G( "db1" ));
return new G( "db1" );
var gInGraph = new G( "db1" );
return new C( new D( new E( _f, gInGraph ), gInGraph ) );
13 juillet 2013© Invenietis 2012-2013
Allez, c’est bientôt fini…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
49
13 juillet 2013© Invenietis 2012-2013
Les responsabilités d’un Container de DI
 Associer une Abstraction à une
classe Concrète
 Obtenir un Objet
 Résoudre ses dépendances
 Gérer le Cycle de Vie des Objets
Abstraction
ConcretionInstanciation
Dependencies
50
…Et que ce soit facile à configurer et à utiliser.
…Et si possible, que cela offre d’autres capacités, notamment
permettre des approches « Aspect Oriented Programming »
13 juillet 2013© Invenietis 2012-2013
La DI et le .Net framework
 Une histoire courte… surtout du point de vue de Microsoft
 Spring 1.0 est publié officiellement en mars 2004.
51
From Dependency injection in .Net, Manning 2012
13 juillet 2013© Invenietis 2012-2013
En pratique, 2 exemples
 Castle Windsor
 Très complet, mature et très bien conçu
 Apache License 2.0
 Un des seuls à offrir le tracking d’instances (avec AutoFac)
 Unity
 Issu du groupe Microsoft’s patterns & practices (p&p), supporté par Microsoft
 Microsoft Public License (Ms-PL)
 Complet, correctement extensible
52
13 juillet 2013© Invenietis 2012-2013
 On créé un Container
 On le configure (Register)
 On l’utilise (Resolve)
 On signale la fin de l’utilisation d’un objet (Release)
Principe de fonctionnement
53
Register
Resolve
Release
13 juillet 2013© Invenietis 2012-2013
Principe de fonctionnement
 On créé un Container
 On le configure (Register)
 En enregistrant
 Des Types concrets
 Des associations entre Abstractions (interfaces) et des
Types concrets
 En précisant
 Le Style de Vie
 Des configurations de créations
 On l’utilise (Resolve)
 En résolvant
 Des Abstractions
 Avec si besoin des paramètres
 On signale la fin de l’utilisation d’un objet (Release)
 Pour certains Containers et/ou Styles de Vie
54
Register
Resolve
Release
13 juillet 2013© Invenietis 2012-2013
A quoi cela ressemble ?
 Simple…
55
interface IA
{
void DoSomething();
}
class A : IA
{
public void DoSomething()
{
Console.WriteLine( "A n°{0} do something.", GetHashCode() );
}
}
[TestFixture]
public class RegisterResolve
{
[Test]
public void RegisterAndResolve()
{
UnityContainer c = new UnityContainer();
// Register
c.RegisterType<IA, A>( new ContainerControlledLifetimeManager() );
// Resolve
var a = c.Resolve<IA>();
a.DoSomething();
}
}
13 juillet 2013© Invenietis 2012-2013
Tout ça pour ça ?
 Une énorme Factory éminemment configurable ?
• La configuration est centralisée
• Elle peut s’exprimer en code et/ou en ressources (typiquement en Xml)
• Les dépendances sont gérées automatiquement, quelque soit leurs niveaux
 Un super ServiceProvider ?
• Les implémentations sont masquées, il devient facile de travailler avec des
Abstractions
• Le cycle de vie des objets est géré par le Container, je ne m’en occupe plus
56
Oui ! Mais…
13 juillet 2013© Invenietis 2012-2013
Allez, c’est bientôt fini…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
57
13 juillet 2013© Invenietis 2012-2013
Bien utiliser la DI != Savoir utiliser un Container
 Trop souvent sur- ou mal- utilisé
 Dependency Injection != Utiliser un Container
58
Outillage
Conception
Pas de Container de DI Container de DI
Pas de DI
Couplage fort, problématiques
techniques (constructions, cycle
de vie) intriquées avec le Métier.
Service Locator Anti-Pattern.
Dépendances invisibles, difficile à
maintenir.
DI
Codage à la main de
l’obtention/instanciation des
dépendances.
De nombreux bénéfices associés.
13 juillet 2013© Invenietis 2012-2013
Bien utiliser la DI != Savoir utiliser un Container
 Trop souvent sur- ou mal- utilisé
 Un Container de DI n’est qu’un facilitateur
 Une bonne architecture n’exige pas de Container
 On peut toujours décider de ne pas utiliser de Container
 Avant de l’utiliser, il y a deux notions clés à comprendre
 SEAM : la soudure, le joint
 COMPOSITION ROOT : le support principal de l’injection
59
Before practicing Zen, mountains were mountains and rivers were rivers.
While practicing Zen, mountains are no longer mountains and rivers are no longer rivers.
After realization, mountains are mountains and rivers are rivers again.
13 juillet 2013© Invenietis 2012-2013
SEAM et COMPOSITION ROOT (Démo)
 Un framework (très) simple
 Qui peut fonctionner sans DI
 C’est l’occasion de « voir » la DI à l’œuvre
 Et aussi d’apprendre, un peu, à s’en servir
60
Tout framework bien conçu expose un ou quelques SEAM. Ces « soudures » sont
des points centraux du framework qui instancient des COMPOSITION ROOT qui
sont les objets en charge de la majorité des opérations.
Dans le cadre de MVC, les objets Contrôleurs sont les principaux
COMPOSITION ROOT, et le ControllerFactory le principal SEAM à considérer.
13 juillet 2013© Invenietis 2012-2013
 Chercher le SEAM…
 …y introduire l’unique appel au Container de DI
 …pour obtenir la racine de composition
 Toutes les dépendances de la racine de composition sont résolues…
 …la racine est opérationnelle
 …le système fonctionne.
61
Mise en œuvre de la DI
C’est souvent aussi simple que cela.
Mais, malheureusement, pas toujours…
13 juillet 2013© Invenietis 2012-2013
Dernière ligne droite…
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
62
13 juillet 2013© Invenietis 2012-2013
Lorsque la résolution doit être différée…
 Parce que la dépendance a solliciter dépend du contexte d’exécution
 Multi-tenancy
 Privilèges, niveaux d’accès
 On ne peut donc pas l’injecter systématiquement
 Parce que la dépendance est « optionnelle »
 Elle ne sera sollicitée, statistiquement, que dans quelques cas
 Elle est coûteuse
 on ne souhaite donc pas l’injecter systématiquement
63
Et il ne peut y avoir que deux raisons à cela !
13 juillet 2013© Invenietis 2012-2013
Une Solution, plusieurs mises en œuvre
 Introduire une indirection sous la forme d’une Factory
 La racine de composition dépend de la Factory
 La Factory est sollicitée lorsque la dépendance est nécessaire
 Techniquement, la Factory peut-être :
 Une simple Func<T> qui rappellera le Container
Cette fonction peut comporter des paramètres supplémentaires
 Une interface dédiée
Avec une ou plusieurs méthodes qui renvoient la dépendance…
…et des méthodes qui permettent de signaler la fin de l’utilisation (Release)
64
Factory
13 juillet 2013© Invenietis 2012-2013
Un problème… de dépendances !
 La Factory est liée au type du Container utilisé dans l’Application
 Cela couple le « Métier » à « l’Infrastructure »
 C’est mal!
 Découpler ?
 Func<T> est supporté par la quasi-totalité des Containers
 La meilleure solution est définitivement (de mon point de vue) celle de Castle.Windsor
La « Typed Factory » est une interface qui est automagiquement implémentée.
http://devlicio.us/blogs/krzysztof_kozmic/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx
65
13 juillet 2013© Invenietis 2012-2013
Enfin !
 Programmation SOLID
 Qu’est-ce qu’une dépendance ?
 Qu’est-ce que l’Inversion de Contrôle ?
 Si on est pas à Hollywood, on est dans le « Grand Extérieur »
 L’Injection des Dépendances
 Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »
 Les containers de DI
 La bonne Dependency Injection
 L’enjeu de la « résolution tardive »
 Pièges et Conclusion
66
13 juillet 2013© Invenietis 2012-2013
Quelques pièges de la DI
 Les Containers ne sont pas identiques… loin s’en faut
 Même les basiques divergent
 Certains exigent un enregistrement explicite…
 …d’autres décident d’instancier ce qu’ils veulent (c’est le cas de Unity)
 Les enregistrements multiples, les enregistrements nommés
 Le choix du constructeur quand il y en a plusieurs (faut-il prendre le plus long ou
le plus court ?)
 Opt-in ou Opt-out pour les propriétés ?
 Les dépendances circulaires
 Le contrôle du cycle de vie
 Voir l’annexe qui suit pour les 2 approches.
67
UnityContainer c = new UnityContainer();
var r = c.Resolve<Random>();
13 juillet 2013© Invenietis 2012-2013
Extensibilité des Containers
 Unity, Castle, AutoFac, etc… sont réellement extensibles
 Exemple de Unity
 Corriger le comportent par défaut
 Autres exemples
 Gérer un fallback déterministe sur les enregistrements nommés
 Introduire un mapping automatique de certaines interfaces (« Ambiant Contract »)
68
13 juillet 2013© Invenietis 2012-2013
Conclusion
 Concevoir indépendamment d’un Container
 Comprendre les enjeux de la Conception logicielle
 Viser SOLID
 Utiliser les Containers comme des Facilitateurs
 Ne pas dépendre de leur spécificités
 Rester dans les clous
 Connaître son Container
 Et ne pas hésiter à l’étendre si besoin est
69
13 juillet 2013© Invenietis 2012-2013
Bibliographie
 “Dependency Injection in .Net’, Mark Seeman, Manning 2012
 http://www.martinfowler.com/articles/injection.html
Un must-read…
 http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html
http://kozmic.pl/2010/08/19/must-windsor-track-my-components/
Les tenants du « Le Container doit gérer totalement le cycle de vie » : ce sont principalement des membres de la
communauté Windsor
 http://davybrion.com/blog/2010/02/avoiding-memory-leaks-with-nservicebus-and-your-own-castle-windsor-
instance/
NServiceBus s’adapte à Castle… Mais la conclusion est que NSB doit, un jour, explicitement offrir un point de Release
dans le cadre de son fonctionnement.
 http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/
 Excellent article par le créateur de Autofac qui explique la (très bonne) gestion du Lifetime dans Autofac.
 http://nblumhardt.com/2010/01/the-relationship-zoo/
Toujours un excellent article: une typologie des relations entre les objets.
 http://www.joelonsoftware.com/articles/LeakyAbstractions.html
Joel Spolsky : « All non-trivial abstractions, to some degree, are leaky. »
 http://giorgiosironi.blogspot.com/2009/07/when-to-inject-distinction-between.html
Injecter ou créer ?
 http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/
Démontre le danger des singletons « cachés ». Peut être lue de la même façon comme un argument contre le
ServiceLocator. Cela dit, à mon avis, le problème de fond est dans le fait d’utiliser des classes concrètes (CreditCard)
au lieu d’abstractions (ICreditCard) qui sont de facto décorrélés de leurs implémentations.
70
13 juillet 2013© Invenietis 2012-2013
Cycle de Vie: les deux approches
 Le Container traque les instances (et leurs dépendances)
 Il faut appeler une méthode explicite Release( o ) lorsque l’on ne se sert plus de o
 C’est le mode « Rolls-Royce tout terrain »
• Indépendant du type d’application
• Si les développeurs ET l’infrastructure appellent correctement Release( o )
OU (souvent exclusif)
 L’application gère ses « Scopes »
 Moins de bookkeeping (donc d’overhead)
 Particulièrement adapté au modèle Request/Response
 Sensiblement couplé à un type d’application, un Host particulier
 Lecture fortement recommandée:
 http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/
71

Mais conteúdo relacionado

Semelhante a Injection de dependances - Les bases

OCTO 2012 : Les pratiques des geants du web
OCTO 2012 : Les pratiques des geants du web OCTO 2012 : Les pratiques des geants du web
OCTO 2012 : Les pratiques des geants du web OCTO Technology
 
Sde intervention espace-innovation-juillet-2013-v4
Sde intervention espace-innovation-juillet-2013-v4Sde intervention espace-innovation-juillet-2013-v4
Sde intervention espace-innovation-juillet-2013-v4Hervé BEBIN
 
L'agilité chez Jouve via le Behaviour Driven Development
L'agilité chez Jouve via le Behaviour Driven DevelopmentL'agilité chez Jouve via le Behaviour Driven Development
L'agilité chez Jouve via le Behaviour Driven DevelopmentJouve
 
Les pratiques des geants du web
Les pratiques des geants du webLes pratiques des geants du web
Les pratiques des geants du webStephen PERIN
 
Eloge de la User Story - Agile Tour Bordeaux -
Eloge de la User Story - Agile Tour Bordeaux - Eloge de la User Story - Agile Tour Bordeaux -
Eloge de la User Story - Agile Tour Bordeaux - Cecil Dijoux
 
[Oldies] Club client D2SI : DevOps
[Oldies] Club client D2SI : DevOps [Oldies] Club client D2SI : DevOps
[Oldies] Club client D2SI : DevOps Devoteam Revolve
 
Behaviour Driven Development chez Jouve ITS - Agile Laval 2014
Behaviour Driven Development chez Jouve ITS - Agile Laval 2014Behaviour Driven Development chez Jouve ITS - Agile Laval 2014
Behaviour Driven Development chez Jouve ITS - Agile Laval 2014Serge HARDY
 
Catopsys - Une startup agile et lean
Catopsys - Une startup agile et lean Catopsys - Une startup agile et lean
Catopsys - Une startup agile et lean Daniel Duhautbout
 
Prioriser les chantiers d'accessibilité numérique quand tout est à faire
Prioriser les chantiers d'accessibilité numérique quand tout est à fairePrioriser les chantiers d'accessibilité numérique quand tout est à faire
Prioriser les chantiers d'accessibilité numérique quand tout est à faireQelios
 
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...lyonjug
 
BreizhCamp 2015 - D3js par l'exemple
BreizhCamp 2015 - D3js par l'exempleBreizhCamp 2015 - D3js par l'exemple
BreizhCamp 2015 - D3js par l'exempleRossi Oddet
 
Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)
Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)
Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)Elapse Technologies
 
Intelligence Artificielle - Algorithmes de recherche
Intelligence Artificielle - Algorithmes de rechercheIntelligence Artificielle - Algorithmes de recherche
Intelligence Artificielle - Algorithmes de rechercheMohamed Heny SELMI
 
Génie logiciel - Avant le logiciel
Génie logiciel - Avant le logicielGénie logiciel - Avant le logiciel
Génie logiciel - Avant le logicielJulien Schneider
 
Adaptation d'exécution de modèles : vers des iDSML adaptables
Adaptation d'exécution de modèles : vers des iDSML adaptablesAdaptation d'exécution de modèles : vers des iDSML adaptables
Adaptation d'exécution de modèles : vers des iDSML adaptablesOlivier Le Goaër
 

Semelhante a Injection de dependances - Les bases (20)

OCTO 2012 : Les pratiques des geants du web
OCTO 2012 : Les pratiques des geants du web OCTO 2012 : Les pratiques des geants du web
OCTO 2012 : Les pratiques des geants du web
 
Sde intervention espace-innovation-juillet-2013-v4
Sde intervention espace-innovation-juillet-2013-v4Sde intervention espace-innovation-juillet-2013-v4
Sde intervention espace-innovation-juillet-2013-v4
 
Startup driven development
Startup driven developmentStartup driven development
Startup driven development
 
L'agilité chez Jouve via le Behaviour Driven Development
L'agilité chez Jouve via le Behaviour Driven DevelopmentL'agilité chez Jouve via le Behaviour Driven Development
L'agilité chez Jouve via le Behaviour Driven Development
 
Les pratiques des geants du web
Les pratiques des geants du webLes pratiques des geants du web
Les pratiques des geants du web
 
Eloge de la User Story - Agile Tour Bordeaux -
Eloge de la User Story - Agile Tour Bordeaux - Eloge de la User Story - Agile Tour Bordeaux -
Eloge de la User Story - Agile Tour Bordeaux -
 
Ecrire un code Testable
Ecrire un code TestableEcrire un code Testable
Ecrire un code Testable
 
[Oldies] Club client D2SI : DevOps
[Oldies] Club client D2SI : DevOps [Oldies] Club client D2SI : DevOps
[Oldies] Club client D2SI : DevOps
 
Agile pour l'echafaud ATT2020.pptx
Agile pour l'echafaud ATT2020.pptxAgile pour l'echafaud ATT2020.pptx
Agile pour l'echafaud ATT2020.pptx
 
Behaviour Driven Development chez Jouve ITS - Agile Laval 2014
Behaviour Driven Development chez Jouve ITS - Agile Laval 2014Behaviour Driven Development chez Jouve ITS - Agile Laval 2014
Behaviour Driven Development chez Jouve ITS - Agile Laval 2014
 
Catopsys - Une startup agile et lean
Catopsys - Une startup agile et lean Catopsys - Une startup agile et lean
Catopsys - Une startup agile et lean
 
Prioriser les chantiers d'accessibilité numérique quand tout est à faire
Prioriser les chantiers d'accessibilité numérique quand tout est à fairePrioriser les chantiers d'accessibilité numérique quand tout est à faire
Prioriser les chantiers d'accessibilité numérique quand tout est à faire
 
cours1-2-vision-bklog.pdf
cours1-2-vision-bklog.pdfcours1-2-vision-bklog.pdf
cours1-2-vision-bklog.pdf
 
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
Engagement des sociétés d'Ingénierie dans la contribution open source : un ce...
 
BreizhCamp 2015 - D3js par l'exemple
BreizhCamp 2015 - D3js par l'exempleBreizhCamp 2015 - D3js par l'exemple
BreizhCamp 2015 - D3js par l'exemple
 
Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)
Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)
Propulsez votre architecture grâce au TDD et aux mocks (Agile Québec 2013)
 
Intelligence Artificielle - Algorithmes de recherche
Intelligence Artificielle - Algorithmes de rechercheIntelligence Artificielle - Algorithmes de recherche
Intelligence Artificielle - Algorithmes de recherche
 
Algorithmesderecherche 160306125009
Algorithmesderecherche 160306125009Algorithmesderecherche 160306125009
Algorithmesderecherche 160306125009
 
Génie logiciel - Avant le logiciel
Génie logiciel - Avant le logicielGénie logiciel - Avant le logiciel
Génie logiciel - Avant le logiciel
 
Adaptation d'exécution de modèles : vers des iDSML adaptables
Adaptation d'exécution de modèles : vers des iDSML adaptablesAdaptation d'exécution de modèles : vers des iDSML adaptables
Adaptation d'exécution de modèles : vers des iDSML adaptables
 

Injection de dependances - Les bases

  • 1. 13 juillet 2013© Invenietis 2012-2013 Injection de Dépendances …les bases
  • 2. 13 juillet 2013© Invenietis 2012-2013 Les Concepts  Un de 5 principes SOLID  Dépendances  IoC – Inversion of Control  Objets  « Stateful » ou « Stateless »  Cycle de vie  Seam & Composition Root 2
  • 3. 13 juillet 2013© Invenietis 2012-2013 Le discours que vous allez subir…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 3
  • 4. 13 juillet 2013© Invenietis 2012-2013 La conception SOLID  SRP – Single responsibility principle • Un objet ⇒ Une responsabilité  OCP – Open/Closed principle • Un composant doit être extensible, pas modifiable.  LSP – Liskov substitution principle • N’importe quel type compatible doit être substituable.  ISP – Interface segregation principle • Des interfaces spécialisées plutôt qu’une générale.  DIP – Dependency injection principle • Hollywood principle: « Don’t call us, we’ll call you » 4
  • 5. 13 juillet 2013© Invenietis 2012-2013 Principe fondamental - Bénéfices - Conception clarifiée - Evolution facilitée - Réutilisabilité élevée - Mise en œuvre - Définir des interfaces (ou des classes abstraites) et les utiliser - Eviter le « new » Depend on Abstractions, not Concretions 5
  • 6. 13 juillet 2013© Invenietis 2012-2013 Le discours que vous subissez…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  La résolution de dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 6
  • 7. 13 juillet 2013© Invenietis 2012-2013 Qu’est-ce qu’une dépendance ?  Tout composant, module ou objet « D » qui est extérieur au composant, module ou objet « C » et dont « C » a besoin pour fonctionner.  C’est bien ou c’est mal ?  Ça dépend…  …et des fois, ça dépasse. 7 Objet C (un Contrôleur par exemple) ConcludeSubscription() { Cette méthode doit envoyer un mail… } Objet D (un Service d’envoi de Mail par exemple) SendMail( recipient, body ) { Cette méthode sait envoyer un mail… } Dépendance
  • 8. 13 juillet 2013© Invenietis 2012-2013 Le Grand Bazar des Dépendances 8
  • 9. 13 juillet 2013© Invenietis 2012-2013 Le Grand Bazar des Dépendances • J’utilise « new D() » quand j’en ai besoin. • Je n’utilise pas « new ». 9
  • 10. 13 juillet 2013© Invenietis 2012-2013 Le Grand Bazar des Dépendances • J’utilise « new D() » quand j’en ai besoin. • Je n’utilise pas « new ». • J’ai un champ qui contient le D à utiliser. • Je n’ai pas de champ pour D. 10
  • 11. 13 juillet 2013© Invenietis 2012-2013 Le Grand Bazar des Dépendances • J’utilise « new D() » quand j’en ai besoin. • Je n’utilise pas « new ». • J’ai un champ qui contient le D à utiliser. • Ce champ est exposé en tant que Propriété. • Ce champ est configuré via une méthode. • Ce champ ne peut être configuré que depuis le constructeur. • Je n’ai pas de champ pour D. 11
  • 12. 13 juillet 2013© Invenietis 2012-2013 Le Grand Bazar des Dépendances • J’utilise « new D() » quand j’en ai besoin. • Je n’utilise pas « new ». • J’ai un champ qui contient le D à utiliser. • Ce champ est exposé en tant que Propriété. • Ce champ est configuré via une méthode. • Ce champ ne peut être configuré que depuis le constructeur. • Je n’ai pas de champ pour D. • Il m’est passé en paramètre de méthode. • Je vais chercher D dans le « Grand Extérieur » quand j’en ai besoin. 12
  • 13. 13 juillet 2013© Invenietis 2012-2013 Le discours que vous subissez…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 13
  • 14. 13 juillet 2013© Invenietis 2012-2013 Je n’utilise pas « new » : Inversion of Control  Je ne contrôle plus la création de la ressource.  Je me contente d’utiliser un objet (idéalement une Abstraction)  Je ne contrôle plus son Cycle de Vie J’ai abandonné le contrôle… Je viens de vivre une inversion de contrôle. Ce n’est ni la première, ni la dernière. A chaque IoC, les développeurs souffrent. 14
  • 15. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { public void Method() { D dep = ??? dep.Run(); } } 15
  • 16. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { public void Method() { D dep = new D(); dep.Run(); } } 16
  • 17. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { D _dep; public void Method() { _dep.Run(); } } 17 ???
  • 18. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { D _dep; public D Dep { get { return _dep; } set { _dep = value; } } public void Method() { _dep.Run(); } } 18
  • 19. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { D _dep; public void Init( D dep, int rate ) { _dep = dep; ... } public void Method() { _dep.Run(); } } 19
  • 20. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { readonly D _dep; public C( D dep, int rate ) { _dep = dep; ... } public void Method() { _dep.Run(); } } 20
  • 21. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { public void Method( D dep ) { dep.Run(); } } 21
  • 22. 13 juillet 2013© Invenietis 2012-2013 Concrètement, simplement. • « new » • Pas « new » • Champ pour D • Propriété • Méthode • Constructeur • Pas de champ pour D • Paramètre de méthode • Le « Grand Extérieur » public class C { public void Method() { D dep = ??? dep.Run(); } } 22
  • 23. 13 juillet 2013© Invenietis 2012-2013 New is NOT dead! (Faut-il tout “externaliser” ?)  Une Entité est “stateful”  Elle porte de la donnée (qui, souvent, la définit).  Une entité est (souvent) créée lorsque l’on en a besoin via “new”  Un Service est “stateless”  Plusieurs objest (instances) de MailService représentent, de fait, le même service  Les Services sont (très souvent) “injectables”  Les Services dependent des Entités  En théorie, le contraire est faux 23 Ce que j’aime dans le développement, c’est que, parfois, c’est plus subtil que cela, et que ces règles doivent s’accomoder d’exceptions.
  • 24. 13 juillet 2013© Invenietis 2012-2013 Le discours que vous subissez…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 24
  • 25. 13 juillet 2013© Invenietis 2012-2013 Le Grand Extérieur ou « How to not new? »  Ambiant Context  Et son méchant associé le Singleton  Service Provider  Et son collègue le Service Locator  Factory Method  Et son grand frère l’Abstract Factory Method 25 Si l’on injecte pas, il faut aller chercher D “dans le Grand Extérieur”.
  • 26. 13 juillet 2013© Invenietis 2012-2013 Les (très) mauvais Singletons  Très mauvais  Acceptable… Mais uniquement car accepté (opinion personnelle)… SuperConfig cfg = (SuperConfig)ConfigurationManager.GetSection( "SuperApp" ); public static class Connection { static SqlConnection _con; static public SqlConnection Default { get { return _con ?? (_con = new SqlConnection( "…" ) ); } } } static ILogger _log = LogManager.GetLogger<Connection>(); 26
  • 27. 13 juillet 2013© Invenietis 2012-2013 Le bon Singleton : Ambiant Context  Un Ambiant Context est une Abstraction  Qui ne fait que fournir de la donnée (lecture seule) ou agir sur une information « totalement globale ».  Cette donnée (très globale) étant susceptible d’intéresser n’importe quel sous-système, n’importe quand.  Un Ambiant Context par excellence  Le TimeProvider À consommer sans modération en lieu et place de DateTime.UtcNow. 27
  • 28. 13 juillet 2013© Invenietis 2012-2013 The good old Service Provider  Since .Net framework 1.0  Au cœur du Component Model, mais aussi de XAML.  Simple, efficace et souple  si le Service demandé n’existe pas, null est retourné. namespace System { public interface IServiceProvider { object GetService( Type serviceType ); } } 28
  • 29. 13 juillet 2013© Invenietis 2012-2013 Le Service Locator : une aberration  « Un Anneau pour les gouverner tous. »  Tentative d’Abstraction de l’IoC, qui réussit le tour de force d’être à la fois « sur et sous-designé »…  ne respecte même pas le contrat du Service Provider (qu’il spécialise).  A oublier! namespace Microsoft.Practices.ServiceLocation { public interface IServiceLocator : IServiceProvider { object GetInstance( Type serviceType ); object GetInstance( Type serviceType, string key ); IEnumerable<object> GetAllInstances( Type serviceType ); TService GetInstance<TService>(); TService GetInstance<TService>( string key ); IEnumerable<TService> GetAllInstances<TService>(); } } 29
  • 30. 13 juillet 2013© Invenietis 2012-2013 Le Grand Extérieur : L’Usine Center  Exemple de Factory Methods (2 méthodes statiques, 2 méthodes d’instances)  En pratique, on appelle une méthode statique: string fileName = @"C:TempGoogleHomeDownloaded.htm"; WebRequest req = WebRequest.Create( "http://www.google.com" ); using( WebResponse resp = req.GetResponse() ) using( Stream stream = resp.GetResponseStream() ) using( Stream file = File.Create( fileName ) ) { stream.CopyTo( file ); } 30 public class C { public void Method() { D dep = DFactory.CreateOneD(); dep.Run(); } }
  • 31. 13 juillet 2013© Invenietis 2012-2013 Le Grand Extérieur : L’Usine Center  Mais?! DFactory est donc un singleton!  Si son fonctionnement doit pouvoir être paramétré, on introduit une Abstract Factory.  Abstract Factory public class C { public void Method() { D dep = theFactory.CreateOneD(); dep.Run(); } } public class C { public void Method() { D dep = DFactory.CreateOneD(); dep.Run(); } } Mais ?! theFactory… est une dépendance à résoudre ! 31
  • 32. 13 juillet 2013© Invenietis 2012-2013 Pour le Grand Extérieur, donc…  Ambiant Context  Et son méchant associé le Singleton  Service Provider  Et son collègue le Service Locator  Factory Method  Et son grand frère l’Abstract Factory Method Les dépendances sont masquées, implicites, invisibles sauf à inspecter l’implémentation. 32
  • 33. 13 juillet 2013© Invenietis 2012-2013 Le discours que vous subissez…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 33
  • 34. 13 juillet 2013© Invenietis 2012-2013 L’Injection des Dépendances (Dependency Injection) • J’utilise « new D() » quand j’en ai besoin. • Je n’utilise pas « new ». • J’ai un champ qui contient le D à utiliser. • Ce champ est exposé en tant que Propriété. • Ce champ est configuré via une méthode. • Ce champ ne peut être configuré que depuis le constructeur. • Je n’ai pas de champ pour D. • Il m’est passé en paramètre de méthode. • Je vais chercher D dans le « Grand Extérieur » quand j’en ai besoin. Parameter Injection Contructor Injection Method Injection Property Injection 34
  • 35. 13 juillet 2013© Invenietis 2012-2013 « Don’t call us, we’ll call you. »  Notion de « Graphe de Dépendances »  Ces dépendances sont fournies class C { public C( D dep ) { ... } } 35
  • 36. 13 juillet 2013© Invenietis 2012-2013 « Don’t call us, we’ll call you. »  Notion de « Graphe de Dépendances »  Ces dépendances sont fournies class C { public C( D dep ) { ... } } class D { public D( E e, G db2 ) { ... } } 36
  • 37. 13 juillet 2013© Invenietis 2012-2013 « Don’t call us, we’ll call you. »  Notion de « Graphe de Dépendances »  Ces dépendances sont fournies class C { public C( D dep ) { ... } } class D { public D( E e, G db2 ) { ... } } class G { public G( string dbName ) { ... } } class F { public F( string dbName ) { ... } } class E { public E( F db, G db2 ) { ... } } 37
  • 38. 13 juillet 2013© Invenietis 2012-2013 static C GiveMeC() { var g = new G( "db1" ); var f = new F( "db2" ); return new C( new D( new E( f, g ), g ) ); } « Don’t call us, we’ll call you. »  Notion de « Graphe de Dépendances »  Ces dépendances sont fournies class C { public C( D dep ) { ... } } class D { public D( E e, G db2 ) { ... } } class G { public G( string dbName ) { ... } } class F { public F( string dbName ) { ... } } class E { public E( F db, G db2 ) { ... } } 38
  • 39. 13 juillet 2013© Invenietis 2012-2013 Programming to Abstractions  Qui décide des implémentations ? class C : IC { public C( ID dep ) { ... } } 39 ?
  • 40. 13 juillet 2013© Invenietis 2012-2013 Programming to Abstractions  Qui décide des implémentations ? class C : IC { public C( ID dep ) { ... } } class D2 : ID { public D( IE e, IG db2 ) { ... } } class G : IG { public G( string d ) { ... } } class FGoogle : IF { public FGoogle( int ratio ) { ... } } class EV3 : IE { public EV3( IF db, IG db2 ) { ... } } 40
  • 41. 13 juillet 2013© Invenietis 2012-2013 static IC GiveMeC() { var g = new G( "db1" ); var f = new FGoogle( 42 ); return new C( new D2( new EV3( f, g ), g ) ); } Programming to Abstractions  Qui décide des implémentations ? class C : IC { public C( ID dep ) { ... } } class D2 : ID { public D( IE e, IG db2 ) { ... } } class G : IG { public G( string d ) { ... } } class FGoogle : IF { public FGoogle( int ratio ) { ... } } class EV3 : IE { public EV3( IF db, IG db2 ) { ... } } 41
  • 42. 13 juillet 2013© Invenietis 2012-2013 Résoudre les Dépendances  Abstraction  Concretion  Gestion des instances : le Cycle de Vie  FGoogle et G sont des « Singletons », C, D et EV3 sont « Transients »  Singleton: toujours la même instance retournée à chaque fois que l’on en a besoin.  Transient: toujours un nouvel objet à chaque fois que l’on en a besoin. static FGoogle _f; static G _g; static IC GiveMeC() { if( _f == null ) _f = new FGoogle( 42 ); if( _g == null ) _g = new G( "db1" ); return new C( new D( new EV3( _f, _g ), _g ) ); } 42
  • 43. 13 juillet 2013© Invenietis 2012-2013  EV3 n’est plus Transient: il est lié à la requête en cours.  En remplaçant HttpContext.Current.Items par HttpContext.Current.Session, EV3 sera associé à la Session de l’utilisateur. static FGoogle _f; static G _g; static IC GiveMeC() { if( _f == null ) _f = new FGoogle( 42 ); if( _g == null ) _g = new G( "db1" ); IE e = (IE)HttpContext.Current.Items[typeof(IE)]; if( e == null ) { e = new EV3( _f, _g ); HttpContext.Current.Items[typeof(IE)] = e; } return new C( new D( e, _g ) ); } Entre « Singleton » et « Transient » 43
  • 44. 13 juillet 2013© Invenietis 2012-2013 Le discours que vous subissez…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 44
  • 45. 13 juillet 2013© Invenietis 2012-2013 La règle d’or de la Gestion des Ressources  Ou encore : celui qui obtient un Objet doit prévenir lorsqu’il n’en a plus besoin.  Pas si simple en pratique (voire un peu naïf)  Comment gérer le partage d’objets ?  La nouvelle implémentation d’un objet requiert une destruction alors que ce n’était pas le cas avant ?  C’est un des points clés de la conception à surveiller de près. Celui qui crée un Objet est celui qui le détruit. 45
  • 46. 13 juillet 2013© Invenietis 2012-2013 Les « Scopes » de Vie  Une règle simple à respecter (exemple en environnement Web)  C’est, entre autre, ce qu’un Container de DI facilite  Mais en pratique, trop souvent, les Scopes ne s’emboitent pas gentiment comme cela. Application Session Requête Méthode X 46
  • 47. 13 juillet 2013© Invenietis 2012-2013 Cycle de Vie et réutilisabilité  A tout Objet concret est associé un Cycle de Vie, ou Style de Vie.  Aux extrêmes, les plus simples : • Transient • Singleton  Mais aussi : • Per Thread • Per Request • Per User • Per Session • Per Graph • Per Scope • … 47 static G _g; … return _g ?? (_g = new G( "db1" )); return new G( "db1" );
  • 48. 13 juillet 2013© Invenietis 2012-2013 Cycle de Vie et réutilisabilité  A tout Objet concret est associé un Cycle de Vie, ou Style de Vie.  Aux extrêmes, les plus simples : • Transient • Singleton  Mais aussi : • Per Thread • Per Request • Per User • Per Session • Per Graph • Per Scope • … 48 IE e = (IE)HttpContext.Current.Items[typeof(IE)]; if( e == null ) { e = new EV3( _f, _g ); HttpContext.Current.Items[typeof(IE)] = e; } return e; static G _g; … return _g ?? (_g = new G( "db1" )); return new G( "db1" ); var gInGraph = new G( "db1" ); return new C( new D( new E( _f, gInGraph ), gInGraph ) );
  • 49. 13 juillet 2013© Invenietis 2012-2013 Allez, c’est bientôt fini…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 49
  • 50. 13 juillet 2013© Invenietis 2012-2013 Les responsabilités d’un Container de DI  Associer une Abstraction à une classe Concrète  Obtenir un Objet  Résoudre ses dépendances  Gérer le Cycle de Vie des Objets Abstraction ConcretionInstanciation Dependencies 50 …Et que ce soit facile à configurer et à utiliser. …Et si possible, que cela offre d’autres capacités, notamment permettre des approches « Aspect Oriented Programming »
  • 51. 13 juillet 2013© Invenietis 2012-2013 La DI et le .Net framework  Une histoire courte… surtout du point de vue de Microsoft  Spring 1.0 est publié officiellement en mars 2004. 51 From Dependency injection in .Net, Manning 2012
  • 52. 13 juillet 2013© Invenietis 2012-2013 En pratique, 2 exemples  Castle Windsor  Très complet, mature et très bien conçu  Apache License 2.0  Un des seuls à offrir le tracking d’instances (avec AutoFac)  Unity  Issu du groupe Microsoft’s patterns & practices (p&p), supporté par Microsoft  Microsoft Public License (Ms-PL)  Complet, correctement extensible 52
  • 53. 13 juillet 2013© Invenietis 2012-2013  On créé un Container  On le configure (Register)  On l’utilise (Resolve)  On signale la fin de l’utilisation d’un objet (Release) Principe de fonctionnement 53 Register Resolve Release
  • 54. 13 juillet 2013© Invenietis 2012-2013 Principe de fonctionnement  On créé un Container  On le configure (Register)  En enregistrant  Des Types concrets  Des associations entre Abstractions (interfaces) et des Types concrets  En précisant  Le Style de Vie  Des configurations de créations  On l’utilise (Resolve)  En résolvant  Des Abstractions  Avec si besoin des paramètres  On signale la fin de l’utilisation d’un objet (Release)  Pour certains Containers et/ou Styles de Vie 54 Register Resolve Release
  • 55. 13 juillet 2013© Invenietis 2012-2013 A quoi cela ressemble ?  Simple… 55 interface IA { void DoSomething(); } class A : IA { public void DoSomething() { Console.WriteLine( "A n°{0} do something.", GetHashCode() ); } } [TestFixture] public class RegisterResolve { [Test] public void RegisterAndResolve() { UnityContainer c = new UnityContainer(); // Register c.RegisterType<IA, A>( new ContainerControlledLifetimeManager() ); // Resolve var a = c.Resolve<IA>(); a.DoSomething(); } }
  • 56. 13 juillet 2013© Invenietis 2012-2013 Tout ça pour ça ?  Une énorme Factory éminemment configurable ? • La configuration est centralisée • Elle peut s’exprimer en code et/ou en ressources (typiquement en Xml) • Les dépendances sont gérées automatiquement, quelque soit leurs niveaux  Un super ServiceProvider ? • Les implémentations sont masquées, il devient facile de travailler avec des Abstractions • Le cycle de vie des objets est géré par le Container, je ne m’en occupe plus 56 Oui ! Mais…
  • 57. 13 juillet 2013© Invenietis 2012-2013 Allez, c’est bientôt fini…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 57
  • 58. 13 juillet 2013© Invenietis 2012-2013 Bien utiliser la DI != Savoir utiliser un Container  Trop souvent sur- ou mal- utilisé  Dependency Injection != Utiliser un Container 58 Outillage Conception Pas de Container de DI Container de DI Pas de DI Couplage fort, problématiques techniques (constructions, cycle de vie) intriquées avec le Métier. Service Locator Anti-Pattern. Dépendances invisibles, difficile à maintenir. DI Codage à la main de l’obtention/instanciation des dépendances. De nombreux bénéfices associés.
  • 59. 13 juillet 2013© Invenietis 2012-2013 Bien utiliser la DI != Savoir utiliser un Container  Trop souvent sur- ou mal- utilisé  Un Container de DI n’est qu’un facilitateur  Une bonne architecture n’exige pas de Container  On peut toujours décider de ne pas utiliser de Container  Avant de l’utiliser, il y a deux notions clés à comprendre  SEAM : la soudure, le joint  COMPOSITION ROOT : le support principal de l’injection 59 Before practicing Zen, mountains were mountains and rivers were rivers. While practicing Zen, mountains are no longer mountains and rivers are no longer rivers. After realization, mountains are mountains and rivers are rivers again.
  • 60. 13 juillet 2013© Invenietis 2012-2013 SEAM et COMPOSITION ROOT (Démo)  Un framework (très) simple  Qui peut fonctionner sans DI  C’est l’occasion de « voir » la DI à l’œuvre  Et aussi d’apprendre, un peu, à s’en servir 60 Tout framework bien conçu expose un ou quelques SEAM. Ces « soudures » sont des points centraux du framework qui instancient des COMPOSITION ROOT qui sont les objets en charge de la majorité des opérations. Dans le cadre de MVC, les objets Contrôleurs sont les principaux COMPOSITION ROOT, et le ControllerFactory le principal SEAM à considérer.
  • 61. 13 juillet 2013© Invenietis 2012-2013  Chercher le SEAM…  …y introduire l’unique appel au Container de DI  …pour obtenir la racine de composition  Toutes les dépendances de la racine de composition sont résolues…  …la racine est opérationnelle  …le système fonctionne. 61 Mise en œuvre de la DI C’est souvent aussi simple que cela. Mais, malheureusement, pas toujours…
  • 62. 13 juillet 2013© Invenietis 2012-2013 Dernière ligne droite…  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 62
  • 63. 13 juillet 2013© Invenietis 2012-2013 Lorsque la résolution doit être différée…  Parce que la dépendance a solliciter dépend du contexte d’exécution  Multi-tenancy  Privilèges, niveaux d’accès  On ne peut donc pas l’injecter systématiquement  Parce que la dépendance est « optionnelle »  Elle ne sera sollicitée, statistiquement, que dans quelques cas  Elle est coûteuse  on ne souhaite donc pas l’injecter systématiquement 63 Et il ne peut y avoir que deux raisons à cela !
  • 64. 13 juillet 2013© Invenietis 2012-2013 Une Solution, plusieurs mises en œuvre  Introduire une indirection sous la forme d’une Factory  La racine de composition dépend de la Factory  La Factory est sollicitée lorsque la dépendance est nécessaire  Techniquement, la Factory peut-être :  Une simple Func<T> qui rappellera le Container Cette fonction peut comporter des paramètres supplémentaires  Une interface dédiée Avec une ou plusieurs méthodes qui renvoient la dépendance… …et des méthodes qui permettent de signaler la fin de l’utilisation (Release) 64 Factory
  • 65. 13 juillet 2013© Invenietis 2012-2013 Un problème… de dépendances !  La Factory est liée au type du Container utilisé dans l’Application  Cela couple le « Métier » à « l’Infrastructure »  C’est mal!  Découpler ?  Func<T> est supporté par la quasi-totalité des Containers  La meilleure solution est définitivement (de mon point de vue) celle de Castle.Windsor La « Typed Factory » est une interface qui est automagiquement implémentée. http://devlicio.us/blogs/krzysztof_kozmic/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx 65
  • 66. 13 juillet 2013© Invenietis 2012-2013 Enfin !  Programmation SOLID  Qu’est-ce qu’une dépendance ?  Qu’est-ce que l’Inversion de Contrôle ?  Si on est pas à Hollywood, on est dans le « Grand Extérieur »  L’Injection des Dépendances  Les « styles de vies » ou « combien de temps me reste-t-il à vivre? »  Les containers de DI  La bonne Dependency Injection  L’enjeu de la « résolution tardive »  Pièges et Conclusion 66
  • 67. 13 juillet 2013© Invenietis 2012-2013 Quelques pièges de la DI  Les Containers ne sont pas identiques… loin s’en faut  Même les basiques divergent  Certains exigent un enregistrement explicite…  …d’autres décident d’instancier ce qu’ils veulent (c’est le cas de Unity)  Les enregistrements multiples, les enregistrements nommés  Le choix du constructeur quand il y en a plusieurs (faut-il prendre le plus long ou le plus court ?)  Opt-in ou Opt-out pour les propriétés ?  Les dépendances circulaires  Le contrôle du cycle de vie  Voir l’annexe qui suit pour les 2 approches. 67 UnityContainer c = new UnityContainer(); var r = c.Resolve<Random>();
  • 68. 13 juillet 2013© Invenietis 2012-2013 Extensibilité des Containers  Unity, Castle, AutoFac, etc… sont réellement extensibles  Exemple de Unity  Corriger le comportent par défaut  Autres exemples  Gérer un fallback déterministe sur les enregistrements nommés  Introduire un mapping automatique de certaines interfaces (« Ambiant Contract ») 68
  • 69. 13 juillet 2013© Invenietis 2012-2013 Conclusion  Concevoir indépendamment d’un Container  Comprendre les enjeux de la Conception logicielle  Viser SOLID  Utiliser les Containers comme des Facilitateurs  Ne pas dépendre de leur spécificités  Rester dans les clous  Connaître son Container  Et ne pas hésiter à l’étendre si besoin est 69
  • 70. 13 juillet 2013© Invenietis 2012-2013 Bibliographie  “Dependency Injection in .Net’, Mark Seeman, Manning 2012  http://www.martinfowler.com/articles/injection.html Un must-read…  http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html http://kozmic.pl/2010/08/19/must-windsor-track-my-components/ Les tenants du « Le Container doit gérer totalement le cycle de vie » : ce sont principalement des membres de la communauté Windsor  http://davybrion.com/blog/2010/02/avoiding-memory-leaks-with-nservicebus-and-your-own-castle-windsor- instance/ NServiceBus s’adapte à Castle… Mais la conclusion est que NSB doit, un jour, explicitement offrir un point de Release dans le cadre de son fonctionnement.  http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/  Excellent article par le créateur de Autofac qui explique la (très bonne) gestion du Lifetime dans Autofac.  http://nblumhardt.com/2010/01/the-relationship-zoo/ Toujours un excellent article: une typologie des relations entre les objets.  http://www.joelonsoftware.com/articles/LeakyAbstractions.html Joel Spolsky : « All non-trivial abstractions, to some degree, are leaky. »  http://giorgiosironi.blogspot.com/2009/07/when-to-inject-distinction-between.html Injecter ou créer ?  http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/ http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/ Démontre le danger des singletons « cachés ». Peut être lue de la même façon comme un argument contre le ServiceLocator. Cela dit, à mon avis, le problème de fond est dans le fait d’utiliser des classes concrètes (CreditCard) au lieu d’abstractions (ICreditCard) qui sont de facto décorrélés de leurs implémentations. 70
  • 71. 13 juillet 2013© Invenietis 2012-2013 Cycle de Vie: les deux approches  Le Container traque les instances (et leurs dépendances)  Il faut appeler une méthode explicite Release( o ) lorsque l’on ne se sert plus de o  C’est le mode « Rolls-Royce tout terrain » • Indépendant du type d’application • Si les développeurs ET l’infrastructure appellent correctement Release( o ) OU (souvent exclusif)  L’application gère ses « Scopes »  Moins de bookkeeping (donc d’overhead)  Particulièrement adapté au modèle Request/Response  Sensiblement couplé à un type d’application, un Host particulier  Lecture fortement recommandée:  http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/ 71