Aus unserer beliebten Sendereihe “Was machen die Techies da eigentlich?” lesen Sie heute die Folge “Refactoring ist wie Aufräumen, nur cooler”.
Softwareentwickler sagen manchmal Sachen wie “Da müssen wir mal ein Refactoring machen” oder “Refactor mercilessly!” oder “That piece of code is not well-factored”. Wie andere Profis auch haben sie ihren eigenen Jargon, und den zu verstehen kann manchmal ganz nützlich sein.
Refactoring ist das Umstrukturieren von Code, ohne dabei die Funktionalität zu ändern.
Lassen Sie mich Ihr Verständnis mit einer Analogie aufbauen. Wenn unser Code eine Werkstatt wäre, dann wären die Features (Business-Prozesse) die Dinge, die wir in dieser Werkstatt herstellen können. Dann könnten wir sagen
Aufräumen ist das Umstrukturieren der Werkstatt, ohne dabei die Funktionalität zu ändern.
Wenn ich also alle Schraubenschlüssel in dasselbe Regalfach räume, ist das ein Refactoring. Wenn ich hingegen eine Kreissäge anschaffe, ist das kein Refactoring, weil ich damit die Möglichkeiten (Funktionalität) der Werkstatt erweitere. Ein paar eingetrocknete Farbtöpfe wegzuwerfen (unbenutzten Code entfernen) wäre wiederum ein Refactoring – die Funktionalität der Werkstatt wird ja nicht mehr oder weniger.
Warum macht man ein Refactoring? Um spätere Änderungen zu erleichtern und damit verbundene Bugs zu vermeiden. Das ist noch zu schwach formuliert, in etlichen Fällen müsste es heißen: um spätere Änderungen erst möglich zu machen.
Hier ein einigermaßen realistisches Beispiel aus der Softwareentwicklung: Denken Sie an die Berechnung des Preises inkl. Umsatzsteuer. Wenn der Code schlecht strukturiert ist, gibt es vielleicht 17 Stellen, an denen ein Netto-Preis mit 1,19 multipliziert wird. Und dann noch 3 Stellen, an denen auf den Netto-Preis 19% draufgeschlagen werden. (Manche Programmierer sagen dann gern “Das ist historisch so gewachsen.”).
Ein Refactoring wäre dann, die Vorschrift zur Berechnung von Umsatzsteuer und Brutto-Preis nur noch an einer Stelle im Code zu implementieren, z.B. in einem Objekt, dass Sie SalesTaxCalculator nennen. Vor und nach dem Refactoring haben Sie dieselbe Funktionalität, hinterher ist der Code “nur” besser aufgeräumt.
Wenn Sie das Refactoring nicht machen, wird sich die schlechte Code-Qualität rächen, sobald Änderungen gemacht werden müssen. Zum Beispiel könnte nach einer Weile auffallen, dass auf unseren Rechnungen falsch gerundet wird. Kaufmännische Rundung ist Vorschrift und es wird unangenehm, wenn das Finanzamt ständig irgendwelche Differenzen im 1-Cent-Bereich beanstandet.
Der unerfahrene Programmierer wird die Rundungsregeln an 16 von 17 Stellen einbauen (eine hat er übersehen), und die drei Stellen wo 19% draufgeschlagen werden, komplett vergessen. Der erfahrene Programmierer wird zuerst ein Refactoring machen, so dass die Umsatzsteuerberechnung nur noch an einer Stelle stattfindet. Danach wird er die Rundungsregeln an dieser einen Stelle einbauen.
Durch das Zentralisieren der Berechnung werden auch zukünftige Änderungen erleichtert. Wenn Sie z.B. in die Niederlande expandieren, braucht Ihr Code nicht nur den normalen niederländischen Steuersatz von 21%, sondern für einige Ihrer Produkte vielleicht den ermäßigten Steuersatz von 6% (der interessanterweise z.B. für Fahrradbau und Zierpflanzen anfällt). Nach dem Refactoring haben Sie wesentlich weniger Arbeit bei der Anpassung: Der SalesTaxCalculator muss um landesspezifische Steuersätze erweitert werden. Außerdem brauchen Sie noch eine Tabelle, die zu einem Produkt und einem Land den Steuersatz angibt. Die Änderungen halten sich in Grenzen und haben ein wesentlich geringeres Risiko als in der “unaufgeräumten” Variante des Codes.
Das “Zentralisieren von Geschäftslogik” wie im obigen Beispiel ist eine der wichtigsten Spielarten des Refactorings, es gibt andere wie z.B. dass Umbenennen von Funktionen, das Vereinfachen von Teilen des Programms u.ä.
Wenn nun durch Refactoring keine neue Funktionalität zustande kommt, worin besteht der Wert für’s Business?
Refactoring ist eines der wichtigsten Mittel im Kampf gegen unnötige Komplexität. Und unnötige Komplexität ist die Quelle für überraschende Mehrkosten z.B. durch Terminüberschreitung, Bugs, und Sicherheitslücken. Kontinuierliches Refactoring sorgt dafür, dass der Code gut strukturiert ist, wodurch sich neue Features schneller entwickeln lassen. Langfristig verringert sich die Total Cost of Ownership, also nicht nur die Kosten für die Erstellung der Software, sondern auch für Wartung und Anpassung.
Es gibt mindestens zwei dicke Bücher über das Thema Refactoring – Sie sehen also, dass wir hier nur an der Oberfläche eines vielschichtigen Themas gekratzt haben. Ich hoffe, es war trotzdem nützlich und erhellend und freue mich über Rückfragen oder Kommentare.
Matthias Berth