La inyección de constructor tiene la ventaja de que hace explícita la dependencia y obliga al cliente a proporcionar una instancia. También puede garantizar que el cliente no pueda cambiar la instancia más tarde. Una desventaja (posible) es que debe agregar un parámetro a su constructor.
Setter Injection tiene la ventaja de que no requiere agregar un parámetro al constructor. Tampoco requiere que el cliente configure la instancia. Esto es útil para dependencias opcionales. Esto también puede ser útil si desea que la clase cree, por ejemplo, un repositorio de datos real de forma predeterminada, y luego, en una prueba, puede usar el configurador para reemplazarlo con una instancia de prueba.
La inyección de interfaz , por lo que puedo decir, no es muy diferente a la inyección de setter. En ambos casos, está (opcionalmente) configurando una dependencia que se puede cambiar más adelante.
En última instancia, es una cuestión de preferencia y si se requiere o no una dependencia . Personalmente, uso la inyección de constructor casi exclusivamente. Me gusta que explique las dependencias de una clase al obligar al cliente a proporcionar una instancia en el constructor. También me gusta que el cliente no pueda cambiar la instancia después del hecho.
Muchas veces, mi única razón para pasar dos implementaciones separadas es para probar. En producción, puedo pasar a DataRepository
, pero en pruebas, pasaría a FakeDataRepository
. En este caso, generalmente proporcionaré dos constructores: uno sin parámetros y otro que acepta a IDataRepository
. Luego, en el constructor sin parámetros, encadenaré una llamada al segundo constructor y pasaré a new DataRepository()
.
Aquí hay un ejemplo en C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
Esto se conoce como inyección de dependencia del pobre. Me gusta porque en el código del cliente de producción, no necesito repetirme al tener varias declaraciones repetidas que parecen
var foo = new Foo(new DataRepository());
Sin embargo, todavía puedo pasar una implementación alternativa para las pruebas. Me doy cuenta de que con la DI de Poor Man estoy codificando mi dependencia, pero eso es aceptable para mí, ya que utilizo principalmente DI para las pruebas.