Jedynym uzasadnionym anty-wzorcem wstrzykiwania zależności, o którym wiem, jest wzorzec Service Locator , który jest anty-wzorcem, gdy używana jest do niego struktura DI.
Wszystkie inne tak zwane anty-wzorce DI, o których słyszałem, tutaj lub gdzie indziej, są tylko nieco bardziej szczegółowymi przypadkami ogólnych anty-wzorów projektowania OO / oprogramowania. Na przykład:
Nadmierne wstrzyknięcie przez konstruktora stanowi naruszenie zasady pojedynczej odpowiedzialności . Zbyt wiele argumentów konstruktora wskazuje na zbyt wiele zależności; zbyt wiele zależności wskazuje, że klasa próbuje zrobić za dużo. Zwykle ten błąd koreluje z innymi zapachami kodu, takimi jak niezwykle długie lub niejednoznaczne nazwy klas („manager”). Narzędzia analizy statycznej mogą łatwo wykryć nadmierne sprzężenie aferentne / odprowadzające.
Wstrzykiwanie danych, w przeciwieństwie do zachowania, jest podtypem anty-wzorca poltergeist , przy czym geist w tym przypadku jest pojemnikiem. Jeśli klasa musi wiedzieć o bieżącej dacie i godzinie, nie wstrzykujesz DateTime
danych, które są danymi; zamiast tego wstrzykujesz abstrakcję przez zegar systemowy (zwykle nazywam mój ISystemClock
, chociaż myślę, że jest bardziej ogólny w projekcie SystemWrappers ). Jest to nie tylko poprawne dla DI; jest to absolutnie niezbędne dla testowalności, abyś mógł testować zmienne w czasie funkcje bez konieczności faktycznego oczekiwania na nie.
Deklarowanie każdego cyklu życia jako Singleton jest dla mnie doskonałym przykładem programowania kultu kultowego, aw mniejszym stopniu potocznie nazywanym „ obiektowym szambo ”. Widziałem więcej przypadków nadużywania singletonów, niż pamiętam, i bardzo niewiele z nich dotyczy DI.
Innym częstym błędem są specyficzne dla implementacji typy interfejsów (o dziwnych nazwach, takie jak IOracleRepository
), wykonywane tylko po to, aby móc zarejestrować je w kontenerze. To samo w sobie stanowi naruszenie zasady inwersji zależności (tylko dlatego, że jest to interfejs, co nie znaczy, że jest naprawdę abstrakcyjne) i często obejmuje również wzdęcie interfejsu, które narusza zasadę segregacji interfejsu .
Ostatnim błędem, który zazwyczaj widzę, jest „opcjonalna zależność”, którą zrobili w NerdDinner . Innymi słowy, istnieje konstruktor, który akceptuje iniekcji zależność, ale również inny konstruktor, który wykorzystuje „default” wdrożenie. To również jest niezgodny DIP i ma tendencję do prowadzić do LSP naruszeń, jak również, jako twórców, z biegiem czasu, zacznij założenia wokół realizacji domyślny i / lub rozpocząć nowe instancje-ing się przy użyciu domyślnego konstruktora.
Jak mówi stare powiedzenie, możesz pisać FORTRAN w dowolnym języku . Dependency Injection nie jest panaceum, które uniemożliwi deweloperom przekręcane zarządzanie nimi zależności, ale nie zapobiegają wielu typowych błędów / przeciw wzorów:
...i tak dalej.
Oczywiście nie chcesz projektować struktury zależnej od konkretnej implementacji kontenera IoC , takiej jak Unity lub AutoFac. To po raz kolejny narusza DIP. Ale jeśli nawet zastanawiasz się nad zrobieniem czegoś takiego, musiałeś już popełnić kilka błędów projektowych, ponieważ Dependency Injection jest techniką zarządzania zależnościami ogólnego przeznaczenia i nie jest związana z koncepcją kontenera IoC.
Wszystko może skonstruować drzewo zależności; może to jest kontener IoC, może to test jednostkowy z wieloma próbnymi próbami, może to sterownik testowy dostarczający fałszywe dane. Twój framework nie powinien się tym przejmować, a większość frameworków, które widziałem, nie przejmuje się tym, ale nadal intensywnie wykorzystują wstrzykiwanie zależności, dzięki czemu można je łatwo zintegrować z wybranym kontenerem IoC użytkownika końcowego.
DI to nie nauka rakietowa. Po prostu starają się unikać new
, a static
wyjątkiem sytuacji, gdy istnieje powód, aby z nich korzystać, takie jak metoda narzędzie, które nie ma zależności zewnętrzne, lub klasie użytkowej, która nie mogła mieć żadnego celu poza ramami (współdziałanie owijarki i klucze słownika są typowe przykłady to).
Wiele problemów ze strukturami IoC pojawia się, gdy programiści uczą się, jak z nich korzystać, i zamiast zmieniać sposób obsługi zależności i abstrakcji w celu dopasowania do modelu IoC, zamiast tego próbuj manipulować kontenerem IoC, aby spełnić oczekiwania ich stary styl kodowania, który często wymagałby wysokiego sprzężenia i niskiej spójności. Zły kod to zły kod, niezależnie od tego, czy korzysta on z technik DI, czy nie.