{"id":699,"date":"2015-10-28T16:15:05","date_gmt":"2015-10-28T14:15:05","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=699"},"modified":"2015-11-08T13:24:55","modified_gmt":"2015-11-08T11:24:55","slug":"eine-ganze-fabrik-nur-zum-testen","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/eine-ganze-fabrik-nur-zum-testen\/","title":{"rendered":"Eine ganze Fabrik &#8211; nur zum Testen"},"content":{"rendered":"<p>Hallo Spa\u00df-Coder.<\/p>\n<p>Heute geht es wieder um das Thema Rafactoring und eine weitere M\u00f6glichkeit, Abh\u00e4ngigkeiten aufzul\u00f6sen, um unseren Code unter Testkontrolle zu bringen. Wem ist schon einmal eine Klasse \u00fcber den Weg gelaufen, welche im Konstruktor mehrstufige Abh\u00e4ngigkeiten erzeugt, um sp\u00e4ter eine korrekt initialisierte Klasse verwenden zu k\u00f6nnen? Hier gibt es sicherlich verschiedene Ans\u00e4tze, was man h\u00e4tte besser machen k\u00f6nnen. Wer einen Blick auf das &#8222;D&#8220; von SOLID werfen m\u00f6chte, kann dies im Artikel <a href=\"http:\/\/invidit.de\/blog\/dependency-inversion-principle\/\">Dependency Inversion Principle<\/a> machen. Jetzt ist aber das Kind bereits in den Brunnen gefallen und der Konstruktor sieht so aus wie oben beschrieben.<\/p>\n<p>Mit der Idee, nur mit Tests abgesicherten Code umzubauen, wird es schwierig die Klasse sinnvoll zu testen, wenn alle Abh\u00e4ngigkeiten im Konstruktor selbst erzeugt werden. Hier haben wir ohne Weiteres keine Einflussm\u00f6glichkeiten. Wie an vielen anderen Stellen auch kann ein Mocking-Framework dabei unterst\u00fctzen, Abh\u00e4ngigkeiten zwischen Klassen aufzuheben. Doch geht es auch ohne Framework?<\/p>\n<p>&nbsp;<\/p>\n<h1>Extract and Override Factory Method<\/h1>\n<p>Das nachfolgende Muster hilft uns sehr schnell dabei, Herr \u00fcber die oben geschilderte Ausgangslage zu werden. Das Prinzip ist einfach: wenn wir das Erzeugen der Abh\u00e4ngigkeiten beeinflussen wollen, brauchen wir nur den zugeh\u00f6rigen Code in eine separate Methode zu schieben (<em>Extract Method<\/em>) und in einer abgeleiteten Klasse zu \u00fcberschreiben. Diese neue Klasse ist dann das subject under test, welches sich nat\u00fcrlich genauso verh\u00e4lt wie die urspr\u00fcngliche Klasse mit Ausnahme der Erzeugung der Abh\u00e4ngigkeiten.<\/p>\n<p>Die extrahierte Methode wird <strong>Fabrik-Methode<\/strong> genannt. Unser Produktions-Code bleibt unver\u00e4ndert erhalten und &#8222;fabriziert&#8220; die ben\u00f6tigten Klassen wie es bisher der Konstruktor getan hat. In der Testklasse k\u00f6nnen wir jedoch die Fabrik-Methode durch \u00dcberschreibung in der Form anpassen, dass die Abh\u00e4ngigkeiten auf von uns bereitgestellte Fake- oder Mock-Objekte ge\u00e4ndert werden. Damit haben wir die Abh\u00e4ngigkeit f\u00fcr unseren Test aufgehoben und k\u00f6nnen die Klasse unter Testkontrolle bringen.<\/p>\n<p>In der abgeleiteten Klasse k\u00f6nnen die Fake- oder Mock-Objekte sogar als Instanzvariablen zugewiesen werden (ggf. \u00fcber einen weiteren Konstruktor). So wird die Klasse zus\u00e4tzlich noch sehr flexibel f\u00fcr verschiedene Testszenarien.<\/p>\n<p>Hier noch mal alle erforderlichen Schritte.<\/p>\n<h2>Anleitung<\/h2>\n<ol>\n<li>Objekterstellung im Konstruktor identifizieren.<\/li>\n<li>Extrahieren der gesamten Logik f\u00fcr die Erstellung in eine Fabrik-Methode (protected).<\/li>\n<li>Abgeleitete Klasse f\u00fcr den Test erstellen und Fabrik-Methode \u00fcberschreiben.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h1>Schlechter Stil &#8211; aber testbar!<\/h1>\n<p>Mit Hilfe dieses Vorgehens erreichen wir unser Ziel. Wir schaffen die M\u00f6glichkeit, dass der Code testbar wird. Er wird aber auch zun\u00e4chst schlechter was den Programmierstil angeht. Statische Code-Analyse-Tools wie etwa PMD werden dieses Pattern als schlechtes <a href=\"http:\/\/pmd.sourceforge.net\/pmd-4.3.0\/rules\/design.html#ConstructorCallsOverridableMethod\">Code-Design anmeckern<\/a>. Prinzipiell birgt das Aufrufen \u00fcberschriebener Methoden im Konstruktor einer Klasse Gefahren.<\/p>\n<p>Beim Refactoring sollen wir aber ohnehin besonders vorsichtig sein. Ist unser Code einmal testbar, k\u00f6nnen wir auch die Erstellung der Klasseninstanz sauber nach dem SOLID-Prinzip aufr\u00e4umen um auch unserem Anspruch an Code-Design-Regeln zu entsprechen.<\/p>\n<p>&nbsp;<\/p>\n<h1>Zusammenfassung<\/h1>\n<p>Wie bei allen vorgestellten Refactoring-Patterns steht bei diesen Vorgehensweisen im Vordergrund, dass der Einfluss auf den Produktionscode so gering wie m\u00f6glich ist. Zu leicht passiert es, dass das Verhalten des Codes ungewollt ge\u00e4ndert wird und damit unbewusst Fehler eingebaut werden. Die Fabrik-Methode macht nicht nur den Produktions-Code lesbarer, sondern bietet uns in sehr wenigen Schritten die M\u00f6glichkeit, Abh\u00e4ngigkeiten aufzul\u00f6sen und die gew\u00fcnschten Tests vor dem Refactoring zu erstellen.<\/p>\n<p>&nbsp;<\/p>\n<p>Wir w\u00fcnschen euch viel Spa\u00df beim Ausprobieren.<\/p>\n<p>Eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p>Dieser Artikel basiert neben unseren Erfahrungen auf folgenden Quellen:<\/p>\n<ul>\n<li id=\"gs_cit0\" class=\"gs_citr\" tabindex=\"0\">Feathers, Michael C. <i>Effektives Arbeiten mit Legacy Code: Refactoring und Testen bestehender Software<\/i>. mitp Verlags GmbH &amp; Co. KG, 2011.<\/li>\n<li class=\"gs_citr\" tabindex=\"0\"><a href=\"http:\/\/pmd.sourceforge.net\/pmd-4.3.0\/rules\/design.html\">PMD<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df-Coder. Heute geht es wieder um das Thema Rafactoring und eine weitere M\u00f6glichkeit, Abh\u00e4ngigkeiten aufzul\u00f6sen, um unseren Code unter Testkontrolle zu bringen. Wem ist schon einmal eine Klasse \u00fcber den Weg gelaufen, welche im Konstruktor mehrstufige Abh\u00e4ngigkeiten erzeugt, um sp\u00e4ter eine korrekt initialisierte Klasse verwenden zu k\u00f6nnen? Hier gibt es sicherlich verschiedene Ans\u00e4tze, was [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":724,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[90],"tags":[65,53,69],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/699"}],"collection":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=699"}],"version-history":[{"count":4,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/699\/revisions"}],"predecessor-version":[{"id":722,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/699\/revisions\/722"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/724"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}