L'injection de constructeur a l'avantage de rendre la dépendance explicite et d'obliger le client à fournir une instance. Il peut également garantir que le client ne pourra pas modifier l'instance ultérieurement. Un inconvénient (possible) est que vous devez ajouter un paramètre à votre constructeur.
Setter Injection a l'avantage de ne pas nécessiter l'ajout d'un paramètre au constructeur. Il ne nécessite pas non plus que le client définisse l'instance. Ceci est utile pour les dépendances facultatives. Cela peut également être utile si vous souhaitez que la classe crée, par exemple, un référentiel de données réel par défaut, puis dans un test, vous pouvez utiliser le setter pour le remplacer par une instance de test.
L'injection d'interface , pour autant que je sache, n'est pas très différente de l'injection de setter. Dans les deux cas, vous définissez (en option) une dépendance qui peut être modifiée ultérieurement.
En fin de compte, c'est une question de préférence et de savoir si une dépendance est requise ou non . Personnellement, j'utilise l'injection constructeur presque exclusivement. J'aime que cela rend les dépendances d'une classe explicites en forçant le client à fournir une instance dans le constructeur. J'aime aussi que le client ne puisse pas changer l'instance après coup.
Souvent, ma seule raison de passer dans deux implémentations distinctes est pour les tests. En production, je peux réussir un DataRepository
, mais en test, je passerais un FakeDataRepository
. Dans ce cas, je fournirai généralement deux constructeurs: un sans paramètres et un autre qui accepte a IDataRepository
. Ensuite, dans le constructeur sans paramètres, je vais enchaîner un appel au deuxième constructeur et passer un new DataRepository()
.
Voici un exemple en C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
C'est ce qu'on appelle l'injection de dépendance du pauvre. Je l'aime parce que dans le code client de production, je n'ai pas besoin de me répéter en ayant plusieurs instructions répétées qui ressemblent à
var foo = new Foo(new DataRepository());
Cependant, je peux toujours passer dans une autre implémentation pour les tests. Je me rends compte qu'avec Poor Man's DI, je coder en dur ma dépendance, mais c'est acceptable pour moi car j'utilise principalement DI pour les tests.