Hallo,
seit einigen Tagen lese ich mich etwas in das Thema "Dependency Injection" bzw. "Inversion of Control" ein.
Ich verwende für meine ersten Schritte Spring4d, so einiges wird mir aber erst nach und nach klar. Einige Fragen, die ich teilweise auch schon selbst beantworte, bringe ich heute Abend in dieses Forum mit. Es wäre schon, wenn ihr dazu ein paar Worte verlieren könntet und mich entweder bestätigt oder aber korrigiert.
Frage 1)
Sollte man konsequent die Verwendung von Field-Injection zugunsten von Constructor-Injection vermeiden?
Meine Antwort dazu:
Die Verwendung von Field bzw. Property-Injection erschwert es den Code zu testen, da man für den Test sonst auf die Hilfe des GlobalContainers angeweisen ist. Außerdem ist diese Art der Injection fehleranfälliger. Man denke nur daran, dass man eine Property per [Inject] markiert, aber es versäumt die entsprechende
Unit einzubinden, in der dieses Attribut definiert ist.
Die Antwort ist also "Ja".
Frage 2)
Was ist die beste Vorgehensweise für DI in Verbindung mit Oberflächen? Sollte meine "TForm" ebenfalls ein bestimmtes Interface implementieren und im Container registriert werden? Eine andere Möglichkeit wäre eine Klasse zu bauen, die mein Formular aggregiert und per direktem Aufruf des Constructors implementiert. Ich habe dazu keine Beispiele oder Informationen gefunden.
Aus dem Bauch heraus würde ich wohl eine Factory dafür nehmen.
Frage 3)
Wie sieht bei einer Anwendung welche DI nutzt der Startup-Code aus (also von den ersten Zeilen in der
DPR bis zur Anzeige des ersten Fensters)? Habt ihr eine bestimmte Klasse, welche sich um die Konfiguration des Containers kümmert und anschließend die MainForm instanziert? Idealerweise hat jene Klasse als einzige eine Zugriff auf den GlobalContainer und füttert alle anderen Klassen?
Als Resultat hätte man ggf. umfangreiche Konstruktoren, da man ja alles von der "obersten Ebene" durchreichen muss. Ein Verstoß gegen dieses Gebot und man ich ruck-zuck dabei eher einen ServiceLocator zu verwenden, statt richtige Dependency Injection durchzuführen.
Um hier nochmal das Szenario aus Frage 2 zurückzugreifen:
Meine Main-Form müsste also z.B. im Konstruktor auch die Instanzen aller Unter-Formulare mitgegeben bekommen bzw. eine Factory mit dessen diese zum geeigneten Zeitpunkt erzeugt werden können? Über den gleichen Mechanismus würde man der Main-Form auch z.B. bestimmte "Behaviours" mitgeben können, also z.B. ein Interface, dass das Verhalten beim Schließen steuert (Soll gefragt werden ob gespeichert werden soll oder nicht usw.) um das separat Testen zu können.
Frage 4)
Zur Erzeugung der Objekte die nur für die Datenhaltung vorgesehen sind, wird eine Factory im Container registriert. Dies wird anscheinend gemacht, da die Erzeugung dieser Objekte durch den Container eher wenig performant ist und eine Factory bereits die nötige Flexibilität mitbringt.
Frage 5)
Mal in die Zukunft geschaut: Könnte man theoretisch mit DI auch eine Art Plugin-System umsetzten? So dass also beispielsweise die Implementierungen auch aus einem
Package oder sogar über
COM kommen könnten und man so das Verhalten der Anwendung nachträglich ohne Neukompilierung beeinflussen kann? Grundsätzlich spricht da nichts gegen oder?
Frage 6)
Ist es korrekt so, dass der Delphi Debugger für Interfaces keine Properties anzeigen kann bzw. nur dann, wenn ich auch explizit den Namen der Property angebe? Nehmt ihr das so hin oder gibt es da einen Trick? Das sehe ich momentan noch als ziemlichen Nachteil an.
Ich hoffe ich konnte mich soweit zumindest für diejenigen, denen das Thema Dependency Injection nicht fremd ist, verständlich äußern und freue mich auch Eure Antworten.
Beste Grüße
Stefan