2009-02-26 14 views

Odpowiedz

9

Czytanie tego znakomitego article od Martina Fowlera.

Zobacz także wikipedia article.

wtrysk zależność jest najbardziej znanym przykładem odwrócenie sterowania, który w krótkim zamienia kod z tego:

public class FileReader { } 
public class Application { 
    // inflexible concrete dependency 
    private FileReader fileReader = new FileReader(); 
} 

Do:

public interface Reader {} 
public class FileReader implements Reader {} 
public class Application { 
    // flexible abstract dependency injected in 
    private Reader reader; 

    public Application(Reader reader) { // constructor injection 
     this.reader = reader; 
    } 
    public void setReader(Reader reader) { // setter injection 
     this.reader = reader; 
    } 
} 
+1

zestaw narzędzi == quickDraw. – duffymo

+0

(wydmuchuje dym z beczki) – toolkit

+0

huh? czy to wewnętrzny żart? –

4

Nie, MKOl nie jest DDD lub TDD .

Martin Fowler's article to dobre intro.

+0

Zgadzam się w 100%, ale IOC jest prawie obowiązkowy dla dobrego TDD. ;-) –

+0

Przepraszam, złe miejsce. Trzeba dodać do innej odpowiedzi. –

+0

Nie, byłem na miejscu, więc dodaję tylko komentarze, które potwierdzają, że jestem dzisiaj totalnym dolcem. –

1

Jeśli masz pytanie dotyczące tego, czym jest IOC, Wikipedia ma numer fairly extensive explanation.

Odnośnie tutoriali lub przykładów this samouczek obejmuje go całkiem dobrze i ma wiele przykładowych kodów.

+0

+1, tylko dla oferty DeMarco. – duffymo

12

IOC, czyli inwersja kontroli, w większości aplikacji odwraca trasę poprzez kod z interfejsu do bazy danych. To nie jest kompletna odpowiedź, ale jest to jeden z najłatwiejszych sposobów, aby zorientować się w koncepcji.

Jeśli chcesz nauczyć się IOC, wejdź do TDD, ponieważ konfigurowanie testów będzie o wiele łatwiejsze po odwróceniu.

Przykład:

Typowy przepływ większości aplikacji .NET widziałem jest coś takiego:

UserCollection col = BusinessLayer.Class.GetLoggedInUsers(); 
//Business logic 
return col; 

następnie firma jest tak:

UserTable table = DataLayer.Class.GetLoggedInUsers(); 
return table; 

itd. To wszystko pseudo kod. Aby użyć IOC w tym przykładzie, dodajesz interfejs dla klasy warstwy danych, np. IUserRepository. Możesz użyć generycznych i polecam pod maską.

Następnie można zrobić coś takiego:

IUserRepository repository = SetUpRepository(); 
UserCollection col = BusinessLayer.Class.GetUsers(repository); 

Dlaczego to jest ważne? Do testowania można utworzyć fałszywe repozytorium i przekazać je do klasy biznesowej. Maniak zawiera dane, które zawsze są takie same, co oznacza, że ​​ćwiczysz swój kod, a nie testujesz od końca do końca.

Jeśli chcesz C#, tutaj jest podstawowy przykład na weblogs.asp.net:

0

Jeśli rozumiesz DIP (Zależność Inwersja zasadzie), MKOl jest ciasto. Proponuję nauczyć się zasad zorientowanych obiektowo, zanim poznasz wzory. Podstawowe zasady mogą być układane w stosy jak legos, aby osiągnąć dowolny wzór.Brandon Joyce

7

Aby mówić o żargonie, inwersja kontroli jest wzorem, który wspiera, między innymi, zasadę jednej odpowiedzialności.

Aby dowiedzieć się, dlaczego to wszystko przydaje się, potrzebujesz eksponatu, więc musisz ze mną.

Jedna odpowiedzialność oznacza w zasadzie, że twoja klasa powinna być tak niezależna od innych części systemu, jak to możliwe, aby zminimalizować wpływ zmiany jednej części na drugą. (Możesz również powiązać to z faktem, że zmiana implementacji nie powinna powodować rekompilacji wszystkich plików w twoich projektach, tak jak w przypadku zmiany plików .h w projekcie C/C++ na przykład). Efektem ubocznym jest to, że kończy się wiele małych obiektów, które wykonują tylko jedną rzecz, ale bardzo dobrze (w idealnym świecie)

Jednak w większości przypadków, aby wykonać swoją pracę, jeden obiekt musi rozmawiać inny obiekt: to zależy od nich.

Pierwsza część łagodzenia polegająca na oddzieleniu implementacji od interfejsów. Oznacza to poleganie na interfejsach (lub czysto abstrakcyjnych klasach, w zależności od wybranego języka), aby jeden obiekt nie był powiązany z konkretną implementacją innego.

więc używać kanoniczny przykład na potrzeby warstwy biznesowej, trzeba przeprowadzić funkcję, która potrzebuje dostępu do - warstwa danych odzyskać obiektom - niektóre inne usługi - rejestrator do dziennika informacje i czy błędy

Z kolei każda usługa lub zależność ma swoje własne zależności, o których klasa powinna wiedzieć, nawet jeśli ich nie używa. W zależności od ilości referencji, ustawienie obiektu może szybko wyjść z rąk. Teraz pomnóż to przez liczbę klas, które musisz napisać, a skończysz z bałaganem rzeczy.

Korzystanie z kontenera IOC zasadniczo pomaga pozbyć się tego bałaganu. Gdy potrzebujesz obiektu, nie "go wymyśl". Zamiast tego możesz poprosić kontener IOC, aby go dla Ciebie odebrał. Kontener jest odpowiedzialny za dostarczenie obiektu funkcjonalnego, gotowego do użycia, niezależnie od jego zależności.

Co oznacza, że ​​klasa nie ma potrzeby bycia świadomym zależności klas, na których polega, co zmniejsza plątaninę. Co więcej, nie trzeba wiedzieć, jaka rzeczywista klasa implementuje usługi, na których się opiera, co oznacza, że ​​ - Implementacja usługi może być zdefiniowana w innym projekcie (dll lub cokolwiek innego), więc modyfikowanie go nigdy nie wpłynie na ciebie klasa - Implementacja może być inny w zależności od kontekstu (należy pomyśleć o zmianie bazy danych lub nawet przejściu do usługi sieciowej w celu pobrania informacji w zależności od konfiguracji lub nawet aktualnego stanu aplikacji).

Aby spróbować odpowiedzieć na inne pytania, IOC jest wzorem. TDD i DDD są metodami projektowania, dlatego nie można zrównać drugiego. Ale IOC jest nieocenionym narzędziem do obsługi TDD lub DDD.

Wiem, że akronimowa zupa i częściowe próbki, które można znaleźć w pobliżu, nie są łatwe do zdziwienia. Najlepszą radą, jaką mogę ci dać, jest wypróbowanie kilku małych projektów na boku, prototypów, które WYLECIE, aby uzyskać dostęp do tych rzeczy. Nie jest to łatwa droga, jeśli szukasz tego do pracy, ale absolutnie tego wart, choćby z osobistego punktu widzenia.

Mam nadzieję, że trochę pomaga.

0

Inwersja kontroli jest abstrakcją struktury logiki. Jednym z podejść (często używanym jako synonim IoC) jest Dependency Injection, który usuwa odniesienia między obiektami. Kiedy obiekty są uwalniane od szczegółów implementacji aplikacji, na przykład, która klasa implementuje jaką usługę, mogą skupić się na swoich podstawowych funkcjach.

Załóżmy na przykład, że masz klasę, która musi mapować obiekty Foo na obiekty Bar. można napisać tak:

public class FooMapper 
{ 
    public Bar Map(Foo foo) 
    { 
     // ... 
    } 
} 

i używać go tak:

public class NeedsToMapFoos 
{ 
    public void MapSomeFoos() 
    { 
     var fooMapper = new FooMapper(); 

     // ... 
    } 
} 

Choć ważne jest to również sztywny. NeedsToMapFoos Obowiązuje tylko to, że mapowanie występuje, a nie że występuje w określony sposób.

Możemy reprezentować pojęcia „implementacji sans pracy” z interfejsem:

public interface IFooMapper 
{ 
    Bar Map(Foo foo); 
} 

i zadeklarować zależność od tej operacji:

public class NeedsToMapFoos 
{ 
    private readonly IFooMapper _fooMapper; 

    public NeedsToMapFoos(IFooMapper fooMapper) 
    { 
     _fooMapper = fooMapper; 
    } 

    public void MapSomeFoos() 
    { 
     // ...use _fooMapper... 
    } 
} 

Teraz NeedsToMapFoos ma mniejszą wiedzę, co oznacza, że jest mniej skomplikowany. Zamiast wykonywać obowiązki administracyjne, można skupić się na analizie biznesowej.

Dobrze zindeksowane obiekty, takie jak ten, są również bardziej elastyczne. Podobnie jak diamenty są sztywne, a glina jest ciągliwa, struktura wewnętrzna determinuje reakcję na zmiany.

Wreszcie, logika napisana w tym stylu jest również elastyczna. Powiedzmy, że FooMapper.Map jest kosztowną operacją i należy ją zbuforować. Można użyć deseniu dekorator zawinąć istniejący wdrażanie i bezproblemowo przekazać go do NeedsToMapFoos:

public class CachingFooMapper : IFooMapper 
{ 
    private readonly IFooMapper _innerMapper; 
    private readonly IDictionary<Foo, Bar> _cache; 

    public CachingFooMapper(IFooMapper innerMapper) 
    { 
     _innerMapper = innerMapper; 
    } 

    public Bar Map(Foo foo) 
    { 
     // Read bar from _cache. If not there, read from inner mapper and add to _cache. 
    } 
} 

// Usage 

new NeedsToMapFoos(new CachingFooMapper(new FooMapper()));