Termin techniczny oznaczający przeciwieństwo wstrzykiwania zależności?

12

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?

amfibia
źródło
1
Tak, sprzężenie opisuje zarówno użycie jawnych nazw klas w innych klasach, jak i wynikowy stan bazy kodu.
Kilian Foth,
11
Nie, ścisłe sprzężenie opisuje tylko właściwość wynikowego kodu, a nie przeciwieństwo DI. Możesz używać DI i nadal mieć ciasne połączenie z zupełnie innych powodów.
Doc Brown
1
Zgodzono się, że DI i ścisłe połączenie nie są przeciwieństwami .
Eric King,
@EricKing popisać się. Przy okazji +1.
candied_orange 30.09.16
1
„Ssanie zależności” .
SeldomNeedy

Odpowiedzi:

30

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.

candied_orange
źródło
Tak, twarde kodowanie (zależność), w przeciwieństwie do wstrzykiwania go (w czasie wykonywania), jest dokładnie tym, co chciałem zasugerować, po prostu byłeś trochę szybszy ode mnie.
Doc Brown
7
@DocBrown Czasami chciałbym, żeby to miejsce nie kładło tak dużego nacisku na szybkość. Chciałbym usłyszeć, jak byś to ujął.
candied_orange 30.09.16
Dobra odpowiedź - wstrzyknięcie zależności nie oznacza oddzielenia. Wiara w to prowadzi złą drogą
Ant P
1
@CandiedOrange Może ktoś powinien zasugerować w meta, aby odpowiedzi pozostały ukryte przez pewien czas. I / lub, że głosy będą ukryte przed widokiem publicznym na wiele Ngodzin ... 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!
svidgen
1
@svidgen szukaj „najszybszy pistolet na zachodzie” w serwisie meta. Problem ma już długą historię.
candied_orange 30.09.16
6

Ś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:

public DependencyInjectedConstructor(DependencyClass dep) {
  dep.do();
}

public DependencyLookupConstructor() {
  var dep = new DependencyClass();
  dep.do();
}

DependencyLookupConstructorDependencyClassw tym przypadku jest powiązany z konkretnym . Ale oba są połączone DependencyClass. Prawdziwe zło, jeśli jest tutaj, niekoniecznie musi być sprzężeniem, ale DependencyLookupConstructormusi się zmienić, jeśli DependencyClassnagle trzeba wprowadzić własne zależności 1 .

Jednak ten konstruktor / klasa jest nawet bardziej luźno:

public DependencyLocatingConstructor() {
  var dep = ServiceLocator.GetMyDoer();
  dep.do();
}

Jeśli pracujesz w C #, powyższe pozwoli ci ServiceLocatorzwrócić cokolwiek po GetMyDoer()wywołaniu, o ile ma to, do()co DependencyLocatingConstructorma do(). 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:

  • Wzorzec lokalizatora usług
  • Lokalizator / lokalizacja zależności
  • Bezpośrednia konstrukcja obiektu / zależności
  • Ukryta zależność
  • „Zastrzyk niezależny”

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ć Userlub IUserdo różnych celów: np. Locator.GetAdministrator()Kontra Locator.GetAuthor()- lub cokolwiek innego. Mój kod może zapytać o to, czego potrzebuje funkcjonalnie, nawet nie wiedząc, jakie interfejsy obsługuje.

svidgen
źródło
2
Zbawieniem 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 w IDependency. 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.
candied_orange 30.09.16
Punkty są, DI jeszcze pary Cię do tego interfejsu, a nie wymagać , że DependencyClassbę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” :)
svidgen 30.09.16
Właściwie ... Mogę być trochę poza granicami, mówiąc, że DI koniecznie łączy cię z interfejsem, nawet w języku C #. Chociaż uniknąłem ich w C #, mam wrażenie, że mógłbym również zaakceptować dynamicparametry. (Ale nie varparametry, 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.
svidgen 30.09.16
Obiekty są sprzężone z interfejsami. Czy używasz słowa kluczowego interfejsu, czy nie. Taki jest właściwy interfejs. Wszystko, z czym musisz się połączyć. To, co gotujesz, to szczegóły implementacji i dodatkowe rzeczy, których nie potrzebujesz. Możemy to sformalizować, używając słowa kluczowego interfejsu, aby klient powiedział światu: „Potrzebuję tylko tego”. Ale nie musimy. Chyba potrafimy pisać na klawiaturze, dobrze w niektórych językach.
candied_orange 30.09.16
Nie jestem pewien, czy jesteśmy w całkowitej sprzeczności. Ale, aby wyjaśnić ... Obiekty są wewnętrznie połączone z własnymi interfejsami, tak. Ale sam interfejs nakłada sprzężenie zależności tylko wtedy, gdy interfejs jest jawnie nazwany. W języku C #, używając dynamiclub varpobierając obiekt z lokalizatora, możesz zignorować interfejs i użyć dowolnej klasy, która może do()potrzebować, niezależnie od tego, czy ta klasa implementuje jakiś IDoerinterfejs. 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 zrobi do().
svidgen
2

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 .

McKnz
źródło
2
lubię, instance creationale nie jest wystarczająco szczegółowe. DI tworzy instancje, ale za pomocą kontrolera, a nie na poziomie aplikacji. możeinternal instance creation
amfibia
1

Pójdę z zależności enkapsulacji . Wyraża to, że zależność jest zamknięta, a nie odwiedzana i opuszczana ponownie.

Martin Maat
źródło