Dependency Injection in BlitzMax [fab.injection]

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

 

FWeinb

ehemals "ich"

Betreff: Dependency Injection in BlitzMax [fab.injection]

BeitragSo, Jul 21, 2013 19:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe mal wieder BlitzMax rausgekramt um mich mit dem Konzept von Dependency Injection vertraut zu machen. Ich wollte ein eigenes kleines Framework wie Guice erstellen. Und da BlitzMax mit einem rudimentären Reflection und Annotation System ausgestattet ist habe ich mich mal dran gemacht und es umgesetzt.

Ich fange wohl am besten mit einem kleinen Beispiel an:
BlitzMax: [AUSKLAPPEN]
' Create a TInjector
Local injector:TInjector = TInjector.Create();
' Request a TFoo instance;
Local foo:TFoo = TFoo(injector.get("TFoo"));

Print foo.bar.name; '"Hello World"

Type TBar {Injectable}
Field name:String = "Hello World"
End Type

Type TFoo {Injectable} ' Make Injectable
Field bar:TBar {Inject} ' Inject TBar to Field
End Type



Das dürfte für die meisten BlitzMax Nutzer sehr komisch aussehe, doch ist valider BlitzMax code. Dinge die in gescheiften klammern geschrieben werden (wie {Injectable} oder {Inject}) sind sog. Metadaten, in Java nennt man sie Annotations.

Diese Annotations sind nützlich, denn mithilfe von Reflection kann man diese Auswerten.
Das Beispiel Schritt für Schritt erklärt:

BlitzMax: [AUSKLAPPEN]
' Create a TInjector
Local injector:TInjector = TInjector.Create();

Als erstes wird ein TInjector erstellt. Der TInjector such alle Typen mit der Annotation {Injectable} und erstellt eine Art "Bauplan" für diese. Der entstehende TInjector ist dann in der Lage Instanzen von diesen Typen zu erzeugen und an bestimmten stellen einzufügen (zu Injecten).

BlitzMax: [AUSKLAPPEN]
' Request a TFoo instance;
Local foo:TFoo = TFoo(injector.get("TFoo"));


Als nächste nutzen wir den injector nun dazu um eine instanz des Types TFoo zu bekommen. Da BlitzMax nicht wie Java über Generic Types verfügt müssen wir uns um das Casten selber kümmern, leider nicht so schön aber nicht so schlimm bei einer korrekten Nutzung wird der TInjector sowieso nur ein einziges mal direkt Angesprochen.

Der TInjector erstellt nun eine Instanz vom Typ TFoo mit allen seinen Abhängigkeiten. Wie man in dem Beispiel oben sieht ist im Type TFoo das Field bar:TBar mit {Inject} gekennzeichnet. Der Injector erkennt dies und fügt eine Instanz von TBar automatisch ein.

BlitzMax: [AUSKLAPPEN]
Print foo.bar.name; '"Hello World"


Als letztes um zu Zeigen dass das die Instanz mit all ihren Abhängigkeiten erstellt wurde wird foo.bar.name ausgegeben und es wird Hello World zurückgegeben.

Dies wäre ein sehr Simples beispiel für "Field Injection" des weiteren kann das Framework aber auch noch "Method Injection". Es kann mit "Providern" gearbeitet werden und eigene Provider erstellt werden.

Bei Interesse würde ich diese Punkte hier auch gerne noch mal erklären.

Das Framework ist mit bbdoc's Dokumentiert und enthält einige Beispiel für die hier angesprochenen Themen (MethodInjection, CustomeProvider) außerdem ist es mithilfe von BaH.MaxUnit getestet worden.

Injection.mod


[Edit]
Wozu das alles überhaupt:Dependency Injection ist ein programmier Paradigma, es geht darum "offen" mit den Abhängigkeiten umzugehen und diese beim Erstellen einer Instanz zu Übergeben. Und zwar die direkten Abhängigkeiten (Law of Demeter). Dieses Paradigma hat zur folge, dass man eigentlich zu jedem Type den man hat eine Art Builder/Provider/Factory haben muss. Irgendwo müssen ja die Abhängigkeiten aufgelöst werden. Genau hier greift ein Dependency Injection Framework ein. Das Framework übernimmt die Aufgabe der Dependency Injection, es müssen so gut wie keine Builder/Provider/Factorys mehr geschrieben werden.
Aber warum überhaupt Dependency Injection: Es geht um Testbarkeit von Code. Ein Quellcode welches nicht offen mit seinen Abhängigkeiten umgeht ist schwer zu testen. Ich kann nur jedem diesen Video empfehlen: "The Clean Code Talks -- Unit Testing" es handelt sich dort zwar um Java code, doch die Probleme sind sehr gut zu übertragen.

Es geht bei Dependency Injection um sauberes Programmieren, ein Framework erleichtert dieses ungemein, da die Mühselige Arbeit abgenommen wird und man sich auf das Programmieren von Funktionalität konzentrieren kann.

[Edit2]
Habe es etwas Überarbeitet und auf GitHub

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group