Eine Sache, die mich bei DI ein wenig stutzig macht, ist die Annahme, dass alle injizierten Objekte billig zu instanziieren y keine Nebenwirkungen haben -Oder- die Abhängigkeit wird so häufig verwendet, dass sie die damit verbundenen Instanziierungskosten überwiegt.
Dies kann vor allem dann von Bedeutung sein, wenn eine Abhängigkeit nicht häufig die innerhalb einer konsumierenden Klasse verwendet werden, wie z. B. eine IExceptionLogHandlerService
. Offensichtlich wird ein Dienst wie dieser innerhalb der Klasse (hoffentlich :)) nur selten aufgerufen - vermutlich nur bei Ausnahmen, die protokolliert werden müssen; dennoch ist die Kanonisches Konstruktor-Injektionsmuster ...
Public Class MyClass
Private ReadOnly mExLogHandlerService As IExceptionLogHandlerService
Public Sub New(exLogHandlerService As IExceptionLogHandlerService)
Me.mExLogHandlerService = exLogHandlerService
End Sub
...
End Class
...erfordert, dass eine "Live"-Instanz dieses Dienstes zur Verfügung gestellt wird, ungeachtet der Kosten/Nebeneffekte, die erforderlich sind, um ihn zu erhalten. Nicht, dass es wahrscheinlich wäre, aber was wäre, wenn die Erstellung dieser Abhängigkeitsinstanz einen Dienst-/Datenbanktreffer oder Nachschlagen in Konfigurationsdateien mit sich brächte oder eine Ressource sperrt, bis sie entsorgt wird? Wenn dieser Dienst stattdessen nach Bedarf, service-located oder factory-generated (die alle ihre eigenen Probleme haben) konstruiert wurde, dann würden Sie die Baukosten nur bei Bedarf übernehmen.
Nun ist es ein allgemein akzeptierter Grundsatz des Software-Designs, dass die Konstruktion eines Objekts est billig und nicht Nebenwirkungen hervorrufen. Das ist zwar ein schöner Gedanke, aber nicht immer der Fall. Die Verwendung von typischer Konstruktor-Injektion setzt jedoch voraus, dass dies der Fall ist. Das heißt, wenn Sie eine Implementierung einer Abhängigkeit erstellen, müssen Sie sie mit DI im Hinterkopf entwerfen. Vielleicht hätten Sie die Objektkonstruktion teurer gemacht, um an anderer Stelle Vorteile zu erzielen, aber wenn diese Implementierung injiziert werden soll, werden Sie wahrscheinlich gezwungen sein, dieses Design zu überdenken.
Bestimmte Techniken können übrigens genau dieses Problem entschärfen, indem sie das "Lazy-Loading" von injizierten Abhängigkeiten ermöglichen, z. B. indem sie einer Klasse eine Lazy<IService>
Instanz als die Abhängigkeit. Dies würde die Konstruktoren Ihrer abhängigen Objekte ändern und dazu führen, dass Sie noch mehr über Implementierungsdetails wie die Kosten für die Objektkonstruktion wissen, was wohl auch nicht wünschenswert ist.