Laden...

Dependency Injection (DI/IoC) nicht pauschal einsetzen, sondern differenziert abwägen

Erstellt von haymo vor 13 Jahren Letzter Beitrag vor 13 Jahren 14.566 Views
Hinweis von herbivore vor 13 Jahren

Abgeteilt von Guter Stil: Properties oder Konstruktor mit vielen Parametern?

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren
Dependency Injection (DI/IoC) nicht pauschal einsetzen, sondern differenziert abwägen

Ich will wirklich niemanden hier persönlich kritisieren, aber ich halte diese offensichtliche Begeisterung für IoC / DI weitestgehend für akademischen Quark. Argumente für DI belegen in Foren meistens solche Allgemeinplätze wie "Abhängigkeiten sind nicht gut" oder "Modularisierung" oder "wenn man mal .. austauschen will" oder so. Einige Vertreter von DI neigen dazu, dieses Muster (meist sehr emotional und engagiert) als die Allgemeinlösung für alle IT Probleme darzustellen. Tatsächlich ist es natürlich nur in bestimmten Fällen überhaupt sinnvoll, DI zu verwenden. Ein gutes "Pro"-Beispiel:

* ein großes Team, welches ein großes Projekt zusammen erstellt. Die Struktur des Codes soll irgendwie vereinheitlicht werden. Aber keiner hat genug Erfahrung um "die beste" Struktur vorzuschlagen oder durchzusetzen. Also kann man z.B. auf die von Spring vorgeschlagene Struktur zurückgreifen. Die ist allemal besser als die KRS (Kraut- und Rüben-Struktur)

* (mehr fällt mir schon nicht mehr ein)

Daher finde ich es toll, dass die Diskussion hier etwas differenzierter geführt wird. Danke! 🙂

Mein Eindruck ist es auch, dass der Hintergrund der Begeisterung die Hoffnung ist, eine möglichst gute Lösung für alle Probleme zu finden. Ist ja auch verständlich. Dennoch kann man sich glaub ich nicht der Anstrengung entziehen, für jedes Problem eine individuelle Lösung zu finden. Zumindest für jedes Neue braucht man auch ne neue Lösung. Das wird einem (ich behaupte 'niemals') von irgendeinem noch so tollen akademischen Prinzip oder gar einem Framework abgenommen werden.

Leider sind auch in diesem Thread die Argumente mehr auf die akademischen Prinzipien konzentriert. Mich würde interessieren, ob schon jemand hier tatsächlich mal eine "große" Applikation gebaut hat und wesentliche Teile / Module oder auch nur eine Klasse irgendwann ausgetauscht wurde - und zwar nur indem die DI-XML Konfig verändert wurde? Kein Rebuild? Kein Redeploy? Und selbst wenn ja: dafür die ganzen Nachteile in Kauf nehmen? Mal ehrlich: Gibt es denn nicht gerade bei "großen" Applikationen weitaus wichtigere Dinge, als die lose Kopplung zu verbessern? Nicht falsch verstehen, ist alles gut und wichtig. Aber in der Praxis wird ein größeres Projekt nicht dadurch ein Erfolg, daß man an irgendwelchen Konzepten blind festhält, sondern durch Erfahrung und vorsichtiges Ausbalancieren verschiedenster Ansprüche - glaube ich. Aber wem sag ich das... 😉

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

U
1.578 Beiträge seit 2009
vor 13 Jahren

Das merke ich auch sehr oft.

Es wird bei den ganzen Pattern etc das eigentliche Ziel aus den Auge verloren.
Patterns sind schön, und auf theoretischer Basis auch nützlich, nur oft erhält man dadurch Funktionalität die man gar nicht benötigt.

Das Problem ist oft, man verrent sich in Details, macht dadurch alles etwas komplizierter und das für ein oft fragwürdigen nutzen.
Das allein sind meiner Meinung nach schon Verletzungen von KISS und YAGNI.

In Universitäten ist das noch okay, die Studenten können diese Einstellungen auch gerne mit in die Firma bringen, aber auch die kommen irgendwann in der Wirtschaft an.

Ich selber sehe das mittlerweile so: Nicht drüber reden wie es am besten gehen könnte sondern es einfach machen wie es am besten passt.
(Schließt Weiterbildung natürlich nicht aus)

Just DO it.

(Ich entwickel auch auf arbeit nach den CCD Prinzipien, diese sind mit Wirtschaftlichkeit vereinbar)

5.941 Beiträge seit 2005
vor 13 Jahren

Hoi haymo

Ich will wirklich niemanden hier persönlich kritisieren, aber ich halte diese offensichtliche Begeisterung für IoC / DI weitestgehend für akademischen Quark. Argumente für DI belegen in Foren meistens solche Allgemeinplätze wie "Abhängigkeiten sind nicht gut" oder "Modularisierung" oder "wenn man mal .. austauschen will" oder so. Einige Vertreter von DI neigen dazu, dieses Muster (meist sehr emotional und engagiert) als die Allgemeinlösung für alle IT Probleme darzustellen. Tatsächlich ist es natürlich nur in bestimmten Fällen überhaupt sinnvoll, DI zu verwenden.

Das finde ich interessant. Eine Allgemeinlösung (für alles) ist es sicher nicht, dafür kann es allgemein angewendet werden.
Inwiefern ist es "Tatsächlich nur in bestimmten Fällen überhaupt sinnvoll, DI zu verwenden"?
Kannst du das bitte mal erläutern?

Zumindest für jedes Neue braucht man auch ne neue Lösung. Das wird einem (ich behaupte 'niemals') von irgendeinem noch so tollen akademischen Prinzip oder gar einem Framework abgenommen werden.

Da gebe ich dir vollkommen Recht. Aber frei nach - do not reinvent the wheel - gibt es auch in neuen Lösungen bestehende Teile, die aus Erfahrung auch genutzt werden könnne.
Abgenommen wird schlussendlich nichts, jedoch würde ich jetzt mal ganz fest behaupten, das eine Anwendung die sich das IoC-Prinzip zu Nutze macht, schlussendlich sauberer und testbarer ist. Und das ohne das du gross etwas machen musst.

Natürlich bringt dir ein DI-Framework nur da etwas, wo du es auch nutzen kannst.
Ist das nicht der Fall, nutzt man es (an dieser Stelle) auch nicht.

Auf DI-Frameworks zu wettern - so verstehe ich das - halte ich für nicht sehr qualifiziert.
Genau so wie du in den meisten Fällen keine Mocks selber schreiben musst, weil es dir ein Mocking-Framwork abnimmt.
Oder ist das auch Mist?

Mich würde interessieren, ob schon jemand hier tatsächlich mal eine "große" Applikation gebaut hat und wesentliche Teile / Module oder auch nur eine Klasse irgendwann ausgetauscht wurde - und zwar nur indem die DI-XML Konfig verändert wurde? Kein Rebuild? Kein Redeploy? Und selbst wenn ja: dafür die ganzen Nachteile in Kauf nehmen? Mal ehrlich: Gibt es denn nicht gerade bei "großen" Applikationen weitaus wichtigere Dinge, als die lose Kopplung zu verbessern? Nicht falsch verstehen, ist alles gut und wichtig. Aber in der Praxis wird ein größeres Projekt nicht dadurch ein Erfolg, daß man an irgendwelchen Konzepten blind festhält, sondern durch Erfahrung und vorsichtiges Ausbalancieren verschiedenster Ansprüche - glaube ich. Aber wem sag ich das... 😉

Ja, da kann ich mich melden.
Früh angefangen - jedoch mit IoC im Kopf - so konnte die Anwendung relativ einfach auf ein DI-Framwork umgestellt werden.
Die komplette Konfiguration läuft per Xml. Wenn die Anwendung beim Kunden läuft, reicht es die Xml-Datei zu ändern und eine neue DLL (Plugin) rein zu kopieren.

Nachteile?
Was ist denn wichtiger, mal blöde gefragt?

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo haymo,

Einige Vertreter von DI neigen dazu, dieses Muster (meist sehr emotional und engagiert) als die Allgemeinlösung für alle IT Probleme darzustellen.

leider klingt auch dein Beitrag genauso "sehr emotional und engagiert" (=eifernd). So wie dein Beitrag aufgezogen und formuliert ist, machst du es leider nicht besser, als die Leute, die du kritisierst. Ich bin aber zuversichtlich, dass die weitere Diskussion trotzdem entspannt und sachlich verläuft. myCSharp.de ist bekannt dafür.

herbivore

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren

Hi Peter,

Inwiefern ist es "Tatsächlich nur in bestimmten Fällen überhaupt sinnvoll, DI zu verwenden"?
Kannst du das bitte mal erläutern?

na eben nur die, wo es tatsächlich einen Nutzen hat. Man kann natürlich DI auch nutzen, um z.B. einen Plugin-Mechanismus zu entwickeln. Funktioniert bestimmt. Ich weiß nur nicht, ob es auch der beste Weg ist. Tatsächlich fällt es mir viel leichter, eine negative Abgrenzung zu machen und alle Fälle aufzuzählen, wo die Nachteile überwiegen. Das liegt wahrscheinlich daran, dass ich kein großer Fan vom übermässigen Gebrauch von DI bin (hast Du bestimmt schon gemerkt 😉) Aber wo es wirklich sinnvoll ist - also konkrete Beispiele, die kannst Du bestimmt besser aufzählen? Ich find immer nur sowas wie "... um lose Kopplung zu machen".

Abgenommen wird schlussendlich nichts, jedoch würde ich jetzt mal ganz fest behaupten, das eine Anwendung die sich das IoC-Prinzip zu Nutze macht, schlussendlich sauberer und testbarer ist. Und das ohne das du gross etwas machen musst.

Aber die Tests schreiben muß man doch sowieso? Ich würde Deinen Vorteil eher so formulieren: Modulare Anwendungen sind leichter zu testen. Und ein Weg, dahin zu kommen, kann DI sein. Ist aber wieder nicht der einzige. Ein "gutes" Design führt IMO genauso dahin. Und die "traditionellen" Möglichkeiten (laß es einfach eine Factory sein) reichen in allen Fällen, die ich gerade überblicken kann, völlig aus.

Ja, da kann ich mich melden.
Früh angefangen - jedoch mit IoC im Kopf - so konnte die Anwendung relativ einfach auf ein DI-Framwork umgestellt werden.
Die komplette Konfiguration läuft per Xml. Wenn die Anwendung beim Kunden läuft, reicht es die Xml-Datei zu ändern und eine neue DLL (Plugin) rein zu kopieren.

Ja, klingt wie ein Plugin-Mechanismus. Klappt bestimmt auch. Aber könnte man doch auch anders machen -ohne DI, ohne Nachteile, oder? Ich meinte auch eher sowas wie: Eine Applikation wurde ausgeliefert und läuft erstmal. Nach einiger Zeit gibt es ein Update mit 24 neuen Funktionalitäten, 102 alte wurden auch geändert. Die werden nachimplementiert und nun geht man ans Produktivsystem, ändert die DI-Konfiguration und kopiert neue DLLs ins bin-Verzeichnis? Soll es so aussehen?
Klassischerweise würde die Anwendung komplett oder teilweise neu deployed werden und gut ist. Darum käme man wohl auch mit DI nicht herum? Nur wo ist jetzt der Vorteil von DI-Konfigs?

Nachteile?

Hier einige der (weniger akademischen) Nachteile. Die akademischen wurden ja schon oft genug genannt:
* man bekommt ein Prinzip mit Regeln aufgedrückt, die teilw. von mindestens genauso sinnvollen Regel der OOP abweichen lassen (Bsp Parameter Injection: Plötzlich sind Objekte nicht mehr IMMER konsistent, sondern erst, wenn alle Parameter gesetzt wurden. Ist nat. ok, solange es kein [zukünftiger] Programmierer im Team vergisst...)
* man gibt so angenehme Features wie Refactoring und "Go to Definition" auf.
* Debugging wird komplizierter (weil kein Usercode)
* ich mag C# Code schreiben mehr als XML schreiben (kenne die C# Alternative, gefällt mir aber aus versch. Gründen auch nicht wirklich)
* Fehler erst zur Laufzeit
* Mehraufwand beim Projektsetup,
* zusätzliche Abhängigkeiten an den IoC Container
* Interface-iritis: man hat plötzlich überall Interfaces, für die es im Prinzip nur eine einzige Ausprägung gibt. (Wahrscheinlich auch für den Fall, dass es evtl. mal usw...?)

Was ist denn wichtiger, mal blöde gefragt?

* Im zeitlichen Rahmen zu bleiben, Dokumentation nicht zu vergessen, built-skripte (die sind eh das A und O! 😉, sich nicht mit akademischen Details aufzuhalten und so weit wie möglich zu reduzieren - weniger! Übersichtlichkeit für nachfolgende Programmierer zu erhalten, das richtige Maß an Generalisierung zu finden und sich im Klaren sein, dass die Anwendung (zumindest in der Form) in 10 Jahren wohl nicht mehr online sein wird...

@Herbivore: danke für den Split. Eigentlich hätte das Thema wohl besser hier rein gepasst: Dependency Injection: Vor- und Nachteile

Ja, entspannt find ich auch gut! Bin ich da falsch rübergekommen? Ist aber auch schwer, bei einem solch "emotionalen" Thema die Sache an sich anders zu sehen, ohne jemanden dabei auf die Füsse zu treten, oder? Aber ich denke, bis jetzt klappts doch ganz gut, [@alle] oder?

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

R
115 Beiträge seit 2006
vor 13 Jahren

Also ich weiß nicht wo Dependency Injection ein "emotionales" Thema ist und das Thema ist auch absolut null akademischer sowie weder Raketenwissenschaft, noch Hexenwerk. Die ersten Schritte sind sogar heute absolut einfach gemacht.

Wenn man eine testbare Anwendung haben möchte, dann benötigt man Komponenten und diese muss man lose Koppeln. Über Dependency Injection lässt sich das ganze einfach machen. Auch ohne XML etc. lässt sich das leicht machen. Auf meinem Blogpost hab ich ein sehr simples Beispiel mit ASP.NET MVC & Windsor Castle.

Ohne Dependency Injection kann man sowas einfach nicht gescheit testen.

Nachteil:
Das Debugging kann komplizierter werden und es ist nicht so eindeutig, woher jetzt überhaupt das Objekt kommt. Da muss man sich auf das Framework verlassen und die Konfiguration muss stimmen.

Vorteil:
Lose Kopplung und nur dadurch bekommt man eine testbare Anwendung. Es geht nicht um "Austauschbarkeit" (im Sinne von "Ich tausch mein MySQL Repository durch Oracle aus oder einem Plugin-System (was bestimmt auch geht)), mir geht es in erster Linie darum, dass es testbar bleibt.

Wenn man keine testbare Anwendung haben möchte, dann spart man sich (für die Einarbeitung) vielleicht ein, zwei Tage, hinterher kann es aber zu Problemen führen. Wenn ich das einmal meinen Azubis erkläre und den erkläre wozu das ganze gut ist, dann verstehen die das auch.

Bei größeren Anwendungen kann auch die Konfiguration komplexer werden, aber umso wichtiger wird es dann, dass die Anwendung testbar bleibt.

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren

Danke Reman, könntest Du noch anders erklären, wieso man eine Anwendung ohne DI nicht testen kann? Vielleicht verstehe ich Dich falsch? Denn Testbarkeit finde ich auch ein wichtiges Kriterium. Aber das hängt doch eher davon ab, ob die Anwendung gut und sinnvoll in einzelne Module aufgeteilt ist. Und das kann man ja auch ohne DI hinbekommen?

Vielen Dank

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

U
1.578 Beiträge seit 2009
vor 13 Jahren

Also ich entwickel ohne DI und bekomme auch ein 100% Code Coverage problemlos hin.

Was ich sagen will, eine gute Architektur ist immer wichtig, da werden mir alle zustimmen, nur zwanghaft immer ein Muster zu folgen (wie ich das damals mit MVVM tat) bringt absolut keinen mehr wert.

Eine Architektur kann auch ohne DI, ohne MVVM oder sonst etwas gut und wartbar sein.

Ein Pattern sollte nur angewandt werden wenn es auch der Lösung dient und angemessen erscheint.
Wichtig ist auch die Reflektion, ist das benutzte Pattern wirklich sinnvoll? Benutzt man es auch korrekt? Wäre ein anderes Pattern oder gar keins angemessener? Wenn man die Architektur gut plant, dann ist alles möglich, sei es mit oder ohne Pattern.

Was ich noch anmerken möchte, das Ziel ist eine gute Applikation auf Basis guten (clean) Code, nicht das man ein Pattern korrekt anwendet.
So ging es mir mit MVVM, ich wollte immer korrektes MVVM an wenden, ich dachte immer "Wie löse ich das Problem auf den MVVM weg", und verlor das Ziel aus dem Auge: "Wie löse ich das Problem angemessen und sauber"

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren

Gut zu lesen! Ich sehe die Priorisierung ganz genauso. Auch denke ich, dass es mit steigender Komplexität einer Anwendung eben auch immer unmöglicher wird, irgendein bestimmtes Muster perfekt umzusetzen. Da muß man selbst bei MVC Abstriche machen und darf - wie Du sagst - nicht das Ziel aus dem Auge verlieren. Denken läßt sich ja auch weder abstrahieren noch generalisieren. Und was bei "Hello World" gilt, muß nicht immer auch im Großen funktionieren.

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo haymo,

könntest Du noch anders erklären, wieso man eine Anwendung ohne DI nicht testen kann?

natürlich kann man eine Anwendung auch ohne DI testen.

DI ermöglicht aber, dass man die einzelnen Units vollkommen unabhängig voneinander testen kann, und zwar auch dann, wenn eine Unit andere Units benutzt. Diese anderen Units kann man mit DI dann problemlos durch Mocks ersetzen.

herbivore

1.373 Beiträge seit 2004
vor 13 Jahren

Hallo,

Offensichtlich herrscht bei einigen der Eindruck DI bedeutet, dass man hunderte von Interfaces erstellen muss und ellenlange XML-Konfigurationen hat.

Zunächst einmal bedeutet Dependency Injection im weiteren Sinne, dass man seine Komponenten so entwirft, dass ihnen ihre Abhängigkeiten extern übermittelt werden, anstatt sie die Abhängigkeiten selbst suchen oder erstellen zu lassen. Das ist erst einmal ziemlich trivial, erhöht aber bereits die Qualität der Software deutlich. Ein einfaches Beispiel:


UnitOfWork uow = GetUnitOfWork();
// c'tor-injection
UserRepository repos = new UserRepository(uow);
User user = CreateNewUser();
repos.AddUser(user);

Das UserRepository benötigt eine UnitOfWork, diese wird ihr explizit mitgeteilt. Das erhöht bereits die Testbarkeit und die Verständlichkeit der Tests.


[Test]
public void when_adding_user_should_register_at_unit_of_work(){
  UnitOfWork uow = new UnitOfWork();
  UserRepository repos = new UserRepository(uow);
  User user = new User("VizOne");
  repos.AddUser(user);
  Assert.That(uow.Contains(user));
}

Die leider noch häufig verwendete Alternative: die UnitOfWork wird aus irgendeinem globalen, statischen Kontext innerhalb des UserRepository herbeigezaubert. Die Tests sind mMn dann schlechter Verständlich:


[Test]
public void when_adding_user_should_register_at_unit_of_work(){
  UserRepository repos = new UserRepository();
  User user = new User("VizOne");
  repos.AddUser(user);
  // UserRepository internally uses UnitOfWork.Current
  Assert.That(UnitOfWork.Current.Contains(user));
}

Bis hierhin war noch kein IoC-Container im Einsatz, keine Konfiguration und keine Interfaces.

Ein IoC-Container beantwortet Fragen, die im Zusammenhang mit den Abhängigkeiten auftreten: woher bekomme ich denn jetzt die benötigten Abhängigkeiten? Wer ist der Eigentümer? Wann können sie zerstört werden? Zudem hilft er, die Konfiguration und Erstellung von Objekten aus dem eigentlich Businesscode zu halten (Separation of Concerns).

Wie ich z.B. gestern hier schrieb, kann ein IoC-Container wunderbar einfach alle benötigten Dienste usw. für einen einzelnen Request zusammenstellen, ohne dass man irgend etwas vom IoC-Container mitbekommt. Wenn ich einen neuen Dienst habe, registriere ich ihn zentral bei meinem IoC-Container, und wer ihn nötig hat, gibt ihn schlicht als Abhängigkeit an, alles weitere macht der Container. Dieses Konzept macht schon bei sehr kleinen Anwendungen Sinn und wächst mit den Anforderungen der Anwendung mit.

Zum Thema XML-Konfiguration für den IoC Container: ich konfiguriere ausschließlich diejenigen Komponenten per XML, die auch tatsächlich je nach Deployment ausgetauscht werden können und müssen, und das sind meist sehr(!) wenige. Der größte Teil der Komponenten wird im Code registriert. Für die meisten serverseitigen Anwendungen ist ein binäres Deployment der Konfigurations-DLL übrigens nicht schwerer als die Änderung einer XML Datei. Zudem ist die Registrierung im Code weniger Fehleranfällig.

Das Abstrahieren von konkreten Typen zu Interfaces ist aus verschiedenen Gründen sinnvoll, allen voran die Austauschbarkeit von Implementierung (und sei es nur für Mocks in Unit Tests) sowie die Minimierung der öffentlichen Schnittstelle (Interface Segregation Principle). Diese Vorteile existieren unabhängig von DI und IoC-Containern, daher sollte diese Abstraktion für geeignete(!) Kandidaten sowieso in Erwägung gezogen werden. Mit den zur Verfügung stehenden Refaktorisierungstools und/oder etwas Weitsicht ist das auch kein großer Akt.

Durch die Verwendung von Interfaces (oder virtueller Methoden) als Services können viele IoC-Container übrigens auch einfache AOP-Ansätze anbieten, indem sie diese Interfaces so zur Laufzeit implementieren, dass zunächst ein Interceptor aufgerufen wird (in AOP-Lingo: ein Advice), der dann spezielle Aufgaben erfüllt (etwa Transaktionsverwaltung). Damit können noch mehr Concerns ausgelagert werden. Das ganze geschieht für den Nutzer transparent und - abgesehen von der Konfiguration - ohne Mehraufwand.

Ich setze seit langer Zeit DI und IoC-Container erfolgreich in der Praxis ein und konnte damit die Komplexität der Anwendungen reduzieren während gleichzeitig Testbarkeit und Konfigurierbarkeit gestiegen sind. Woher die Idee kommt, DI/IoC seien Konzepte mit ausschließlich akademischer Bedeutung, ist für mich nicht nachzuvollziehen. Wenn man DI und den Umgang mit dem IoC-Container seiner Wahl verstanden hat, kann man diese Konzepte schnell und Gewinn bringend in der Praxis anwenden, auch bei kleineren Projekten.

Natürlich löst DI/IoC nicht alle Probleme. Eine Ausnahmeerscheinung sind Anwendungen, die davon stark profitieren, allerdings bei weitem nicht, auch wenn uns das der Themenstarter glauben machen will. Allerdings stimme ich zu, dass die Empfehlung DI einzusetzen, im ursprünglichen Thread (Guter Stil: Properties oder Konstruktor mit vielen Parametern?) nicht dazu beiträgt, dass eigentliche Problem zu lösen (die vielen Parameter).

Grüße,
Andre

S
489 Beiträge seit 2007
vor 13 Jahren

Also ich entwickel ohne DI und bekomme auch ein 100% Code Coverage problemlos hin.

100% Code Coverage bekommt man immer hin auch ohne DI. Was sagt denn die Code Coverage aus?? Doch nur, dass der Code mindestens einmal durchlaufen wurde. Das bedeutet dann noch lange nicht dass auch richtig getestet wurde.

U
1.578 Beiträge seit 2009
vor 13 Jahren

Und? Kennst du meine Tests? Urteile über nichts was du nicht kennst.

Patterns sollte nur angewendet werden wenn sie auch Sinnvoll und angemessen sind.

1.373 Beiträge seit 2004
vor 13 Jahren

Patterns sollte nur angewendet werden wenn sie auch Sinnvoll und angemessen sind.

Richtig, aber hat wer das Gegenteil behauptet? Manche Antworten lesen sich, als wäre jeder DI-Nutzer ein verblendeter Nachläufer.

Ich lese hier oft: "man kann dies und das auch ohne DI machen". Mag sein, viele Alternativen sehen meiner Erfahrung nach in der Praxis dann (nach einigen Iterationen) aus wie ein halbherziger, überspezialisierter Nachbau eines DI Frameworks.

Um noch einmal auf den ersten Post zurückzukommen:

Mich würde interessieren, ob schon jemand hier tatsächlich mal eine "große" Applikation gebaut hat...

Jap, hier.

... und wesentliche Teile / Module oder auch nur eine Klasse irgendwann ausgetauscht wurde - und zwar nur indem die DI-XML Konfig verändert wurde? Kein Rebuild? Kein Redeploy?

Nein, das fand nicht statt. Denn das ist auch nur ein Feature eines IoC-Containers, und bei weitem nicht der wichtigste.

Mal ehrlich: Gibt es denn nicht gerade bei "großen" Applikationen weitaus wichtigere Dinge, als die lose Kopplung zu verbessern?

Gerade "große" Anwendungen haben häufig eine sehr komplexe Konfiguration und sehr viele Komponenten, die (auch) unabhängig und klar abgegrenzt getestet werden müssen. Beides wird durch ein DI und IoC unterstützt.

U
1.578 Beiträge seit 2009
vor 13 Jahren

Patterns sollte nur angewendet werden wenn sie auch Sinnvoll und angemessen sind.

Richtig, aber hat wer das Gegenteil behauptet?

Deine Antworten klingen so als meintest du das das DI pattern das non plus ultra wäre und ohne dem nix ginge 😉

Gerade "große" Anwendungen haben häufig eine sehr komplexe Konfiguration und sehr viele Komponenten, die (auch) unabhängig und klar abgegrenzt getestet werden müssen. Beides wird durch ein DI und IoC unterstützt.

Richtig, aber man kann das auch ohne DI und IoC hin bekommen.
Und es ist dann nicht gleich ein "halbherziger nachbau" wie du es bezeichnest.

Ich behaupte auch nicht das man das DI nicht gebrauchen kann, oder das es nicht unterstützt, aber man muss einfach die Architektur vernünftig planen, wenn dabei ein DI nützlich ist, fein, dann benutzt man es, wenn nicht, dann nimmt man es auch nicht.
Ich verstehe nicht wie ein Pattern so "emotional" betont wird, es ist doch nur ein Muster.

Man fängt nicht an "So, wie zieh ich das Projekt nun mit DI auf".

(Und Ja, ich entwickel auch Große Applikationen mit einigen Jahren Lebenszeit.)

1.373 Beiträge seit 2004
vor 13 Jahren

Ich glaube, im Grunde sind wir uns alle einig: die Anwendbarkeit von Mustern muss zunächst von Fall zu Fall geprüft werden. Im Zweifel spielt dann ggf. persönliche Präferenz und Erfahrung das Zünglein an der Waage.

Grundsätzlich ist es schon wirklich so, dass häufig Techniken und Patterns angewendet werden, ohne zu hinterfragen, ob sie in der jeweiligen Situation angemessen sind. Das Paradebeispiel ist hier wohl der Einsatz relationaler Datenbanken. Wenn eine Anwendung etwas persistieren soll, das irgendwie in Tabellenform gequetscht werden kann, dann wird sofort ein RDBMS herangezogen, ohne weiter nachzudenken. Nicht ohne Grund versucht die NOSQL Bewegung hier gegenzulenken.

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren

Da stimme ich gerne auch zu:) Vielen Dank auch an Reman fuer Deinen interessanten und differenzierten Bericht!
Gerade diese Differenziertheit vermisse ich oft im Zusammenhang mit DI. In einigen (vielen) Berichten wird dieses Konzept allzuoft als "Quasi-Standard" dargestellt. Als fuehre daran kein Weg vorbei und man muesse dies unbedingt einsetzen - weil es "neu" oder "modern" oder so sei... Das ist natuerlich Quatsch und so bin ich froh, dass wir hier einen besseren thread haben, der auch mal in Google auftaucht... 😃

Edit: Nichts gegen Remans Beitrag, aber eigentlich wollte ich mich bei VizOne bedanken... Hab ich aus Versehen vertauscht.

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

0
767 Beiträge seit 2005
vor 13 Jahren

2 Sachen:

1.
ja, auch bei unserem Projekt ist DI eingesetzt und verwenden bei unterschiedlichen Kunden per unterschiedliche Implementierungen eines Interfaces, ohne irgendwas neu zu kompilieren, einfach per Xml Konfiguration. Es muss also nicht unbedingt sein, dass man bei einem Kunden "irgendwann mal was austauschen will". Kann auch gleichzeitig unterschiedlich in Verwendung sein.

2.
ja, auch bei uns ist es zum Großteil eher der Testbarkeit der einzelnen Units wegen so geschrieben. KISS und YAGNI sehe ich dabei nicht verletzt, weil ichs ja für die Tests bereits jetzt durchaus brauche (-> YAGNI) und andererseits gerade dadurch die Tests so simpel wie möglich (KISS) bleiben.

loop:
btst #6,$bfe001
bne.s loop
rts

F
10.010 Beiträge seit 2004
vor 13 Jahren

@haymo :
Da hast Du solltest den ersten Post von VizOne nochmal genau durchsehen.

DI ist der Standard in professioneller Programmierung, nur der Weg dahin muss nicht über einen Container gehen.
Und wenn dir die XML Sachen nicht gefallen, es gibt keinen einzigen Container, den man nicht auch per Code "befüllen" kann.

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren

DI ist der Standard in professioneller Programmierung

hm. Na jetzt freue ich mich aber auf eine Referenz,FZelle ... 😄

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

U
1.578 Beiträge seit 2009
vor 13 Jahren

Ich finde auch nicht das DI ein Standard ist, wie es zb 0815Coder aufführt kann es sehr hilfreich sein wenn man den Benefit davon benötigt, nur das kommt nicht so oft vor wie manche es evtl glauben.

0
767 Beiträge seit 2005
vor 13 Jahren

Ich finde einfach nicht, dass es zusätzliche Arbeit verursacht (eher spart es Zeit). Deshalb seh ich auch nicht, warum ich es nicht verwenden sollte. Bei mir ist es Standard.

loop:
btst #6,$bfe001
bne.s loop
rts

742 Beiträge seit 2005
vor 13 Jahren

Ich schlage mich auch auf FZelle's Seite. Professionelle Softwareentwicklung -> Unit Tests & Modularisierung -> DI

Ich sehe auch null Mehraufwand durch DI, also nutze ich es eigentlich immer. Abhängigkeiten kommen immer vor und Singletons zu schreiben kosten ja auch Zeit. Ich denke man unterschätzt die Arbeit, die einem von einem DI-Container abgenommen wird.

U
1.578 Beiträge seit 2009
vor 13 Jahren

Bei mir ist es Standard.

Genau, bei dir, du definierst den Standard? 😉

@malignate
Mag sein, aber Unit Tests & Modularisierung bekommt man auch so hin....

aaaaber, ich unterscheide da zwischen Dependency Injection und einen einfachen Service Provider.

Aber auch diesen sehe ich nicht als Standard an.

F
10.010 Beiträge seit 2004
vor 13 Jahren

ich unterscheide da zwischen Dependency Injection und einen einfachen Service Provider.

Und da liegt dein Problem, du hast nicht verstanden worüber geredet wird.

DI bedeutet das ein Objekt seine Abhängigkeiten übergeben bekommt, und nicht alles selber fest verdrahtet.
Das hat erstmal überhaupt nichts mit einem Container oder einem Serviceprovider zu tun.
Es ist einfach eine saubere Trennung der Abhängigkeiten, nicht mehr und nicht weniger.
Wenn Du das nicht betreibst ist das Ergebnis sehr schlecht wartbar.

742 Beiträge seit 2005
vor 13 Jahren

Ich denke hier DI mit einem DI-Container gleichzusetzen ist durchaus legitim. Ich kenne eigentlich niemand der konsequent DI ohne einen Container betreibt.

1.373 Beiträge seit 2004
vor 13 Jahren

Das Problem ist tatsächlich, dass verschiedene Konzepte in einen Topf geworfen werden.

Um es also mal auf einen Nenner zu bringen:

Inversion Of Control bedeutet ganz allgemein, dass der Kontrollfluss in der Beziehung zweier oder mehrerer Objekte umgedreht wird. Wikipedia gibt einige gute Beispiele, z.B. das Observer Pattern: beim Observer-Pattern bestimmt nicht das observierte Objekt, welche anderen Objekte über Änderungen informiert werden. Stattdessen melden sich die Observer beim observierten Objekt an und werden dann vom observierten Objekt informiert. Da events sehr änlich arbeiten sind sie ebenfalls bereits ein Mittel der Kontrollflussumkehr.

Dependency Injection ist eine Art von IoC: statt einem Objekt zu gestatten seine Abhängigkeiten selbständig zu suchen werden ihm die Abhängigkeiten von außen mitgeteilt. Das hat NICHTS mit einem Container zu tun:


public class TwitterAccount{
  string userName;
  string password;
  ITwitterApi api;

  public TwitterAccount(ITwitterApi api){
    this.api = api;
  }
 ...
  public void SendTweet(string message){    
    api.SendTweet(userName, password, message);
  }
}

Hier wird die Abhängigkeit (eine ITwitterApi) an den Konstruktor übergeben -> Dependency Injection!

IoC bzw DI Container sind lediglich "schlaue" Fabriken, die Objekte erstellen und dabei gleichzeitig die Abhängigkeiten der erstellten Objekte erkennen, auflösen und injizieren können.

Ob DI und DI Container "Standard" sind, kann ich nicht beurteilen. Die Java-Welt ist tendenziell weiter, was die Verwendung von Patterns angeht, vermutlich ist es hier nicht anders. Das Problem ist natürlich, dass viele Firmen Brownfield-Anwendungen warten müssen, da schmeißt man nicht unbedingt das komplette Design um (zumindest nicht ohne eine solide Basis an automatisierten Tests). Wenn ich so in diversen Maillistings lese, habe ich aber subjektiv den Eindruck, dass sich im Bereich Testbarkeit, Unittests, DI, automatisierte Builds usw. deutlich etwas tut.

Aber letztendlich ist es fast egal, ob es "Standard" ist. Die Vorzüge von DI sind offensichtlich, wer etwas anderes behauptet, hat das Problem und die Lösung nicht verstanden. Ihnen sei das hier zur Lektüre gereicht.

DI Container wiederum nehmen sehr viel Arbeit ab, die man so oder so erledigen muss, und führen zu mMn einfacherem, wartbarerem Code, da man die Objekterstellung fast vollständig ausblenden kann. Man muss sie nicht einsetzen. Ich habe allerdings noch kein Projekt erlebt, bei dem der Einsatz eines DI Containers mehr geschadet als genutzt hat. Es ist ja auch nicht so, dass der Einsatz eines solchen Containers andere Entscheidungen beschneiden würde.

Alles andere, XML Konfiguration, austauschbare Implementierungen, usw. sind nette Dreingaben, die man nutzen kann, aber nicht muss. Und wie gesagt kann man problemlos konkrete Klassen über einen DI Container erstellen lassen, man wird nicht zur Interface-itis gezwungen (wobei man natürlich je nach Situation schon die gebührende Abstraktion verwenden soll, um das System offen zu halten (Open-Closed-Principle) - aber das lässt sich auch noch später hinein-refaktorisieren).

Grüße,
Andre

0
767 Beiträge seit 2005
vor 13 Jahren

Bei mir ist es Standard.
Genau, bei dir, du definierst den Standard? 😉

Ich definiere wie ich standardmässig Applications entwickle - ist doch mein gutes Recht 😃 Wenn wer anderer das gern anders tut, ist das seine Sache.

Natürlich sollte man immer abwägen ob eine Technik Sinn macht oder nicht. Auch DI wird nicht immer sinnvoll sein, mMn aber meistens schon.

loop:
btst #6,$bfe001
bne.s loop
rts

H
haymo Themenstarter:in
91 Beiträge seit 2007
vor 13 Jahren

Eigentlich finde ich ja auch, dass mit dem letzten Beitrag von 0815Coder und mit der Bennennung des Themas von herbivore das Wichtigste gesagt wurde. Ersteres erscheint mir allerdings wenig konstruktiv und ein gutes Beispiel für die verallgemeinernde Pauschalisierung die mich im Zusammenhang mit diesem Thema halt stört. Es klingt wie: "Meistens ist es sinnvoll, mit dem Auto einkaufen zu fahren." Aber wer das so sehen will, soll es halt tun.

Den Begriff DI so weit zu dehnen, dass er im Prinzip auf JEDE Software zutrifft- also bereits die Nutzung eines normalen parametrisierten Konstruktors als DI deklariert wird, halte ich nicht für sinnvoll. Der Begriff DI hat sich IMO etabliert im Zusammenhang mit DI Containern - namentlich wahrscheinlich mit Spring. (Dieses FW als dominant zu sehen, lässt sich zumindest durch die Resonanz in der Fachpresse rechtfertigen.) Die Anforderungen der Modularisierung/Trennung in Komponenten (u.a.- aber nicht NUR für Testbarkeit) waren schon in der Informatik etabliert, bevor es die professionelle SW-Entwicklung plötzlich nur noch mit DI-Containern geben zu dürfen schien. Und jetzt wird es oft so dargestellt, dass diese Technik unumgänglich ist und jeder, der ein Projekt nicht damit startet, unprofessionell arbeitet. Wie gesagt, ich finde es besser, Spring etc. zu nutzen, als GAR keine Struktur zu haben. Gerade wenn man noch nicht sehr viel Erfahrung hat.

Gerade da liegt aber die Gefahr. In der kleinen SW Butze kommt irgendwann der Chef und sagt: "hey, wieso nutzen wir eigentlich kein DiEi-Kontainer? Ich hab das hier gelesen und .... ". Oder: Ein neuer Teamleiter übernimmt ein grösseres Projekt und hat "schon mal was mit DI gemacht und das macht man doch heute so!". Bei diesen pauschalen Entscheidungen kann (und ich bin sicher: wird auch) durchaus ne Menge schief gehen. Zumal einem DI eben nicht die Erfahrung abnimmt, da es auch nicht IMMER nach dem reinen Plan funktioniert. Von daher finde ich es wichtig, dass über diese Technik auch (mal) differenziert berichtet wird, und das Feld im Internet nicht hauptsächlich den Machern der verschiedenen DI-Container und deren Fans überlassen wird.

==============================
heute schon numerics gehabt? Dann nichts wie
hin zu : ILNumerics.Net - numerics for .NET

0
767 Beiträge seit 2005
vor 13 Jahren

Also welchen DI Container man verwendet ist unabhängig vom DI selber. Der Wechsel auf einen anderen DI Container (zB von Spring auf Autofac) sollte minimaler Aufwand sein: das hoffentlich einzige was betroffen ist, ist die Configuration und die erst-instanzierung (wahrscheinlich ein Servicelocator, oder auch eine Integrations dll für ASP oder WCF (zB autofac).

Das ganze DI, IoC, SL Thema wurde bei uns auch eingeführt als kaum wer Ahnung davon hatte, und es wurde zudem von demjenigen nicht gut erklärt. Trotzdem sind die Applications die wir direkt damit angefangen haben um Faktoren besser wartbar, obwohl das ganze eher suboptimal eingesetzt wird.

Mehr Aufwand wars dennoch nicht.

Aus dem ergibt sich für mich: Besser schlecht einsetzen, als gar nicht.

loop:
btst #6,$bfe001
bne.s loop
rts