Ostatnio przeczytałem artykuł Marka Seemanna na temat anty-wzorca Service Locator.
Autor wskazuje dwa główne powody, dla których ServiceLocator jest anty-wzorcem:
Problem z używaniem API (z którym jestem w porządku)
Gdy klasa korzysta z lokalizatora usług, bardzo trudno jest zobaczyć jego zależności, ponieważ w większości przypadków klasa ma tylko jeden konstruktor BEZ PARAMETRÓW. W przeciwieństwie do ServiceLocator, podejście DI jawnie uwidacznia zależności za pośrednictwem parametrów konstruktora, dzięki czemu zależności są łatwo widoczne w IntelliSense.Problem konserwacji (który mnie
zastanawia ) Rozważ następujący przykład
Mamy klasę „MyType”, która wykorzystuje podejście do lokalizatora usług:
public class MyType
{
public void MyMethod()
{
var dep1 = Locator.Resolve<IDep1>();
dep1.DoSomething();
}
}
Teraz chcemy dodać kolejną zależność do klasy „MyType”
public class MyType
{
public void MyMethod()
{
var dep1 = Locator.Resolve<IDep1>();
dep1.DoSomething();
// new dependency
var dep2 = Locator.Resolve<IDep2>();
dep2.DoSomething();
}
}
I tu zaczyna się moje nieporozumienie. Autor mówi:
O wiele trudniej jest stwierdzić, czy wprowadzasz przełomową zmianę, czy nie. Musisz zrozumieć całą aplikację, w której używany jest Lokalizator usług, a kompilator ci nie pomoże.
Ale poczekaj chwilę, gdybyśmy używali podejścia DI, wprowadzilibyśmy w konstruktorze zależność z innym parametrem (w przypadku iniekcji konstruktora). A problem nadal będzie istniał. Jeśli możemy zapomnieć o skonfigurowaniu ServiceLocator, możemy zapomnieć o dodaniu nowego mapowania w naszym kontenerze IoC, a podejście DI spowodowałoby ten sam problem w czasie wykonywania.
Autor wspomniał również o trudnościach z testami jednostkowymi. Ale czy nie będziemy mieli problemów z podejściem DI? Czy nie będziemy musieli aktualizować wszystkich testów, które tworzyły instancję tej klasy? Zaktualizujemy je tak, aby przekazywały nową, mockowaną zależność, aby nasz test był kompilowalny. I nie widzę żadnych korzyści z tej aktualizacji i spędzania czasu.
Nie próbuję bronić podejścia Service Locator. Ale to nieporozumienie sprawia, że myślę, że tracę coś bardzo ważnego. Czy ktoś mógłby rozwiać moje wątpliwości?
AKTUALIZACJA (PODSUMOWANIE):
Odpowiedź na moje pytanie „Czy Service Locator jest anty-wzorcem” naprawdę zależy od okoliczności. I zdecydowanie nie sugerowałbym wykreślenia go z listy narzędzi. Może się to okazać bardzo przydatne, gdy zaczniesz zajmować się starszym kodem. Jeśli masz szczęście być na samym początku projektu, podejście DI może być lepszym wyborem, ponieważ ma pewne zalety w porównaniu z lokalizatorem usług.
A oto główne różnice, które przekonały mnie do rezygnacji z usługi Service Locator w nowych projektach:
- Najbardziej oczywiste i najważniejsze: Service Locator ukrywa zależności klas
- Jeśli korzystasz z jakiegoś kontenera IoC, prawdopodobnie przeskanuje on wszystkie konstruktory podczas uruchamiania, aby sprawdzić wszystkie zależności i natychmiast przekaże Ci informacje o brakujących mapowaniach (lub nieprawidłowej konfiguracji); nie jest to możliwe, jeśli używasz kontenera IoC jako lokalizatora usług
Po szczegóły przeczytaj doskonałe odpowiedzi, które podano poniżej.