Ogólnie rzecz biorąc, moje zależności są pobierane z interfejsów, ale będę używał tylko jednej konkretnej implementacji podczas użycia bez testowania. Na przykład, gdybym napisać FooService
:Wstrzykiwanie zależności: co utraciłeś podczas tworzenia instancji klas w konstruktorze bez parametrów?
public class FooService : IFooService
{
private readonly IBarDependency _barDependency;
public FooService(IBarDependency barDependency)
{
this._barDependency = barDependency;
}
public FooService() : this (new BarDependency())
{
// nothing to do here
}
. . . // code goes here
}
Teraz puryści mają tendencję do gasp w horror, bo instancja konkretnej klasy w konstruktora bez parametrów. W przeszłości wzruszyłem ramionami, ponieważ wiem, że jedyną sytuacją, w której nie będę korzystał z konkretnej klasy, jest to, że jestem jednostkowym testerem i kpiną z zależności.
Mimo że łączy w sobie klasę FooService
z klasą BarDependency
, nie jest to połączenie ciasne; te klasy i interfejsy również istnieją w tym samym zespole, więc nie wydaje mi się, że tracę tu dużo lub maluję się w kącie. Nadal mogę łatwo przetestować klasę FooService
, nie uzyskując kodu, którym nie można zarządzać, tylko za pomocą konstruktora, który pozwala mi przekazywać fałszywe interfejsy.
Pytanie brzmi: co jest tutaj zagrożone? Co tracę przy tego typu wzorach, które warto dodać do kontenera IoC?
Używam tego samego podejścia w małych projektach. DI i inne reguły "robienia tego dobrze" zazwyczaj sprawiają, że małe projekty są nazbyt skomplikowane. Oczywiście, przynosi wiele korzyści, ale nie zawsze jest to warte kłopotów. –