IoC a DI

0

Cześć. Zmagam się ze zrozumieniem pojęć i różnic pomiędzy IoC a DI. Nigdy nie przykuwałem do tego uwagi, po prostu wiedziałem jak się powinno pisać kod.
Nie powinienem robić aby jakaś klasa zależała od drugiej, czyli pisać w klasie Test Class class = new Class();, tylko powinienem wstrzykiwać tę klasę do konstruktora klasy Test. Plusy znam, łatwe utrzymanie, można takie klasy testować zmieniając implementacje.

No ale właśnie, wiem jak to się robi, nie wiem co to dokładnie oznacza. Zawsze mi się wydawało, że to co u góry napisałem, to jest wstrzykiwanie zależności. Gdzieś nad tą klasą tworzę obiekt, który wstrzykuje i to jest właśnie Dependency Injection.

Czy Inversion Of Control jest to cały koncept tego tak jakby? Cały zamysł, a DI to jest tak jakby sposób tego zrobienia?

Przemaglowałem już wiele stron zaczynająć od SO, kończąc na jakiś udziwnionych ścianach tekstu, ale nie mogę tego do końca zrozumieć.
Może mnie ktoś oświecić?

2

IoC to jest forma DI. DI oznacza, że przez konstruktor wstrzykujesz zależności np:


public final class UserService {

private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this,userRepository = userRepository;
}

//reszta kodu
}

Teraz możesz po prostu zamiast w mainie tworzyć cały graf zależności (czyli wywoływać new i przekazywać kolejne reference) użyć do tego kontenera IoC, ale idea jest ta sama. Kontener IoC ma swoje plusi i minusy, jak to ze wszystkim ;)
PS
Można też wstrzykiwac np. przez settery, ale to bardzo głupie, więc założ że tylko przez konstruktor :P

0

Tak, te wszystkie wstrzykiwania znam.
Czyli załóżmy samo tworzenie obiektu w mainie i przesyłanie go do konstruktora to DI? A zamysł wywalenia new z klasy UserService to jest IoC?

0

DI to znaczy że dostarczasz z zewnątrz zależności, a kontener IoC oznacza ze oddelegowujesz do tego framework np. Spring-a

13
  1. IoC to pewna idea i nie należy jej mylić z Dependency Inection ani z kontenerami IoC. IoC do kontenera IoC ma się tak jak krzesło do krzesła elektrycznego.
  2. IoC mówi tylko o tym, żeby nie wiązać się ze szczegółami implementacji innych modułów, a jedynie z kontraktami jakie wystawiają. Dany moduł powinien skupiać sie na wykonywaniu swoich zadań i nie powinien wiedzieć niczego o innych modułach, poza kontraktem/interfejsem jaki oferują. Możemy dzięki temu podmienić moduły na inne i póki kontrakty są poprawne, wszystko musi działać.
  3. DI to sposób realizacji IoC -> wstrzykujemy do modułów implementacje, z których one, poprzez jasno zdefiniowany interfejs, korzystają. Ale to nie jest jedyne rozwiązanie, jakiś ServiceLocator czy Factory też może być realizacją IoC.
  4. Kontener IoC to jest sposób realizacji DI, gdzie składaniem obiektów i wstrzykiwaniem zależności zajmuje się kontener
0

Dostarczam z zewnątrz z zależności, czyli przesyłam do konstruktora.

scibi92 napisał(a):

a IoC oznacza ze oddelegowujesz do tego framework np. Spring-a

W tym wypadku nie mam żadnego framework'a, to o co chodzi :D

2

Można też wstrzykiwac np. przez settery ale to bardzo głupie

Pozwolę sobie dodać coś od siebie bo scibi podał bardzo skąpą "argumentację" ;) Otóż przy definiowaniu zależności jako parametry konstruktora deklarujemy kontrakt danej klasy. Oznacza to że już na etapie tworzenia instancji obiekt musi posiadać poprawny stan, a my w konstruktorze możemy przeprowadzić niezbędną do tego walidację. Wstrzykiwanie zależności poprzez właściwości niczego nie gwarantuje, a nowo utworzony obiekt będzie miał duże prawdopodobieństwo posiadania niewłaściwego stanu jeśli jakaś zależność nie została wstrzyknięta. Z tego też powodu jeśli tylko możliwe należy tego unikać.

0

Przede wszystkim użycie konstruktora oznacza że obiekt jest gotowy od razu do użycia i pozwala uniknąc mutowalności. Jesli współdzielimy referencję np. do jakiegoś serwisu a korzystamy z setterów to ktoś może na chama podmenić implementacje i to rozpropagować dalej.Oczywiście tak na ogół się nie zdarza, ale nie jest to wykluczone.

4

@jajko1233:

co oznacza kontrakt danej klasy?

Możesz go dla uproszczenia utożsamić z interfejsem klasy która jest twoją zaleznością.
Wyobraź sobie że piszesz system który wczytuje dane skądś i zapisuje je w jakiejś postaci. Jak mogło by to wyglądać?

class Loader{
    private final DataCollector dataCollector;
    private final DataSaver dataSaver;

    public void execute(){
        dataSaver.saveData(dataCollector.collectData());
    }
}

Zauważ że nie interesuje nas tutaj czy DataSaver to jest JSONDataSaver czy CSVDataSaver albo DataBaseDataSaver. Interesuje nas tylko, że obiekt który dostaniemy spełnia pewien kontrakt -> dostaje dane i zapisuje je, w sobie znany sposób.
Analogicznie ten nasz DataCollector może pobierać dane z różnych miejsc, w różny sposób, jest to dla nas obojętne o ile spełnia kontrakt -> pobiera dane i zwraca je w odpowiedniej postaci.

Zauważ ze napisaliśmy właśnie kawałek kodu, który może później działać z obiektami które nie istniały kiedy to pisalismy. Za 10 lat napiszesz sobie QuantumSingularityDataSaver, wrzucisz go tutaj i wszystko będzie nadal działać! Nie musimy tego kodu w ogóle ruszać, bo on w ogóle nie wie nic o żadnych konkretnych implementacjach. Będzie działać dla każdego obiektu który spelnia oczekiwany kontrakt.

2

Tak jak już wyżej zostało podkreślone IoC to ogólna idea, polegająca na odwróceniu kontroli, która jest implementowana na kilka sposobów:

dependency injection zamiast tworzyć obiekt samemu, niech ten obiekt zostanie dostarczony z zewnątrz
dependency inversion zamiast polegać na jakimś interfejsie, to ja zdefiniuje interfejs jaki oczekuje i niech mi dostarczą obiekt który spełnia ten interfejs
events zamiast odpytywać czy stan się zmienił w systemie, niech system mnie poinformuje o zmianie (jedna z implementacji to chociażby wzorzec obserwator)
aspect-oriented programming zamiast wywoływać samemu powtarzający się kod (crosscutting concern), niech to ten powtarzający kod sam się wywoła i nie zawraca mi głowy

kolejność w tabelce jest nieprzypadkowa, im niżej tym więcej kontroli oddajemy na zewnątrz, co jest zwykle wygodne z punktu widzenia programisty, tyle że wtedy w systemie się pojawia magia i skoro oddaliśmy tą kontrolę to ciężej jest zapanować nad systemem.

A nazwa kontener IoC się wzięła właśnie stąd, że zwykle taki kontener umożliwia nie tylko DI ale też zwykle inna implementację IoC chociażby aspekty.

1

Nie wiem skąd się nagle wzięło w temacie Aspect oriented Programming, ale warto pamiętać, że to rak. Niektórzy mówią, ze gorszy od GOTO.
Ślepa ścieżka ewolucji programowania obiektowego. Polecam nie zblizać się jesli nie trzeba.
AOP można użyć przy debugowaniu skomplikowanych bugów lub ewentualnie w monitoringu. Pchanie tam czegokolwiek, co jest ważne dla aplikacji (transakcje, security, itp ), to recepta na katastrofę.
Niestety czołowe frameworki javowe tak robią, ale warto chociaż nie dokładać swojego kamyczka.

Alternatywą sensowniejszą dla AOP jest Monada, a w szególności Free Monad.
Problemy łapiemy na etapie kompilacji (a nie w runtime), a do tego możemy łatwo testować zarówno z aspektami, jak i bez.

0

@jarekr000000: sądze że aspekty w typowej aplikacji biznesowej do zarządzania transakcjami czy security są całkiem OK, choć faktycznie sądze że lepiej by default korzystać z innych narzędzi i prawde powiedziawszy nie monad tylko klasycznego obiektowego rozwiązania

0

Decorator niestety uwypukla biedę programowania obiektowego, ale oczywiście, że to lepsze niż ** Stringly typed** AOP.
Poza tym, naprawdę nie sądzę, że jakiś poważniejszy biznes powinien swoje działanie opierać na tym, że akurat kontener będzie miał lepszy dzień, wstaną te aspekty co trzeba i dzieki szcześciu jeszcze podepną się do tych co trzeba metod (bo nikt nie zmieni nazw). Mam jeden projekt gdzie security tzw. runAs przypasowane jest nazwami metod i klas. Miodzio :/

0

Spring Security działa całkiem dobrze z tego co zauważyłem. No i powiedz mi co jest biednego w tych decoratorach i OOP? Bo jak dla mnie OOP jest tak samo dobre jak FP w większości projektów. Odnosze wrażenie że czasami na siłe próbujesz wpychać FP tam gdzie nie trzeba...

0

Tu Mario mści sie na decoratorach (między innymi)

Nic nie usiłuję wpychać. Filozofię wyjaśnia to video:
https://vimeo.com/90738761#t=28m42s

(od wskazanego miejsca - reverse list of bananas)

0

A to aspekty muszą być stringly typed i polegać na nazwach metod? o.O
W innych językach jakoś nie ma takich problemów.

0

@somekind: w Javie tez nie musisz polegać na nazwach metod w aspektach

0

Jeszcze jedno pytanie, bo znalazłem taką definicję

Inversion of Control is a principle in software engineering by which the control of objects or portions of a program is transferred to a container or framework

Jeżeli nie piszę w żadnym frameworku, tylko tworzę prostą aplikację, w której nie tworzę silnych zależności pomiędzy klasami, to w jaki sposób mogę delegować kontrolę do kontenera lub frameworka? Czy jest to błędna definicja?

0

Nie wiem skąd się nagle wzięło w temacie Aspect oriented Programming, ale warto pamiętać, że to rak. Niektórzy mówią, ze gorszy od GOTO.
Ślepa ścieżka ewolucji programowania obiektowego. Polecam nie zblizać się jesli nie trzeba.
AOP można użyć przy debugowaniu skomplikowanych bugów lub ewentualnie w monitoringu. Pchanie tam czegokolwiek, co jest ważne dla aplikacji (transakcje, security, itp ), to recepta na katastrofę.

Czy tylko dla mnie brzmi to jak Kult Cargo przepakowany sezonowym Hype..?

Za miesiąc się okaże, że kontener IOC to zło wcielone...

0
BigosZpomarańczy napisał(a):>

Za miesiąc się okaże, że kontener IOC to zło wcielone...

Z cyklu:
2ddy1a.jpg

Kontenery aplikacji w java

Poza tym nie zło wcielone. Na taki tytuł trzeba sobie zasłużyć.
To po prostu zwykła bieda z nędzą.

1
jarekr000000 napisał(a):
BigosZpomarańczy napisał(a):>

Za miesiąc się okaże, że kontener IOC to zło wcielone...

Z cyklu:
2ddy1a.jpg

Kontenery aplikacji w java

Poza tym nie zło wcielone. Na taki tytuł trzeba sobie zasłużyć.
To po prostu zwykła bieda z nędzą.

Skoro tak wyglądał świat 3000 lat temu to dzisiaj powinno być mniej więcej tak:

Albo tak:

3

Nie chcę brać udziału w tej dyskusji bo to chyba 50-ta z tej serii, nie chcę też tworzyć jakichś ulotnych i łatwo podważalnych definicji, ale chciałbym wyprostować jedno pojęcie.

Podano tu nieścisłe twierdzenia o IoC:

scibi92 napisał(a):

IoC to jest forma DI. DI oznacza że przez konstruktor wstrzykujesz zależności np:

Shalom napisał(a):
  1. DI to sposób realizacji IoC -> wstrzykujemy do modułów implementacje, z których one, poprzez jasno zdefiniowany interfejs, korzystają. Ale to nie jest jedyne rozwiązanie, jakiś ServiceLocator czy Factory też może być realizacją IoC.

Pracowałem z frameworkiem IoC w COBOLu. Tam nie ma konstruktorów, setterów ani interfejsów.
Prosta i krótka definicja: IoC inverts the flow control as compared to traditional control flow
Źródło: https://en.wikipedia.org/wiki/Inversion_of_control

Coś takiego można też zrobić w dowolnym innym języku. IoC można np. zauważyć przy odpalaniu skryptów /etc/init.d gdzie o przepływie sterowania decyduje "framework" a nie skrypt znajdujący się w tym katalogu.

Ogólnie DI nie ma w podstawowym znaczeniu związku z IoC.
IoC nie wymaga DI a samo DI (np. przez konstruktor) często jest realizowane bez IoC.
Przykład: https://hackernoon.com/you-dont-need-a-dependency-injection-container-10a5d4a5f878

Dopiero na poziomie kontenera oba te terminy mogą się spotkać, np. w takim Springu - tam kontener wie tak dużo o module że może mu grzebać w bebechach bez wiedzy wybranego obiektu.

Ogólnie bliższe mi jest znaczenie z wiki niż takie odwołujące się w każdym zdaniu (pośrednio lub bezpośrednio) do Springa:

The term is related to, but different from, the dependency inversion principle, which concerns itself with decoupling dependencies between high-level and low-level layers through shared abstractions. The general concept is also related to event-driven programming in that it is often implemented using IoC, so that the custom code is commonly only concerned with the handling of events, whereas the event loop and dispatch of events/messages is handled by the framework or the runtime environment.

0

Definicja @Shalom jest oczywiście poprawna, ja tutaj popełniłem uproszczenie, bo od początku chodziło mi o kontener IOC.

1 użytkowników online, w tym zalogowanych: 0, gości: 1