Jest to raczej nomenklatura (pismo techniczne) niż kwestia czysto techniczna. Usiłuję napisać propozycję refaktoryzacji (i przypisać ją sobie), koncentrując się na rozszerzaniu zastrzyku zależności w naszej aplikacji. Chociaż używamy Springa do autouzupełniania fasoli, wciąż istnieją przypadki, w których instancja korzysta z fasoli MyClass obj = new MyClass(...)
, którą można całkowicie wstrzyknąć. Chciałbym, aby moja propozycja wykorzystywała elegancką nomenklaturę i odnosiła się do wzoru przeciwnego do DI z odpowiednim terminem.
Czy „ścisłe połączenie” jest odpowiednim terminem, który jest antonimem dla DI?
Odpowiedzi:
Nie. Ścisłe sprzężenie to znacznie więcej niż to, czym zajmuje się wstrzykiwanie zależności.
Wstrzyknięcie zależności uzewnętrznia decyzję o wdrożeniu. Oddzielenie tego wymaga długiej drogi, ale sprzężenie to coś więcej niż tylko to.
Dobrym antonimem dla wstrzykiwania zależności jest twarde kodowanie zależności . Kiedy konstruujesz (używasz nowej lub bezpośrednio używasz fabryki) w obiekcie zachowania, rozwiałeś dwie różne obawy. Lokalizator usług pomaga rozdzielić, ale pozostawia cię połączonym z samym lokalizatorem usług.
Sprzężenie to coś więcej niż tylko oddzielenie konstrukcji i zachowania. Jeśli mam 101 metod, które muszą być wywoływane w określonej kolejności z klasy A do klasy B, jestem ściśle powiązany. Nie ma znaczenia, jak wspaniale są rozdzielone konstrukcje i zachowania.
Sprzężenie jest miarą współzależności dwóch obiektów. Wszystko, co przyczynia się do utrudniania wprowadzania zmian w jednym bez wpływu na drugi, przyczynia się do łączenia. Zastrzyk zależności pomaga w tym, ale to nie wszystko.
źródło
N
godzin ... Lub do momentu wybrania odpowiedzi. Wiem , że nie jestem całkowicie obiektywny, gdy jedna odpowiedź ma już 10 głosów, a pozostałe 5 odpowiedzi nie ma!Ściśle mówiąc, Wstrzykiwanie Zależności naprawdę przeciwstawia się NIE Wstrzykiwaniu Zależności - i dlatego każda strategia zarządzania zależnością, która nie jest Wstrzykiwaniem Zależności.
[Niechciane] sprzężenie, choć nie do końca ortogonalne, może wystąpić lub zostać złagodzone w obu kierunkach. Oba są powiązane z
DependencyClass
:DependencyLookupConstructor
DependencyClass
w tym przypadku jest powiązany z konkretnym . Ale oba są połączoneDependencyClass
. Prawdziwe zło, jeśli jest tutaj, niekoniecznie musi być sprzężeniem, aleDependencyLookupConstructor
musi się zmienić, jeśliDependencyClass
nagle trzeba wprowadzić własne zależności 1 .Jednak ten konstruktor / klasa jest nawet bardziej luźno:
Jeśli pracujesz w C #, powyższe pozwoli ci
ServiceLocator
zwrócić cokolwiek poGetMyDoer()
wywołaniu, o ile ma to,do()
coDependencyLocatingConstructor
mado()
. Korzyści płynące z sprawdzania poprawności podpisu w czasie kompilacji nie są nawet powiązane z pełnym interfejsem 2 .Więc wybierz swoją truciznę.
Ale w gruncie rzeczy, jeśli istnieje konkretne „przeciwieństwo” wstrzykiwania zależności, byłoby to coś innego w dziedzinie „strategii zarządzania zależnościami”. Między innymi, jeśli użyłeś któregoś z poniższych w rozmowie, rozpoznałbym to jako NIE wstrzykiwanie zależności:
1. Jak na ironię, niektóre problemy rozwiązywane przez DI na wyższych poziomach są niejako wynikiem [nadmiernego] użycia DI na niższych poziomach. Miałem przyjemność pracować na codebases z niepotrzebnej złożoności całego wskutek umieszczenia kilka miejsc, gdzie złożoność że faktycznie pomagały ... Ja wprawdzie dociskany przez złej ekspozycji.
2. Korzystanie z lokalizacji usługi umożliwia także łatwe określenie różnych zależności tego samego typu według ich roli funkcjonalnej z kodu wywołującego , przy jednoczesnym zachowaniu dużej niezależności od sposobu budowania zależności. Załóżmy, że musisz rozwiązać
User
lubIUser
do różnych celów: np.Locator.GetAdministrator()
KontraLocator.GetAuthor()
- lub cokolwiek innego. Mój kod może zapytać o to, czego potrzebuje funkcjonalnie, nawet nie wiedząc, jakie interfejsy obsługuje.źródło
DependencyInjectedConstructor(DependencyClass dep)
jest to, że DependencyClass może być interfejsem lub klasą abstrakcyjną. Dlatego zasmuca mnie to, że kodery C # używają prefiksu interfejsu, jak wIDependency
. Jako klient, to naprawdę nie moja sprawa, czym jest ta zależność. Dopóki go nie zbuduję, wszystko, co muszę wiedzieć, to jak z tym rozmawiać. Co to jest problem kogoś innego.DependencyClass
będzie to abstrakcyjny interfejs w ogóle. Wymaga tylko, aby logika budowy / konfiguracji / lokalizacji istniała „gdzie indziej”. ... Cóż, a bardziej trafnie na pytanie, chodzi o to, że DI nie jest „przeciwieństwem ciasnego sprzężenia” :)dynamic
parametry. (Ale nievar
parametry, jeśli pamięć służy.) Tak więc, z DI w C #, myślę, że albo muszę kodować interfejs, albo całkowicie muszę zrezygnować z sprawdzania poprawności w czasie kompilacji.dynamic
lubvar
pobierając obiekt z lokalizatora, możesz zignorować interfejs i użyć dowolnej klasy, która możedo()
potrzebować, niezależnie od tego, czy ta klasa implementuje jakiśIDoer
interfejs. Innymi słowy, jeśli mamy A-> B <-C, DI oddziela A od C, ale wymaga sprzężenia zarówno A, jak i C z B i uniemożliwia użycie D, nawet jeśli D to zrobido()
.Nie wiem, że istnieje specyficzny, powszechnie akceptowane terminologii przemysłu, ale alternatywy, które przychodzą na myśl to wewnętrzny tworzenie instancji , tworzenie zależności wewnętrznego , lokalne zależności lub lokalnie scoped zależnościami .
źródło
instance creation
ale nie jest wystarczająco szczegółowe. DI tworzy instancje, ale za pomocą kontrolera, a nie na poziomie aplikacji. możeinternal instance creation
Pójdę z zależności enkapsulacji . Wyraża to, że zależność jest zamknięta, a nie odwiedzana i opuszczana ponownie.
źródło