Używam Dependency Injection (DI) od dłuższego czasu, wstrzykując albo do konstruktora, właściwości lub metody. Nigdy nie czułem potrzeby używania kontenera Inversion of Control (IoC). Im więcej czytam, tym bardziej odczuwam presję ze strony społeczności na korzystanie z kontenera IoC.
Grałem z kontenerami .NET, takimi jak StructureMap , NInject , Unity i Funq . Nadal nie widzę, w jaki sposób kontener IoC przyniesie korzyści / ulepszy mój kod.
Obawiam się również, że zacznę używać kontenera w pracy, ponieważ wielu moich współpracowników zobaczy kod, którego nie rozumieją. Wielu z nich niechętnie uczy się nowych technologii.
Przekonaj mnie, że muszę użyć kontenera IoC. Wykorzystam te argumenty, rozmawiając z innymi programistami w pracy.
Odpowiedzi:
Wow, nie mogę uwierzyć, że Joel sprzyjałby temu:
Nad tym:
Wielu ludzi nie zdaje sobie sprawy, że łańcuch zależności może zostać zagnieżdżony i szybko staje się niewygodne, aby połączyć je ręcznie. Nawet w fabrykach powielanie kodu po prostu nie jest tego warte.
Tak, pojemniki IoC mogą być złożone. Ale w tym prostym przypadku pokazałem, że jest niezwykle łatwy.
OK, uzasadnijmy to jeszcze bardziej. Załóżmy, że masz pewne encje lub obiekty modelu, które chcesz powiązać z inteligentnym interfejsem użytkownika. Ten inteligentny interfejs użytkownika (nazwiemy go Shindows Morms) chce, abyś wdrożył INotifyPropertyChanged, aby mógł odpowiednio śledzić zmiany i odpowiednio aktualizować interfejs użytkownika.
„OK, to nie brzmi tak ciężko”, więc zaczynasz pisać.
Zaczynasz od tego:
.. i skończyć z tym :
To obrzydliwy kod hydrauliczny i utrzymuję, że jeśli piszesz taki kod ręcznie, to kradniesz od swojego klienta . Istnieje lepszy, mądrzejszy sposób pracy.
Słyszałeś kiedyś ten termin, pracujesz mądrzej, a nie ciężej?
Wyobraź sobie, że pojawił się jakiś inteligentny facet z twojego zespołu i powiedział: „Oto łatwiejszy sposób”
Jeśli sprawisz, że twoje nieruchomości będą wirtualne (uspokój się, to nie jest wielka sprawa), możemy automatycznie wplatać się w takie zachowanie nieruchomości. (Nazywa się to AOP, ale nie martw się o nazwę, skup się na tym, co ona dla Ciebie zrobi)
W zależności od używanego narzędzia IoC możesz zrobić coś, co wygląda następująco:
Puf! Cała ta instrukcja INotifyPropertyChanged BS jest teraz automatycznie generowana dla Ciebie na każdym wirtualnym ustawniku właściwości danego obiektu.
Czy to magia? TAK ! Jeśli możesz zaufać faktowi, że ten kod spełnia swoje zadanie, możesz bezpiecznie pominąć całą tę właściwość zawijania mumbo-jumbo. Masz problemy biznesowe do rozwiązania.
Niektóre inne ciekawe zastosowania narzędzia IoC do wykonania AOP:
źródło
Jestem z tobą, Vadim. Kontenery IoC mają prostą, elegancką i przydatną koncepcję i sprawiają, że musisz się uczyć przez dwa dni z 200-stronicowym podręcznikiem.
Osobiście jestem zakłopotany tym, jak społeczność IoC wzięła piękny, elegancki artykuł Martina Fowlera i przekształciła go w kilka złożonych ram, zwykle z 200-300 stronicowymi instrukcjami.
Staram się nie osądzać (HAHA!), Ale myślę, że ludzie, którzy używają kontenerów IoC, są (A) bardzo inteligentni i (B) pozbawieni empatii wobec ludzi, którzy nie są tak mądrzy jak oni. Wszystko ma dla nich doskonały sens, więc mają problem ze zrozumieniem, że wielu zwykłych programistów uzna, że pojęcia są mylące. To przekleństwo wiedzy . Ludzie, którzy rozumieją kontenery IoC, nie mogą uwierzyć, że są ludzie, którzy ich nie rozumieją.
Najcenniejszą zaletą korzystania z kontenera IoC jest to, że możesz mieć przełącznik konfiguracji w jednym miejscu, który pozwala przełączać między, powiedzmy, trybem testowym a trybem produkcyjnym. Załóżmy na przykład, że masz dwie wersje klas dostępu do bazy danych ... jedną wersję, która logowała się agresywnie i przeprowadziła wiele sprawdzeń poprawności, z której korzystałeś podczas programowania, oraz inną wersję bez logowania lub sprawdzania, która była bardzo szybka w produkcji. Miło jest móc przełączać się między nimi w jednym miejscu. Z drugiej strony jest to dość trywialny problem, który można łatwo rozwiązać w prostszy sposób, bez złożoności kontenerów IoC.
Uważam, że jeśli używasz kontenerów IoC, twój kod staje się, szczerze mówiąc, znacznie trudniejszy do odczytania. Liczba miejsc, na które musisz spojrzeć, aby dowiedzieć się, co próbuje zrobić kod, wzrasta o co najmniej jedno. I gdzieś w niebie anioł krzyczy.
źródło
Prawdopodobnie nikt nie zmusza cię do korzystania z frameworku kontenera DI. Już używasz DI do oddzielania swoich klas i poprawiania testowalności, więc zyskujesz wiele korzyści. Krótko mówiąc, preferujesz prostotę, która ogólnie jest dobrą rzeczą.
Jeśli twój system osiąga poziom złożoności, w którym ręczne DI staje się obowiązkiem (to znaczy zwiększa konserwację), zważ to z krzywą uczenia się zespołu szkieletu kontenera DI.
Jeśli potrzebujesz większej kontroli nad zarządzaniem czasem istnienia zależności (to znaczy, jeśli czujesz potrzebę wdrożenia wzorca Singleton), spójrz na pojemniki DI.
Jeśli używasz kontenera DI, używaj tylko potrzebnych funkcji. Pomiń plik konfiguracyjny XML i skonfiguruj go w kodzie, jeśli to wystarczy. Trzymaj się iniekcji konstruktora. Podstawy Unity lub StructureMap można skondensować do kilku stron.
Świetny post na blogu autorstwa Marka Seemanna na ten temat: Kiedy używać kontenera DI
źródło
Moim zdaniem największą zaletą IoC jest możliwość scentralizowania konfiguracji twoich zależności.
Jeśli obecnie używasz wstrzykiwania zależności, kod może wyglądać tak
Jeśli użyłeś statycznej klasy IoC, w przeciwieństwie do IMHO, bardziej skomplikowane pliki konfiguracyjne, możesz mieć coś takiego:
Wtedy twoja statyczna klasa IoC wyglądałaby tak, używam tutaj Unity.
źródło
Kontenery IoC są również dobre do ładowania głęboko zagnieżdżonych zależności klas. Na przykład, jeśli masz następujący kod przy użyciu Depedency Injection.
Jeśli wszystkie te zależności zostały załadowane do kontenera IoC, możesz rozwiązać usługę CustomerService, a wszystkie zależności podrzędne zostaną automatycznie rozwiązane.
Na przykład:
źródło
Jestem fanem deklaratywnego programowania (zobacz, na ile pytań SQL odpowiadam), ale pojemniki IoC, na które patrzyłem, wydają się zbyt tajemnicze dla ich własnego dobra.
... a może twórcy kontenerów IoC nie są w stanie napisać przejrzystej dokumentacji.
... albo oba są prawdziwe w takim czy innym stopniu.
Nie sądzę, że koncepcja kontenera IoC jest zła. Ale implementacja musi być zarówno wydajna (to znaczy elastyczna), aby była użyteczna w wielu różnych aplikacjach, a jednocześnie prosta i łatwa do zrozumienia.
Prawdopodobnie jest ich sześć z pół tuzina innych. Prawdziwa aplikacja (nie zabawka lub wersja demonstracyjna) musi być złożona, biorąc pod uwagę wiele przypadków narożnych i wyjątków od zasad. Albo ujmujesz tę złożoność w kod imperatywny, albo w kod deklaratywny. Ale musisz to gdzieś reprezentować.
źródło
Korzystanie z kontenera polega głównie na zmianie z imperatywnego / skryptowego stylu inicjalizacji i konfiguracji na deklaratywny . Może to mieć kilka różnych korzystnych efektów:
Oczywiście mogą wystąpić trudności:
źródło
Wydaje mi się, że zbudowałeś już własny kontener IoC (używając różnych wzorców opisanych przez Martina Fowlera) i pytasz, dlaczego implementacja kogoś innego jest lepsza niż twoja.
Tak więc masz sporo kodu, który już działa. Zastanawiasz się, dlaczego chcesz zastąpić go implementacją innej osoby.
Plusy za rozważenie kontenera IoC innej firmy
Cons
Więc porównaj swoje zalety do swoich wad i podejmij decyzję.
źródło
Myślę, że większość wartości IoC jest uzyskiwana przy użyciu DI. Ponieważ już to robisz, reszta korzyści ma charakter przyrostowy.
Otrzymana wartość będzie zależeć od rodzaju aplikacji, nad którą pracujesz:
W przypadku wielu dzierżawców kontener IoC może zająć się kodem infrastruktury do ładowania różnych zasobów klienta. Gdy potrzebujesz komponentu specyficznego dla klienta, użyj niestandardowego selektora, aby obsłużyć logikę i nie martw się o to kodem klienta. Z pewnością możesz to zbudować samodzielnie, ale oto przykład, w jaki sposób IoC może pomóc.
Dzięki wielu punktom rozszerzalności IoC może być używany do ładowania komponentów z konfiguracji. Jest to powszechna rzecz do budowania, ale narzędzia są dostarczane przez kontener.
Jeśli chcesz użyć AOP do niektórych przekrojowych problemów, IoC zapewnia haki do przechwytywania wywołań metod. Rzadziej robi się to ad hoc w projektach, ale IoC ułatwia.
Pisałem wcześniej taką funkcjonalność, ale jeśli teraz potrzebuję którejś z tych funkcji, wolę użyć gotowego i przetestowanego narzędzia, jeśli pasuje do mojej architektury.
Jak wspomnieli inni, możesz również centralnie skonfigurować, których klas chcesz używać. Chociaż może to być dobra rzecz, wiąże się to z pewnym błędem i komplikacją. Podstawowe komponenty do większości aplikacji nie są bardzo wymieniane, więc kompromis jest nieco trudniejszy.
Korzystam z kontenera IoC i doceniam jego funkcjonalność, ale muszę przyznać, że zauważyłem kompromis: mój kod staje się bardziej przejrzysty na poziomie klasy i mniej wyraźny na poziomie aplikacji (tj. Wizualizacja przepływu sterowania).
źródło
Jestem uzależniającym się z MKOl. Trudno mi obecnie usprawiedliwić używanie IOC dla DI w większości przypadków. Kontenery MKOl poświęcają sprawdzanie czasu kompilacji, a rzekomo w zamian zapewniają „łatwą” konfigurację, kompleksowe zarządzanie cyklem życia i odkrywanie zależności w czasie rzeczywistym. Uważam, że utrata sprawdzania czasu kompilacji i wynikająca z tego magia / wyjątki w czasie wykonywania nie są warte dzwonków i gwizdów w zdecydowanej większości przypadków. W aplikacjach dla dużych przedsiębiorstw bardzo utrudniają śledzenie tego, co się dzieje.
Nie kupuję argumentu centralizacji, ponieważ można bardzo łatwo scentralizować konfigurację statyczną, używając fabryki abstrakcyjnej dla swojej aplikacji i religijnie odraczając tworzenie obiektów do fabryki abstrakcyjnej, tj. Wykonując odpowiednie DI.
Dlaczego nie wykonać statycznego, pozbawionego magii DI takiego jak ten:
Konfiguracja kontenera jest abstrakcyjną implementacją fabryki, rejestracje są implementacjami abstrakcyjnych elementów członkowskich. Jeśli potrzebujesz nowej zależności singleton, po prostu dodaj inną właściwość abstrakcyjną do fabryki abstrakcyjnych. Jeśli potrzebujesz przejściowej zależności, po prostu dodaj inną metodę i wstrzyknij ją jako Func <>.
Zalety:
Polecam sceptykom, aby wypróbowali kolejny projekt zielonego pola i uczciwie zadaję sobie pytanie, w którym momencie potrzebujesz pojemnika. Łatwo jest później dodać kontener IOC, ponieważ właśnie zastępujesz fabryczną implementację modułem konfiguracji kontenera IOC.
źródło
Największą zaletą korzystania z kontenerów IoC dla mnie (osobiście używam Ninject) było wyeliminowanie przekazywania ustawień i innych rodzajów globalnych obiektów stanu.
Nie programuję dla Internetu, mój jest aplikacją konsolową i w wielu miejscach głęboko w drzewie obiektów muszę mieć dostęp do ustawień lub metadanych określonych przez użytkownika, które są tworzone w całkowicie oddzielnej gałęzi drzewa obiektów. Dzięki IoC po prostu mówię Ninject, aby traktował Ustawienia jako singleton (ponieważ zawsze jest tylko jedna ich instancja), poprosił o Ustawienia lub Słownik w konstruktorze i presto ... pojawiają się magicznie, kiedy ich potrzebuję!
Bez korzystania z kontenera IoC musiałbym przekazać ustawienia i / lub metadane w dół przez 2, 3, ..., n obiektów, zanim byłby faktycznie używany przez obiekt, który go potrzebował.
Kontenery DI / IoC mają wiele innych zalet, ponieważ inne osoby opisały tu szczegółowo, a przejście od pomysłu tworzenia obiektów do zamawiania obiektów może być zaskakujące, ale użycie DI było bardzo pomocne dla mnie i mojego zespołu, więc może możesz to dodać do twojego arsenału!
źródło
Ramy IoC są doskonałe, jeśli chcesz ...
... wyrzucić bezpieczeństwo typu. Wiele (wszystkich?) Struktur IoC zmusza do wykonania kodu, jeśli chcesz mieć pewność, że wszystko jest poprawnie podłączone. „Hej! Mam nadzieję, że wszystko skonfigurowałem, więc moje inicjalizacje tych 100 klas nie zawiodą w produkcji, z wyjątkami zerowymi!”
... miot kod z globalnych (ramy IoC są wszystkim o zmianę stanów globalnych).
... pisz kiepski kod z niejasnymi zależnościami, które trudno refaktoryzować, ponieważ nigdy nie dowiesz się, od czego zależy.
Problem z IoC polega na tym, że ludzie, którzy ich używają, pisali taki kod
co jest oczywiście wadliwe, ponieważ zależność między Foo a Barem jest sztywna. Potem zdali sobie sprawę, że lepiej byłoby napisać podobny kod
co również jest wadliwe, ale mniej oczywiste. W Haskell
Foo()
byłby to typ ,IO Foo
ale tak naprawdę nie chcesz opcjiIO
-part i powinien to być znak ostrzegawczy, że coś jest nie tak z twoim projektem, jeśli go masz.Aby się go pozbyć (część IO), uzyskaj wszystkie zalety frameworków IoC i żadnej z jego wad można zamiast tego użyć abstrakcyjnej fabryki.
Prawidłowe rozwiązanie byłoby podobne
albo może
i wstrzyknąć (ale nie nazwałbym tego wstrzyknięciem) Bar.
Zobacz też: zobacz ten film z Erikiem Meijerem (wynalazcą LINQ), w którym mówi on, że DI jest dla ludzi, którzy nie znają matematyki (i nie mogłem się zgodzić więcej): http://www.youtube.com/watch?v = 8 Mttjyf-8P4
W przeciwieństwie do pana Spolsky'ego nie wierzę, że ludzie, którzy korzystają ze struktur IoC, są bardzo inteligentni - po prostu wierzę, że nie znają matematyki.
źródło
IBar
, tak naprawdę jestIO IBar
). I tak, w przykładzie Haskella Nie mogę uzyskać zerowego odniesienia.Przekonałem się, że prawidłowe wdrożenie Dependency Injection zmusza programistów do korzystania z różnych innych praktyk programistycznych, które pomagają poprawić testowalność, elastyczność, łatwość konserwacji i skalowalność kodu: praktyki takie jak zasada pojedynczej odpowiedzialności, rozdzielenie problemów i kodowanie przeciwko interfejsom API. Wydaje mi się, że jestem zmuszony pisać bardziej modularne klasy i metody wielkości kęsa, co sprawia, że kod jest łatwiejszy do odczytania, ponieważ można go wziąć w kęsy wielkości kęsa.
Ale ma też tendencję do tworzenia raczej dużych drzew zależności, które są znacznie łatwiejsze do zarządzania za pomocą frameworka (szczególnie jeśli używasz konwencji) niż ręcznie. Dzisiaj chciałem przetestować coś naprawdę szybko w LINQPad i pomyślałem, że byłoby zbyt kłopotliwe, aby stworzyć jądro i załadować moje moduły, i ostatecznie napisałem to ręcznie:
Z perspektywy czasu szybsze byłoby użycie frameworka IoC, ponieważ moduły definiują prawie wszystkie te rzeczy zgodnie z konwencją.
Po spędzeniu czasu na studiowaniu odpowiedzi i komentarzy na to pytanie jestem przekonany, że ludzie, którzy są przeciwni korzystaniu z kontenera IoC, nie praktykują prawdziwego wstrzykiwania zależności. Przykłady, które widziałem, to praktyki, które są często mylone z zastrzykiem zależności. Niektóre osoby narzekają na trudności z „odczytaniem” kodu. Prawidłowe wykonanie większości kodu powinno być identyczne przy ręcznym korzystaniu z DI, jak przy korzystaniu z kontenera IoC. Różnica powinna polegać całkowicie na kilku „punktach uruchamiania” w aplikacji.
Innymi słowy, jeśli nie lubisz kontenerów IoC, prawdopodobnie nie robisz Dependency Injection w sposób, w jaki powinien to być zrobiony.
Kolejna kwestia: wstrzyknięcia zależności naprawdę nie można wykonać ręcznie, jeśli używasz odbicia w dowolnym miejscu. Chociaż nienawidzę tego, co robi odbicie w nawigacji kodowej, musisz zdawać sobie sprawę, że istnieją pewne obszary, w których tak naprawdę nie można tego uniknąć. Na przykład program ASP.NET MVC próbuje utworzyć instancję kontrolera poprzez odbicie na każde żądanie. Aby wykonać wstrzyknięcie zależności ręcznie, trzeba uczynić każdy kontroler „kontekstowym katalogiem głównym”:
Porównaj to teraz z zezwoleniem na to dla środowiska DI:
Za pomocą środowiska DI zwróć uwagę, że:
ISimpleWorkflowInstanceMerger
, mogę przetestować, czy została wykorzystana tak, jak się spodziewam, bez potrzeby połączenia z bazą danych ani nic takiego.ISimpleWorkflowInstanceMerger
interfejs. To pozwala mi podzielić aplikację na osobne moduły i zachować prawdziwą architekturę wielowarstwową, co z kolei sprawia, że rzeczy są znacznie bardziej elastyczne.Typowa aplikacja internetowa będzie miała sporo kontrolerów. Cały ból związany z ręcznym wykonywaniem DI w każdym kontrolerze naprawdę się powiększy wraz z rozwojem aplikacji. Jeśli masz aplikację z tylko jednym kontekstowym katalogiem głównym, który nigdy nie próbuje utworzyć instancji usługi przez odbicie, to nie jest to tak duży problem. Niemniej jednak każda aplikacja, która korzysta z Dependency Injection, stanie się wyjątkowo kosztowna w zarządzaniu, gdy osiągnie określony rozmiar, chyba że użyjesz jakiegoś szkieletu do zarządzania wykresem zależności.
źródło
Ilekroć używasz słowa kluczowego „new”, tworzysz konkretną zależność od klasy i mały dzwonek alarmowy powinien rozbrzmiewać w twojej głowie. Trudniej jest przetestować ten obiekt w izolacji. Rozwiązaniem jest zaprogramowanie interfejsów i wstrzyknięcie zależności, aby obiekt mógł być testowany jednostkowo za pomocą wszystkiego, co implementuje ten interfejs (np. Makiety).
Problem polega na tym, że musisz gdzieś budować obiekty. Wzorzec fabryczny to jeden ze sposobów przeniesienia sprzężenia z POXO (zwykły stary „wstaw tutaj swój język OO” Obiekty). Jeśli ty i twoi współpracownicy piszecie taki kod, to kontener IoC jest kolejnym „przyrostowym ulepszeniem”, które możecie wprowadzić do swojej bazy kodu. Przeniesie cały ten paskudny fabryczny kod z czystych obiektów i logiki biznesowej. Zdobędą go i pokochają. Do licha, powiedz firmie, dlaczego to uwielbiasz i zachęć wszystkich.
Jeśli twoi współpracownicy jeszcze nie robią DI, sugeruję, abyś najpierw skupił się na tym. Przekaż, jak napisać czysty kod, który można łatwo przetestować. Czysty kod DI jest trudną częścią, gdy już tam będziesz, przeniesienie logiki okablowania obiektu z klas Factory do kontenera IoC powinno być stosunkowo proste.
źródło
Ponieważ wszystkie zależności są wyraźnie widoczne, promuje tworzenie komponentów, które są luźno powiązane, a jednocześnie łatwo dostępne i wielokrotnego użytku w całej aplikacji.
źródło
Nie potrzebujesz kontenera IoC.
Ale jeśli rygorystycznie przestrzegasz wzorca DI, zauważysz, że posiadanie go usunie mnóstwo zbędnego, nudnego kodu.
W każdym razie często jest to najlepszy czas na użycie biblioteki / frameworka - gdy rozumiesz, co on robi i możesz to zrobić bez biblioteki.
źródło
Tak się składa, że próbuję wyhodować domowy kod DI i zastąpić go MKOl. Prawdopodobnie usunąłem ponad 200 wierszy kodu i zastąpiłem go około 10. Tak, musiałem trochę się nauczyć, jak korzystać z kontenera (Winsor), ale jestem inżynierem pracującym nad technologiami internetowymi w 21 wieku, więc jestem do tego przyzwyczajony. Prawdopodobnie spędziłem około 20 minut, zastanawiając się, jak to zrobić. To było warte mojego czasu.
źródło
W miarę rozdzielania klas i odwracania zależności, klasy pozostają małe, a „wykres zależności” wciąż rośnie. (To nie jest złe.) Korzystanie z podstawowych funkcji kontenera IoC sprawia, że okablowanie wszystkich tych obiektów jest banalne, ale wykonanie go ręcznie może być bardzo uciążliwe. Na przykład, co jeśli chcę utworzyć nową instancję „Foo”, ale potrzebuje ona „paska”. I „Bar” potrzebuje „A”, „B” i „C”. I każda z nich potrzebuje 3 innych rzeczy itp. (Tak, nie mogę wymyślić dobrych fałszywych nazwisk :)).
Użycie kontenera IoC do zbudowania grafu obiektowego zmniejsza złożoność tony i wypycha ją do jednorazowej konfiguracji. Mówię po prostu „stwórz mi Foo”, a to wyjaśnia, co jest potrzebne, aby je zbudować.
Niektóre osoby używają kontenerów IoC do znacznie większej infrastruktury, co jest dobre w przypadku zaawansowanych scenariuszy, ale w tych przypadkach zgadzam się, że może zaciemniać i utrudniać czytanie kodu oraz debugowanie dla nowych deweloperów.
źródło
Dittos o Jedności. Stań się zbyt duży i usłyszysz skrzypienie w krokwiach.
Nigdy nie zaskakuje mnie, gdy ludzie zaczynają mówić o tym, jak czysty wygląd kodu IoC to ci sami ludzie, którzy kiedyś mówili o tym, jak szablony w C ++ były eleganckim sposobem na powrót w latach 90., ale obecnie będą je potępiać jako tajemnicze . Bah!
źródło
W świecie .NET AOP nie jest zbyt popularny, więc dla DI platforma jest Twoją jedyną realną opcją, niezależnie od tego, czy piszesz ją samodzielnie, czy używasz innej.
Jeśli użyłeś AOP, możesz wstrzykiwać podczas kompilacji aplikacji, co jest bardziej powszechne w Javie.
DI ma wiele zalet, takich jak zmniejszone sprzężenie, więc testowanie jednostek jest łatwiejsze, ale jak to zaimplementować? Czy chcesz użyć refleksji, aby zrobić to sam?
źródło
Więc minęły prawie 3 lata, co?
50% osób, które komentowały ramy IoC, nie rozumie różnicy między IoC a IoC Framework. Wątpię, aby wiedzieli, że możesz pisać kod bez wdrażania na serwerze aplikacji
Jeśli weźmiemy najpopularniejszy framework Java Spring, to konfiguracja IoC została przeniesiona z XMl do kodu i teraz wygląda tak
`@Configuracja klasy publicznej AppConfig {
} `I potrzebujemy ram, aby to zrobić, dlaczego dokładnie?
źródło
Szczerze mówiąc, nie widzę wielu przypadków, w których potrzebne są pojemniki IoC, i przez większość czasu po prostu dodają niepotrzebnej złożoności.
Jeśli używasz go tylko do uproszczenia budowy obiektu, musiałbym zapytać, czy tworzysz ten obiekt w więcej niż jednej lokalizacji? Czy singleton nie spełni twoich potrzeb? Czy zmieniasz konfigurację w czasie wykonywania? (Przełączanie typów źródeł danych itp.).
Jeśli tak, może być potrzebny kontener IoC. Jeśli nie, to po prostu odsuwasz inicjalizację od miejsca, w którym programista może ją łatwo zobaczyć.
Kto powiedział, że interfejs jest lepszy niż dziedziczenie? Załóżmy, że testujesz usługę. Dlaczego nie skorzystać z konstruktora DI i stworzyć próbne zależności za pomocą dziedziczenia? Większość usług, z których korzystam, ma tylko kilka zależności. Wykonanie testów jednostkowych w ten sposób zapobiega zachowaniu mnóstwa bezużytecznych interfejsów i oznacza, że nie musisz używać Resharpera, aby szybko znaleźć deklarację metody.
Uważam, że w przypadku większości implementacji stwierdzenie, że kontenery IoC usuwają niepotrzebny kod, jest mitem.
Po pierwsze, najpierw trzeba ustawić pojemnik. Następnie musisz zdefiniować każdy obiekt, który należy zainicjować. Aby nie zapisywać kodu podczas inicjalizacji, należy go przenieść (chyba że obiekt jest używany więcej niż jeden raz. Czy jest lepszy jako Singleton?). Następnie dla każdego obiektu zainicjowanego w ten sposób musisz utworzyć i utrzymywać interfejs.
Ktoś ma jakieś przemyślenia na ten temat?
źródło
ShippingCostCalculator
alboProductUIPresentation
, albo jakiejkolwiek innej strategii / realizacji, w dokładnie tym samym kodzie , poprzez wprowadzenie tylko jednego zmieniony plik XML.Potrzebujesz kontenera IoC, jeśli potrzebujesz scentralizować konfigurację swoich zależności, aby można je było łatwo wymieniać masowo. Jest to najbardziej sensowne w TDD, gdzie wiele zależności jest zamienionych, ale gdzie istnieje niewielka współzależność między zależnościami. Odbywa się to kosztem do pewnego stopnia zaciemnienia przepływu kontroli nad budową obiektów, dlatego ważna jest dobrze zorganizowana i odpowiednio udokumentowana konfiguracja. Dobrze jest mieć powód, aby to zrobić, w przeciwnym razie jest to jedynie pozłacanie abstrakcyjne . Widziałem to tak źle, że zostało sprowadzone do bycia odpowiednikiem instrukcji goto dla konstruktorów.
źródło
Oto dlaczego. Projekt nazywa się IOC-with-Ninject. Możesz pobrać i uruchomić go za pomocą Visual Studio. W tym przykładzie użyto Ninject, ale WSZYSTKIE instrukcje „new” znajdują się w jednym miejscu i można całkowicie zmienić sposób działania aplikacji, zmieniając moduł powiązania, który ma być używany. Przykład skonfigurowano tak, aby można było powiązać z próbną wersją usług lub wersją rzeczywistą. W małych projektach może to nie mieć znaczenia, ale w dużych projektach jest to wielka sprawa.
Dla jasności zalety, jakie widzę: 1) WSZYSTKIE nowe instrukcje w jednym miejscu w katalogu głównym kodu. 2) Całkowicie prześlij ponownie kod z jedną zmianą. 3) Dodatkowe punkty za „fajny czynnik”, ponieważ to ... no cóż: fajne. : p
źródło
Spróbuję dowiedzieć się, dlaczego MKOl może nie być dobry z mojej perspektywy.
Podobnie jak w przypadku wszystkich innych elementów, kontener IOC (lub, jak ująłby to Einstein, I = OC ^ 2) to koncepcja, którą musisz sam zdecydować, czy jej potrzebujesz, czy nie w swoim kodzie. Ostatnie oburzenie mody o MKOl to tylko moda. Nie zakochuj się w modzie, to pierwsze. Istnieje mnóstwo koncepcji, które można zaimplementować w kodzie. Przede wszystkim używam wstrzykiwania zależności, odkąd zacząłem programować i sam nauczyłem się tego terminu, kiedy został spopularyzowany pod tą nazwą. Kontrola zależności jest bardzo starym tematem i do tej pory poruszano ją trylionami sposobów, w zależności od tego, co było oddzielone od czego. Oddzielenie wszystkiego od wszystkiego to nonsens. Problem z kontenerem IOC polega na tym, że próbuje być tak przydatny jak Entity Framework lub NHibernate. Podczas gdy pisanie odwzorowania obiektowo-relacyjnego jest po prostu koniecznością, gdy tylko trzeba połączyć dowolną bazę danych z systemem, kontener IOC nie zawsze jest konieczny. Więc kiedy kontener IOC jest przydatny:
1: Nie jest tak często, że masz tak wiele zależności w kodzie, albo że znasz je na wczesnym etapie projektowania. Myślenie abstrakcyjne jest przydatne, gdy należy myśleć abstrakcyjnie.
2: Łączenie kodu z kodem innej firmy stanowi problem HuGe. Pracowałem z kodem, który ma ponad 10 lat i podążałem w tym czasie za fantazyjnymi i zaawansowanymi koncepcjami ATL, COM, COM + i tak dalej. Teraz nie można nic zrobić z tym kodem. Mówię o tym, że zaawansowana koncepcja daje wyraźną przewagę, ale na dłuższą metę jest ona anulowana z samą przestarzałą przewagą. Po prostu wszystko to uczyniło droższym.
3: Tworzenie oprogramowania jest wystarczająco trudne. Możesz rozszerzyć go na nierozpoznawalne poziomy, jeśli pozwolisz, aby jakiś zaawansowany pomysł pojawił się w kodzie. Wystąpił problem z IOC2. Chociaż jest to zależność odsprzęgająca, oddziela także przepływ logiczny. Wyobraź sobie, że znalazłeś błąd i musisz zrobić sobie przerwę, aby zbadać sytuację. IOC2, jak każda inna zaawansowana koncepcja, utrudnia to. Naprawienie błędu w ramach koncepcji jest trudniejsze niż naprawienie błędu w prostszym kodzie, ponieważ po naprawieniu błędu należy ponownie zastosować się do koncepcji. (Aby dać przykład, C ++ .NET ciągle zmienia składnię tak bardzo, że musisz się zastanowić, zanim zmienisz wersję starszej wersji .NET.) Więc w czym problem z IOC? Problem polega na rozwiązywaniu zależności. Logika rozwiązywania jest zwykle ukryta w samym IOC2, napisane może w niecodzienny sposób, którego musisz się nauczyć i utrzymać. Czy Twój produkt innej firmy będzie dostępny za 5 lat? Microsoft nie był.
Syndrom „Wiemy jak” jest napisany wszędzie w odniesieniu do IOC2. Jest to podobne do testowania automatyzacji. Fantazyjny termin i idealne rozwiązanie na pierwszy rzut oka, wystarczy, że wszystkie testy wykonasz w nocy i zobaczysz wyniki rano. Naprawdę bolesne jest wyjaśnianie firmie po firmie, co tak naprawdę oznaczają testy automatyczne. Zautomatyzowane testowanie zdecydowanie nie jest szybkim sposobem na zmniejszenie liczby błędów, które możesz wprowadzić z dnia na dzień, aby podnieść jakość swojego produktu. Ale moda sprawia, że to pojęcie jest denerwująco dominujące. IOC2 cierpi na ten sam zespół. Uważa się, że należy go wdrożyć, aby oprogramowanie było dobre. KAŻDY ostatni wywiad Zostałem zapytany, czy wdrażam IOC2 i automatyzację. To znak mody: firma miała część kodu napisanego w MFC, której nie porzuci.
Musisz nauczyć się IOC2 jak każdej innej koncepcji oprogramowania. Decyzja, czy należy użyć IOC2, należy do zespołu i firmy. Jednak przed podjęciem decyzji należy podać przynajmniej WSZYSTKIE powyższe argumenty. Tylko jeśli widzisz, że strona plus przewyższa stronę negatywną, możesz podjąć pozytywną decyzję.
Nie ma nic złego w IOC2, z wyjątkiem tego, że rozwiązuje tylko problemy, które rozwiązuje i wprowadza problemy, które wprowadza. Nic więcej. Jednak przeciwstawianie się modzie jest bardzo trudne, mają usta potu, wyznawców wszystkiego. Dziwne, jak nikogo nie ma, kiedy ujawnia się problem z ich fantazją. Broniono wielu koncepcji w branży oprogramowania, ponieważ generują zysk, powstają książki, odbywają się konferencje, powstają nowe produkty. To moda, zwykle krótkotrwała. Gdy tylko ludzie znajdą coś innego, porzucają to całkowicie. IOC2 jest użyteczny, ale wykazuje te same znaki, co wiele innych zaginionych koncepcji, które widziałem. Nie wiem, czy to przetrwa. Nie ma na to żadnej reguły. Myślisz, że jeśli będzie przydatny, przetrwa. Nie, nie idzie tak. Wystarczy jedna duża, bogata firma, a koncepcja może umrzeć w ciągu kilku tygodni. Zobaczymy. NHibernate przeżył, EF zajął drugie miejsce. Może IOC2 też przetrwa. Nie zapominaj, że większość pojęć w tworzeniu oprogramowania nie jest niczym szczególnym, są one bardzo logiczne, proste i oczywiste, a czasem trudniej jest zapamiętać obecną konwencję nazewnictwa niż zrozumieć samą koncepcję. Czy znajomość IOC2 czyni programistę lepszym programistą? Nie, ponieważ jeśli programista nie byłby w stanie wymyślić koncepcji podobnej do IOC2, wówczas trudno będzie mu zrozumieć, który problem rozwiązuje IOC2, korzystanie z niego będzie wyglądać sztucznie i może zacząć z niego korzystać ze względu na polityczną poprawność. Nie zapominaj, że większość pojęć w tworzeniu oprogramowania nie jest niczym szczególnym, są one bardzo logiczne, proste i oczywiste, a czasem trudniej jest zapamiętać obecną konwencję nazewnictwa niż zrozumieć samą koncepcję. Czy znajomość IOC2 czyni programistę lepszym programistą? Nie, ponieważ jeśli programista nie byłby w stanie wymyślić koncepcji podobnej do IOC2, wówczas trudno będzie mu zrozumieć, który problem rozwiązuje IOC2, korzystanie z niego będzie wyglądać sztucznie i może zacząć z niego korzystać ze względu na polityczną poprawność. Nie zapominaj, że większość pojęć w tworzeniu oprogramowania nie jest niczym szczególnym, są one bardzo logiczne, proste i oczywiste, a czasem trudniej jest zapamiętać obecną konwencję nazewnictwa niż zrozumieć samą koncepcję. Czy znajomość IOC2 czyni programistę lepszym programistą? Nie, ponieważ jeśli programista nie byłby w stanie wymyślić koncepcji podobnej do IOC2, wówczas trudno będzie mu zrozumieć, który problem rozwiązuje IOC2, korzystanie z niego będzie wyglądać sztucznie i może zacząć z niego korzystać ze względu na polityczną poprawność. Czy znajomość IOC2 czyni programistę lepszym programistą? Nie, ponieważ jeśli programista nie byłby w stanie wymyślić koncepcji podobnej do IOC2, wówczas trudno będzie mu zrozumieć, który problem rozwiązuje IOC2, korzystanie z niego będzie wyglądać sztucznie i może zacząć z niego korzystać ze względu na polityczną poprawność. Czy znajomość IOC2 czyni programistę lepszym programistą? Nie, ponieważ jeśli programista nie byłby w stanie wymyślić koncepcji podobnej do IOC2, wówczas trudno będzie mu zrozumieć, który problem rozwiązuje IOC2, korzystanie z niego będzie wyglądać sztucznie i może zacząć z niego korzystać ze względu na polityczną poprawność.
źródło
Osobiście używam IoC jako pewnego rodzaju mapy struktury mojej aplikacji (tak, wolę też StructureMap;)). Ułatwia to zastąpienie moich zwykłych implementacji interfejsu implementacjami Moq podczas testów. Utworzenie konfiguracji testowej może być tak proste, jak wykonanie nowego wywołania init do mojej struktury IoC, zastępując dowolną klasę moją granicą testową próbną.
Prawdopodobnie nie jest to po to, aby korzystać z IoC, ale używam go najczęściej ...
źródło
POJEMNIK NA MOC rozwiązuje problem, którego nie mógłbyś mieć, ale to fajny problem
http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-its-a-nice-problem-to-have/
źródło
nie potrzebujesz struktury, aby osiągnąć wstrzyknięcie zależności. Możesz to zrobić również według podstawowych pojęć Java. http://en.wikipedia.org/wiki/Dependency_injection#Code_illustration_using_Java
źródło
Zdaję sobie sprawę, że jest to dość stary post, ale wydaje się, że wciąż jest dość aktywny, i pomyślałem, że przedstawię kilka kwestii, które nie zostały jeszcze wspomniane w innych odpowiedziach.
Powiem, że zgadzam się z zaletami wstrzykiwania zależności, ale wolę samodzielnie konstruować i zarządzać obiektami, używając wzorca podobnego do tego, który zarysował Maxm007 w swojej odpowiedzi. Znalazłem dwa główne problemy z używaniem kontenerów innych firm:
1) Posługiwanie się biblioteką innej firmy „automatycznym” zarządzaniem żywotnością obiektów może przynieść nieoczekiwane rezultaty. Odkryliśmy, że szczególnie w dużych projektach możesz mieć znacznie więcej kopii obiektu, niż się spodziewasz, a nawet więcej, niż gdybyś ręcznie zarządzał cyklami życia. Jestem pewien, że różni się to w zależności od używanego frameworka, ale problem jednak istnieje. Może to być również problematyczne, jeśli obiekt przechowuje zasoby, połączenia danych itp., Ponieważ obiekt może czasami żyć dłużej, niż się spodziewasz. Dlatego nieuchronnie kontenery IoC mają tendencję do zwiększania wykorzystania zasobów i wykorzystania pamięci przez aplikację.
2) Moim zdaniem kontenery IoC są formą „programowania czarnej skrzynki”. Odkryłem, że w szczególności nasi mniej doświadczeni programiści mają tendencję do ich nadużywania. Pozwala to programiście nie myśleć o tym, jak obiekty powinny się ze sobą odnosić ani jak je rozdzielić, ponieważ zapewnia im mechanizm, w którym mogą po prostu złapać dowolny obiekt z powietrza. Np. Może istnieć dobry powód projektowy, że ObjectA nigdy nie powinien wiedzieć o ObjectB bezpośrednio, ale zamiast tworzyć fabrykę, most lub lokalizator usług, niedoświadczony programista po prostu powie „nie ma problemu, po prostu wezmę ObjectB z kontenera IoC „. Może to faktycznie prowadzić do zwiększonego sprzężenia obiektów, co właśnie ma zapobiegać IoC.
źródło
Wstrzykiwanie zależności w projekcie ASP.NET można wykonać za pomocą kilku wierszy kodu. Przypuszczam, że korzystanie z kontenera ma pewną zaletę, gdy masz aplikację, która korzysta z wielu interfejsów i wymaga testów jednostkowych.
źródło