{"id":110,"date":"2015-04-26T11:00:57","date_gmt":"2015-04-26T09:00:57","guid":{"rendered":"http:\/\/invidit.de\/blog\/?p=110"},"modified":"2015-09-20T10:26:50","modified_gmt":"2015-09-20T08:26:50","slug":"refactoring-was-es-ist-und-warum-jeder-entwickler-es-machen-sollte","status":"publish","type":"post","link":"https:\/\/invidit.de\/blog\/refactoring-was-es-ist-und-warum-jeder-entwickler-es-machen-sollte\/","title":{"rendered":"Refactoring &#8211; Was es ist und warum jeder Entwickler es machen sollte"},"content":{"rendered":"<p>Hallo Spa\u00df-Coder.<\/p>\n<p>kennt ihr das Gef\u00fchl, dass ihr euch nicht an euren eigenen Code herantraut? Ihr schreibt ein sch\u00f6nes Programm und nun soll eine Funktion oder ein Feature erg\u00e4nzt werden. Aber der Code ist irgendwie unverst\u00e4ndlich, un\u00fcbersichtlich. Ist ja schlie\u00dflich schon ein paar Monate her, dass ihr ihn geschrieben habt. Noch schneller kommt dieses Gef\u00fchl auf, wenn ihr im Team mit anderen zusammenarbeitet und Code von den Teamkollegen \u00e4ndern m\u00fcsst.<\/p>\n<p>Der erste Schritt, den wir in einer solchen Situation in der Regel unternehmen ist, den Code zu verstehen. Dann versucht man die Stelle zu finden, an der das neue Feature integriert werden soll und passt den Code an oder erweitert ihn. Je nach Qualit\u00e4t des Codes, den ihr vorfindet, ist das ein mehr oder weniger schweres Unterfangen. Hierbei hilft uns das <em>Refactoring<\/em>.<\/p>\n<p>Aber auch bei der Implementierung neuer Features ist es sinnvoll, nach dem Hinzuf\u00fcgen der Funktion noch einmal den Code zu betrachten und zu schauen, ob dieser auch sauber ist und unseren eigenen Anspr\u00fcchen gen\u00fcgt. Wer hat nicht schonmal nach ein paar Wochen in seinen eigenen Code geschaut und gedacht &#8222;Ohje, was habe ich denn da hinterlassen?&#8220;. Besonders bei der Arbeit in Teams h\u00e4lt solcher Code sehr schnell auf, da jeder im Team zun\u00e4chst den Code verstehen und dann ggf. selbst refaktorisieren muss.<\/p>\n<p>&nbsp;<\/p>\n<h3>Was ist Refactoring?<\/h3>\n<blockquote><p>Refactoring oder zu deutsch Refaktorisieren ist die T\u00e4tigkeit, Programmcode mit geeigneter Absicherung und in kleinen Schritten dahingehend zu ver\u00e4ndern, dass er <em>leicht verst\u00e4ndlich<\/em> und <em>einfach zu erweitern<\/em> ist, unter Beibehaltung des bisherigen Verhaltens.<\/p><\/blockquote>\n<p>Das hei\u00dft, wir \u00c4ndern das Verhalten des Codes nicht, wenn wir ihn refaktorisieren.<\/p>\n<p>Ein Refactoring hilft uns in oben beschriebener Situation also doppelt:<\/p>\n<ul>\n<li>der Code wird lesbarer und leichter verst\u00e4ndlich<\/li>\n<li>unser Feature l\u00e4sst sich leichter einbauen, da der refaktorisierte Code leicht zu erweitern ist<\/li>\n<\/ul>\n<p>Wir unterscheiden verschiedene <strong>Arten des Refactorings:<\/strong><\/p>\n<ol>\n<li><strong>Toolunterst\u00fctztes Refactoring<\/strong><br \/>\nDarunter verstehen wir alle Arten des Refactorings, bei der uns unsere IDE unterst\u00fctzt. Darunter fallen etwa Umbenennungen von Variablen, Parametern, Funktionen und Klassen, aber auch das extrahieren von Funktionen in Methoden oder die automatische Umgestaltung von Abfrageausdr\u00fccken.<\/li>\n<li><strong>Refactoring zur Verbesserung der Lesbarkeit<\/strong><br \/>\nWenn wir Code \u00e4ndern m\u00fcssen, den wir nicht verstehen, m\u00fcssen wir uns zwangsl\u00e4ufig damit auseinandersetzen. Vielleicht lesen wir ihn und schreiben uns den Ablauf auf einem Blatt Papier auf, vielleicht nutzen wir Log-Ausgaben oder den Debugger um herauszufinden, was passiert. Irgendwann haben wir den Punkt erreicht, da wissen wir, was der Code macht. Dies ist der richtige Zeitpunkt, um den Code so zu refaktorisieren, dass wir ihn auch beim n\u00e4chsten Mal\u00a0 verstehen. Dann aber ohne langes Analysieren und Debuggen.<\/li>\n<li><strong>Refactoring zur Verbesserung der Erweiterbarkeit<\/strong><br \/>\nHaben wir den Code verstanden (und ggf. zur besseren Lesbarkeit umgebaut), stellen wir ggf. fest, dass wir die Erweiterung sehr schnell und einfach einf\u00fcgen k\u00f6nnten, wenn der Code hier nur ein bisschen anders aufgebaut w\u00e4re. Stellen wir dies fest, sollten wir den Code genau so umbauen, bevor wir unsere Erweiterung vornehmen.<\/li>\n<li><strong>geplantes Refactoring<br \/>\n<\/strong>Wenn wir als Entwickler nicht regelm\u00e4\u00dfig refaktorisieren und den Code immer mehr vernachl\u00e4ssigen, stellen wir irgendwann fest, dass wir Zeit brauchen, um Teile unserer Software umfangreich neu zu gestalten. Es handelt sich um ein &#8222;gro\u00dfes&#8220; Refactoring. Dieses sollte im Projekt- oder Sprintplan als Aufgabe auftauchen, da es eine relevante Zeit dauern wird.<br \/>\nGute Teams werden ein geplantes Refactoring selten brauchen. Das perfekte Team wird es niemals brauchen, da sie st\u00e4ndig den Code im Rahmen ihrer t\u00e4glichen Arbeit sauber halten.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h3>Warum Refactoring?<\/h3>\n<p>Ist das st\u00e4ndige \u00c4ndern von Code, ohne dass wir neue Funktionen oder Features hinzuf\u00fcgen nicht verschwendete Arbeit?<\/p>\n<p>Unserer Ansicht nach nicht. Im Laufe der Zeit wird der Code schlechter und es wird schwieriger \u00c4nderungen einzuf\u00fcgen. Auch glauben wir nicht, dass wir als Softwareentwickler sofort im ersten Wurf den\u00a0 perfekten Code schreiben k\u00f6nnen. Wir schaffen es nicht, bei jedem neuen Feature von Anfang an alle Standards und Namenskonventionen, alle Prinzipien und Empfehlungen einzuhalten. Daf\u00fcr ist unsere Arbeit einfach zu komplex. Sicher, mit erh\u00f6hter Erfahrung werden wir mehr und mehr davon in unsere t\u00e4gliche Arbeit aufnehmen k\u00f6nnen, aber kaum jemand wird den perfekten Code direkt beim ersten Wurf schreiben k\u00f6nnen.<\/p>\n<p>Auch werden sich Anforderungen mit der Zeit \u00e4ndern, Technologien und damit verbundene Prinzipien werden sich \u00e4ndern. Sp\u00e4testens dann sind wir gezwungen, unseren Code zu refaktorisieren.<\/p>\n<p>Durch Refactoring kommen wir in kleinen Schritten immer weiter zu einem komponentenorientierten Design. Erstellen wir im ersten Wurf vielleicht eine Mammutklasse, die zun\u00e4chst das gew\u00fcnschte Feature enth\u00e4lt, refaktorisieren wir ihn anschlie\u00dfend immer weiter unseren Anforderungen entsprechend, sodass der Code sich in saubere Komponenten aufteilt und leicht zu erweitern ist.<\/p>\n<p>Der wichtigste aller Gr\u00fcnde ist aber, dass sauberer, professioneller Code, der eine hohe Qualit\u00e4t hat und sicherstellt, sowie schnell, einfach und sicher zu erweitern ist, mittel- bis langfristig nur ein Ziel hat: eine hohe Wirtschaftlichkeit! Denn k\u00f6nnen wir schneller unser neues Feature einf\u00fcgen, so k\u00f6nnen wir es auch schneller ausliefern.<\/p>\n<p>&nbsp;<\/p>\n<h3>Wie gehen wir beim Refactoring vor?<\/h3>\n<p>Refactoring ist f\u00fcr uns eine permanente T\u00e4tigkeit. Wir schreiben ein paar Zeilen funktionierenden Code, schauen sie uns noch einmal an und bauen sie wieder um, damit sie besser lesbar oder strukturierter sind. Dann schreiben wir weiteren funktionierenden Code, refaktorisieren ihn wieder und so weiter. Wir machen also immer wieder zwei Schritte:<\/p>\n<ol>\n<li>den Code zum Laufen bringen<\/li>\n<li>den Code sauber machen<\/li>\n<\/ol>\n<p>Kent Beck hat sich dazu die Metapher der zwei H\u00fcte \u00fcberlegt. Wir tragen einen Hut, wenn wir den Code zum Laufen bringen und einen anderen, wenn wir den Code sauber machen. Wir haben nur einen Kopf, k\u00f6nnen also nicht beide H\u00fcte gleichzeitig tragen. Wir d\u00fcrfen aber regelm\u00e4\u00dfig die H\u00fcte wechseln.<\/p>\n<p>Stolpern wir beim Refactoring also z.B. \u00fcber einen Fehler, sollten wir das Refactoring zu Ende bringen, den Fehler beheben (den Hut wechseln) und anschlie\u00dfend das Refactoring wieder aufnehmen (den Hut erneut wechseln). Wir sollten uns immer bewusst sein, ob wir den Code zum Laufen bringen oder sauber machen. Wichtig ist, dass wir immer auch den zweiten Schritt durchf\u00fchren. Wir d\u00fcrfen niemals aufh\u00f6ren, bevor wir den Code nicht sauber gemacht haben!<\/p>\n<p>Unsere Verantwortung als Entwickler, der sp\u00e4ter diesen Code wieder \u00e4ndert oder sein Beitrag zu einem Team leistet, ist es, permanent den Code zu bewerten und Designprobleme durch Refaktorisieren zu beheben.<\/p>\n<p>&nbsp;<\/p>\n<h3>Code \u00c4ndern aber das Verhalten beibehalten? Wie geht das denn?<\/h3>\n<p>Wie aber stellen wir sicher, dass beim Refactoring der bestehende Code nicht sein Verhalten \u00e4ndert? Wir \u00e4ndern schlie\u00dflich den vorhandenen Code, teilweise die Struktur und den internen Aufrufstapel.<\/p>\n<p>Hierbei ist es von essenzieller Wichtigkeit, dass wir f\u00fcr jedes von uns erwartete Verhalten ausreichend Tests haben. Bevor wir mit dem Refaktorisieren beginnen, m\u00fcssen alle Tests gr\u00fcn sein! Nur so k\u00f6nnen wir guten Gewissens unseren Code verbessern, ohne die Funktionalit\u00e4t zu ver\u00e4ndern.<\/p>\n<p>Sollte es &#8211; aus welchen Gr\u00fcnden auch immer &#8211; nicht m\u00f6glich sein, Unittests zu schreiben, gilt die Regel, dass wir besser einen Integrationstest schreiben, als gar keinen Test.<\/p>\n<p>Wie ist also unser Fahrplan zum Refactoring?<\/p>\n<ol>\n<li>wir schreiben unser Feature<\/li>\n<li>decken es mit Tests ausreichend ab<\/li>\n<li>pr\u00fcfen, ob die Tests gr\u00fcn sind<\/li>\n<li>f\u00fchren Refactorings durch<\/li>\n<li>pr\u00fcfen erneut, ob alle Tests gr\u00fcn sind<\/li>\n<\/ol>\n<p>Wollen wir vorhandenen Code umbauen, beginnen wir im besten Fall mit Schritt 3. Sind noch keine Tests vorhanden, beginnen wir mit Schritt 2 um das Verhalten vor unserem Umbau zun\u00e4chst abzusichern.<\/p>\n<p>Abschlie\u00dfend haben wir sauberen Code und die Sicherheit, dass wir genau die Funktionalit\u00e4t haben, die wir &#8211; durch die Tests beschrieben &#8211; haben m\u00f6chten.<\/p>\n<p>Die K\u00f6nigsdisziplin dabei ist das sogenannte Test-Driven-Development. Darauf gehen wir aber detaillierter in einem eigenen Artikel ein.<\/p>\n<p>&nbsp;<\/p>\n<h3>Wie viel Refactoring ist denn n\u00f6tig?<\/h3>\n<p>Nun, das kann nur jeder f\u00fcr sich selbst entscheiden. Der Code sollte <a href=\"http:\/\/invidit.de\/blog\/basics-pfadfinderregel\/\">mindestens ein wenig besser sein<\/a>! Nach ein paar Refaktorisierungen in kleinen Schritten wird der Code mit der Zeit deutlich besser. Wichtig ist, dass Refactoring keine zus\u00e4tzliche Arbeit ist, sondern einen Bestandteil er normalen Arbeit f\u00fcr uns als verantwortungsbewussten Entwickler darstellt.<\/p>\n<p>Die ben\u00f6tigte Zeit f\u00fcr das Refactoring wird sich mittelfristig lohnen, da der Code leichter zu verstehen und besser zu \u00e4ndern ist, wenn wir dabei die SOLID-Prinzipien beachten.<\/p>\n<p>Da wir heute noch nicht wissen, was n\u00e4chste Woche, in einem Monat oder in einem halben Jahr von unserem Code verlangt wird, ist eine evolution\u00e4re Entwicklung wichtig. Sobald wir neue Anforderungen an den Code haben, k\u00f6nnen wir den Code entsprechend den neuen Anforderungen \/ Informationen anpassen. Wir sollten es aber vermeiden, zu weit vorauszudenken und den Code komplizierter zu gestalten, als es derzeit notwendig ist. Das Prinzip dahinter tr\u00e4gt auch einen Namen: <a href=\"http:\/\/de.wikipedia.org\/wiki\/YAGNI\" target=\"_blank\">YAGNI<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h3>Zusammenfassung<\/h3>\n<p>Es ist wichtig und unsere Verantwortung als professioneller Entwickler, dass der Code, den wir schreiben, nicht nur funktioniert, sondern <strong>gut lesbar<\/strong>, <strong>leicht verst\u00e4ndlich<\/strong> und <strong>effizient zu erweitern<\/strong> ist.<\/p>\n<p>Refactoring beginnt im Kleinen und ist Bestandteil der t\u00e4glichen Arbeit von uns als Entwickler. Wir refaktorisieren st\u00e4ndig unseren Code und den Code unseres Teams.<\/p>\n<p>Nur so k\u00f6nnen wir mittel- bis langfristig sicherstellen, dass unsere Softwareentwicklung wirtschaftlich bleibt.<\/p>\n<p>&nbsp;<\/p>\n<p>Viel Spa\u00df beim Ausprobieren und Happy Coding w\u00fcnschen<\/p>\n<p>eure Spa\u00df-Coder<\/p>\n<p>&nbsp;<\/p>\n<p>Dieser Artikel basiert neben unseren Erfahrungen auf den Ausf\u00fchrungen aus:<\/p>\n<ol style=\"list-style-type: lower-alpha;\">\n<li id=\"gs_cit0\" class=\"gs_citr\" tabindex=\"0\">Martin, Robert C. <i>Clean Code-Refactoring, Patterns, Testen und Techniken f\u00fcr sauberen Code: Deutsche Ausgabe<\/i>. MITP-Verlags GmbH &amp; Co. KG, 2013.<\/li>\n<li class=\"gs_citr\" tabindex=\"0\">\n<div id=\"gs_cit0\" class=\"gs_citr\" tabindex=\"0\">Fowler, Martin <em><a href=\"https:\/\/www.youtube.com\/watch?v=vqEg37e4Mkw\" target=\"_blank\">Workflows of Refactoring<\/a><\/em>.<br \/>\nOOP 2014<\/div>\n<\/li>\n<li class=\"gs_citr\" tabindex=\"0\">Hariri, Hadi <em><a href=\"https:\/\/www.youtube.com\/watch?v=2Y3kFpNvsvU\" target=\"_blank\">Refactoring Legacy Code Bases<br \/>\n<\/a>Basta Sprint 2013 <\/em><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Hallo Spa\u00df-Coder. kennt ihr das Gef\u00fchl, dass ihr euch nicht an euren eigenen Code herantraut? Ihr schreibt ein sch\u00f6nes Programm und nun soll eine Funktion oder ein Feature erg\u00e4nzt werden. Aber der Code ist irgendwie unverst\u00e4ndlich, un\u00fcbersichtlich. Ist ja schlie\u00dflich schon ein paar Monate her, dass ihr ihn geschrieben habt. Noch schneller kommt dieses Gef\u00fchl [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":159,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[90],"tags":[54,18,55,53,56],"_links":{"self":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/110"}],"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\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/comments?post=110"}],"version-history":[{"count":10,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/110\/revisions"}],"predecessor-version":[{"id":368,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/posts\/110\/revisions\/368"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media\/159"}],"wp:attachment":[{"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/media?parent=110"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/categories?post=110"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/invidit.de\/blog\/wp-json\/wp\/v2\/tags?post=110"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}