Was ist eine Umkehrung der Kontrolle und wann sollte ich sie anwenden?

Antworten:

62

IoC (siehe Inversion of Control in Wikipedia) ist in Fällen anwendbar, in denen eine Komponente eine Aufgabe nicht vollständig ausführen kann, weil sie nicht über die erforderlichen Informationen oder Funktionen verfügt.

Das einfachste Beispiel für ein IoC- Muster wären Callback-Funktionen in C. Sie können beispielsweise die Funktion deklarieren:

void Iterator(void *list, Func* f)

Was über das listAnwenden der fFunktion auf jedes Element iteriert . Die IteratorFunktion weiß nicht, wie die einzelnen Elemente verarbeitet werden. Sie geben lediglich eine Funktion als Argument an und verarbeiten sie.

Wie das vorherige Beispiel zeigt, können Sie mit IoC Ihr Programm in separate Komponenten entkoppeln, die nichts voneinander wissen. Eine der häufigsten Versionen von IoC ist Dependecy Injection .

In Dependency Injection muss jede Komponente eine Liste von Abhängigkeiten deklarieren, die zur Ausführung ihrer Aufgabe erforderlich sind. Zur Laufzeit führt eine spezielle Komponente, die als IoC-Container bezeichnet wird, eine Bindung zwischen diesen Komponenten durch. Es wird versucht, Werte für veröffentlichte Komponentenabhängigkeiten bereitzustellen.

Hier ist ein Beispiel in Pseudocode:

class Foo 
{ 
   <Require Boo>Constructor(Boo boo){ boo.DoSomething } 
}

In diesem Beispiel Fooverfügt die Klasse über einen Konstruktor, für den ein Argument vom Typ erforderlich ist Boo, um eine Aktion auszuführen.

Sie können eine Instanz einer Klasse Foomit folgendem Code erstellen :

MyContainer.Create(typeof Foo)

MyContainer- ist ein IoC-Container , der dafür sorgt, dass die Instanz abgerufenBoo und an den FooKonstruktor übergeben wird.

Zusammenfassend lässt sich sagen, dass Sie mit IoC Ihr Programm in separate Teile aufteilen können. Das ist gut, weil:

  • Komponenten können einfach unabhängig voneinander getestet werden.
  • Die Programmkomplexität kann reduziert werden.
  • Sie können Komponenten auf eine andere Implementierung umstellen.

In einigen Fällen jedoch, IoC kann machen Code schwerer zu verstehen.

Wenn Sie ein gutes Beispiel für die Verwendung von IoC in der Praxis sehen möchten, schauen Sie sich Mircosoft Composite UI Application Block und CompositeWPF an

Ich hoffe meine Erklärung hilft dir.

Grüße,
aku


quelle
1
Fünf Jahre später, aber immer noch ... Das war eine hervorragende Beschreibung. Vielen Dank.
Nick Hodges
4
Nicht so viel über IoC erwähnt wird die Tatsache, dass Code schwerer zu lesen ist. Lesbarkeit hat oberste Priorität, wenn Sie hervorragende Software schreiben möchten. Es übertrifft sogar die Testbarkeit. Sie können Code weit über seine Nützlichkeit hinaus entkoppeln.
Arne Evertsson
Ein Code, der für alle Abhängigkeiten eine schnittstellenbasierte Lösung verwendet, basiert also auch auf dem IoC-Design?
nikel
18

Da ich mich vor kurzem selbst damit befasst und alle Lesezeichen aufbewahrt habe, war das Folgende für mich von unschätzbarem Wert, um etwas über IOC / DI zu lernen.

Martin Fowlers Originalartikel über IOC / DI

Einige Konzepte, die Sie zuerst kennen sollten

Eine hervorragende Sammlung von IOC / DI-Tutorials

Buch über IOC / DI von Manning Press

Quelle und Erklärung, wie Sie Ihr eigenes IOC erstellen - Denn das Lesen von Quellcode ist immer der beste Weg, um ein Konzept zu verstehen.

Kris Erickson
quelle
4

Hey JMS, im Grunde genommen können Sie mit IoC / DI definieren, welche Implementierung Sie einmal verwenden, und eine statische Kopie Ihres Containers aufbewahren, damit Sie jedes Mal darauf verweisen können, wenn Sie darauf verweisen möchten.

Die Wikipedia wird Ihnen wahrscheinlich helfen, aber ich wollte auf Ihren zweiten Teil verweisen - ja, Abhängigkeitsinjektion kann für Klassen durchgeführt werden (dh jedes Mal, wenn dieser Klassentyp an eine Methode übergeben werden muss, verwenden Sie diese Klasse), aber es ist besser zu Verwenden Sie Schnittstellen, da Sie auf diese Weise ändern können, welche Version eines Providers, Repositorys usw. Sie verwenden, indem Sie es in Ihrem Setup erneut referenzieren.

Angenommen, Sie hatten eine Schnittstelle zum Einlesen eines Streams und eine XMLStreamReader- und eine SQLStreamReader-Implementierung. Anschließend können Sie den Verweis auf die Schnittstelle an Ihre Methoden übergeben und in Ihrem IoC-Container angeben, welche verwendet werden soll.

Sie können also festlegen, dass öffentliche List ReadPeople (IStreamReader-Reader) und in Ihrem Setup für Ihren IoC-Container jedes Mal, wenn Sie einen IStreamReader erwarten, SQLStreamReader verwenden.

Wenn Sie es sich später anders überlegen, müssen Sie es nur an einer Stelle ändern (dem Setup Ihres Containers), und es spielt keine Rolle, wie viele Methoden nach einem IStreamReader fragen, er erhält immer die Standardeinstellung, die Sie Ihrem Container anvertraut haben auftischen.


quelle
3

Angenommen, Sie haben einen Validator, mit dem Sie überprüfen können, ob ein Unternehmen in Ihrem System gültig ist. Ihr "BusinessValidator" verfügt möglicherweise über ein Feld vom Typ AddressValidator, das den Adressteil des Geschäfts validiert. Wenn Sie den BusinessValidator testen möchten, ohne externen Code (dh den addressValidator-Code) auszuführen, können Sie, wenn Sie eine Art von IoC / DI in Ihrem Framework verwendet haben, einfach einen nachgebildeten addressValidator an seiner Stelle "injizieren" und müssen sich nicht um das Testen kümmern Code außerhalb des Bereichs der zu testenden Klasse.

codeLes
quelle