Slide 1

Slide 1 text

Dependency Injection ... oder "wie werde ich die Verwandten los"

Slide 2

Slide 2 text

DI & IoC Schon mal gehört?

Slide 3

Slide 3 text

Inversion of Control - IoC Paradigma aus dem Software Design / Architektur Widerspricht dem "klassischen" Ansatz "jeder besorgt sich seine Sachen selbst" Das Objekt, bzw. die Klasse gibt die Steuerung der Abhängigkeiten aus der Hand Sog. Hollywood-Prinzip: "Don't call us, we call you"

Slide 4

Slide 4 text

Dependency Injection - DI Ist ein Entwurfsmuster Betrachtet Abhängigkeiten zwischen Objekten Verwendet ein erweitertes Factory Entwurfsmuster als Basis Ist eine Anwendung des IoC Paradigmas Die Anwendung des Musters auf bestehenden Code ist ein Refactoring Prozess Es gibt Bibliotheken in PHP, die am Ende des Prozesses stehen

Slide 5

Slide 5 text

Kontrolle? Wer? Wie? Ich? Mach mal ein Beispiel ... !

Slide 6

Slide 6 text

So sieht es häufig aus... oDbConn = new MyMysqlDriver(CPATH); } }

Slide 7

Slide 7 text

Besser, aber immer noch gruselig... oDbConn = new $this->sDriverClass(); } }

Slide 8

Slide 8 text

Was läuft da schief? Die Klasse kümmert sich um das Erzeugen von kritischen Objekten Der Klassenname der Abhängigkeit ist fest in der instanzierenden Klasse "verdrahtet" Selbst beim Auslagern des Klassennamens der Abhängigkeit kümmert sich dennoch die Klasse selbst um die Bereitstellung der Instanz

Slide 9

Slide 9 text

Ok, seh ich ein... aber... DI ist nun so viel besser? Ging bis jetzt auch ohne ...

Slide 10

Slide 10 text

Stimmt ...

Slide 11

Slide 11 text

Hast Du denn bisher schon mal Tests für Deine App geschrieben?

Slide 12

Slide 12 text

Wenn ja, hast Du eine solche Klasse schon mal getestet?

Slide 13

Slide 13 text

Ja?

Slide 14

Slide 14 text

Haste bestimmt geflucht, oder?

Slide 15

Slide 15 text

Wäre Dir mit DI wahrscheinlich erspart geblieben ;)

Slide 16

Slide 16 text

Genug der Witze. Wie wende ich das Muster an?

Slide 17

Slide 17 text

Zuerst: Was heißt Abhängigkeit? Eine Abhängigkeit äußert sich durch die Referenzierung oder Verwendung einer konkreten Implementierung in einer Klasse. class FooImpl { public function __construct() { $oVar = new BarImpl(); } } class FooImpl { public function __construct(BarImpl $oParam) { // ... } }

Slide 18

Slide 18 text

Welche Arten von "Injection" gibt es? Constructor Injection Instanzen werden über den Konstruktor beim Erstellen der Instanz übergeben und in der Instanz vorgehalten und / oder weiter durchgereicht. Getter / Setter Injection Instanzen werden per setFoo(FooInterface $oFoo) und getFoo() gesetzt und geholt. Man greift nicht mehr auf die Eigenschaft direkt zu, da auch die Beschaffung der Instanz verborgen wird.

Slide 19

Slide 19 text

Schritt 1: Don't do constructor work Konstruktoren sollen nur den ersten Zustand einer Instanz beschreiben. Schlecht: public function __construct() { $this->oDb = new DbConnImpl( "localhost", "user", "pass"); } Besser: public function __construct(DbConnImpl $oDb) { $this->oDb = $oDb; }

Slide 20

Slide 20 text

Schritt 2: Design by contract Anstelle der Implementierung sollen Interfaces stehen. Dieser Schritt löst die Abhängigkeit zu einer konkreten Implementierung. statt: public function setDbConn(MySQLDbConn $oConn) {} lieber: public function setDbConn(Queryable $oConn) {} => Vorteil: Theoretisch kann die DB nun auch eine SQLite sein, solang das Interface "Queryable" erfüllt ist.

Slide 21

Slide 21 text

Schritt 3: Weg mit den Globals Damit sind sowohl globale Variablen, als auch Singletons in Konstruktoren und Methoden gemeint! denn: public function __construct() { $this->oVar = DbConn::getInstance(); } ist das Gleiche wie: public function __construct() { $this->oVar = $GLOBALS['dbconn']; } Es gibt jedoch Ausnahmen, bei denen es Sinn macht einen Singleton einzusetzen!

Slide 22

Slide 22 text

Ok, Globals weg ... aber woher denn sonst?

Slide 23

Slide 23 text

Bootstrapping

Slide 24

Slide 24 text

Aufgaben des Bootstrappings Erzeugung der global benötigten Objekte (z. B. DbConn) Weiterverteilung der Objekte bei der Initialisierung des Frameworks z. B. MVC-Framework 1. Bootstrap erzeugt DbConn 2. Bootstrap erzeugt MVC-Router 3. Bootstrap übergibt DbConn an MVC Router 4. MVC Router findet passenden Controller 5. MVC Router übergibt DbConn an Controller 6. Controller erzeugt Service Layer 7. Controller übergibt DbConn an Service Layer => DbConn ist nur ein Mal erzeugt worden!

Slide 25

Slide 25 text

IoC Container

Slide 26

Slide 26 text

Was machen IoC Container? Sie kennen die Abhängigkeiten einer Klasse Sie erzeugen Instanzen der geforderten Klasse Sie "konfigurieren" die neue Instanz mit den bekannten Abhängigkeiten Manche können Abhängigkeitsgraphen auflösen => Klasse A braucht eine Instanz von B => B braucht im Konstruktor eine Instanz von C Meist erkennen diese dann auch "Circular References" => Wenn C im o. g. Beispiel eine Instanz von A benötigen würde

Slide 27

Slide 27 text

Verschiedene Ansätze: Deklarativ Im Bootstrap einer App wird der Container konfiguriert. Hierbei wird die Implementierung für ein Interface angegeben. $oCont = Container::getInstance() $oCont->useDep('Queryable', 'MySqlQueryableImpl'); $oCont->manageClass('Foo', 'aNickName'); $oFoo = $oCont->get('aNickName'); assert (($oFoo instanceof Foo) === true) && (($oFoo->getConn() instanceof Queryable) === true) Ein assert auf MySqlQueryableImpl würde ebenfalls funktionieren, aber gegen das Prinzip verstoßen.

Slide 28

Slide 28 text

Verschiedene Ansätze: Annotation Dieser Ansatz ist in PHP noch recht neu. Eine Klasse wird per DocBlock annotiert. class Foo { /** * @inject */ public function __construct(Queryable $oConn){ } } $oCont = Container::getInstance(); $oFoo = $oCont->get('Foo');

Slide 29

Slide 29 text

Verschiedene Ansätze: Konfiguration Eine externe Konfigurationsdatei wird verwendet. Hier ein Beispiel aus einer FLOW3 YAML Konfiguration: F3\MyPackage\Foo: properties: bar: { object: F3\MyPacka ge\BarInterface } $oFoo = Container::getInstance()->get('Foo')

Slide 30

Slide 30 text

Doch Vorsicht! auch der IoC Container ist eine Abhängigkeit!

Slide 31

Slide 31 text

Habt ihr Beispiele? Lasst uns drüber reden...

Slide 32

Slide 32 text

Vielen Dank!

Slide 33

Slide 33 text

Ein paar Links Blogartikel über Symfony's DIC http://usrportage.de/archives/926-Dependency-Injection-Container- Refactorings,-Part-One.html Martin Fowler über "Injection" http://martinfowler.com/articles/injection.html Flow3 Object Framework http://flow3.typo3.org/documentation/manuals/flow3/flow3. objectframework/#flow3.objectframework.objectdependencies