Letzte Woche gab es den ersten Teil der DI-Beitragsreihe. Es wurde das Konzept der Constructor Injection vorgestellt. Heute wollen wir einen kleinen Schritt weiter in Richtung DI-Container gehen. Dafür wird ein weiteres Konzept vorgestellt, dass eine Alternative zur Constructor Injection ist.
Das letzte Beispiel sah so aus:
class Example { private $db; public function __construct(MyDatabase $db) { $this->db = $db; } public function getSomething() { return secretFunction($this->db->query("Select * from test")); } }
Setter Injection:
Bei diesem Konzept kann man den Konstruktor Aufruf säubern, da nicht alle Abhängigkeiten beim Erzeugen des Objekts vorhanden sein müssen. Diese können nachträglich gesetzt werden. Das Beispiel sieht dann umgebaut so aus:
class Example { private $db; public function __construct(MyDatabase $db) { // init something } public function setDatabase(MyDatabase $db) { $this->db = $db; } public function getSomething() { if ($this->db == null) { throw new Exception("database connection must not be null"); } return secretFunction($this->db->query("Select * from test")); } }
Nachteile:
Da man die Initialisierung des Objekts und das Setzen der Abhängigkeiten entzerren kann, besteht auch die Gefahr, dass man einen Methodenaufruf nutzt, der noch nicht funktional ist. Somit muss man sich gegen diesen Fall absichern.
Wenn viele Abhängigkeiten existieren muss man eine ganze Reihe Setter-Aufrufe aneinander reihen. Die Abhängigkeitsanzahl wird aber dadurch auch nicht reduziert.
Die Vorteile, die man schon aus der Constructor Injection kennt, hat man hier natürlich auch. Das Unittest-Mock Beispiel greift somit wieder.