Follow my new blog

Montag, 23. Mai 2011

Drei Zwecke fürs Refactoring

Refactoring ist zu einer festen Vokabel in der Branche geworden, würde ich sagen. Ohne Refactoring geht es in älteren größeren Projekten einfach nicht. Deshalb hat Refactoring, so scheint mir, ein sehr pauschal gutes Image. Refactoring sollte man können und tun. Bei TDD ist es sogar in der Definition: red-green-refactor.

Mir scheint jedoch, dass wir gut daran täten, zu differenzieren. Ist Refactoring immer gleich? (Womit ich nicht “Extract Method” mit “Extract Interface” vergleichen will.) Hat Refactoring immer denselben Zweck? Zweck ist ja nicht, die Umstrukturierung von Code unter Beibehaltung der Funktionalität. Das ist nur, was passiert.

Ich glaube, es gibt mindestens drei unterschiedliche Zwecke oder Ziele für Refactoring. Jeder hat mit innerer Codequalität vor dem Hintergrund des aktuellen Problemverständnisses zu tun. Innere Qualität existiert nämlich nicht absolut, so denke ich, sondern nur im Verhältnis zu einer Vorstellung davon, was eigentlich das Kern der Anforderungen an eine Software ist und wie eine Lösung grundsätzlich aussehen sollte.

  • Qualität steigern #1: Wenn von Refactoring die Rede ist, dann ist meist Refactoring zur Verbesserung der inneren Qualität gemeint. Sie stehen vor einem Brownfield und wollen daraus – zumindest in Teilen – eine blühende Wiese machen. Den Spaghetticode entzerren. Die technische Schuldenlast abtragen. Darum geht es bei legacy code. Die innere Qualität ist schlecht und bevor man auch nur daran denken kann, neue Funktionalität hinzuzufügen, müssen Sie erstmal Grund reinbringen.
    Beispiel: Die 10.000 Zeilen Klasse, die Sie zerlegen, um sie besser zu verstehen und dann zu erweitern.
  • Qualität beibehalten #2: Refactoring lässt sich nicht vermeiden, auch wenn die innere Qualität schon hoch ist. Denn neue Anforderungen mögen eine andere Struktur des Code erfordern. Also müssen Sie auch Refactoring betreiben, um eine hohe Qualität zu erhalten. Das finde ich wert es zu unterscheiden von Refactoring-Zweck #1.
    Beispiel: Das Refactoring nach den TDD red-green-Schritten.
  • Qualität transformieren #3: Schließlich gibt es noch einen weiteren Refactoring-Zweck, der nicht unbedingt mit neuen Anforderungen zu tun hat. Bei #1 geht es darum, Code für die Umsetzung von Anforderungen überhaupt fit zu machen; bei #2 geht es darum, fitten Code fit zu halten im Lichte neuer Anforderungen. Aber bei #3 ist der Code fit (hohe innere Qualität), keine neuen Anforderungen liegen an – und doch treibt Sie etwas zum Refactoring – und zwar eine neue Sichtweise auf Problem und Code. Domain Driven Design nennt das refactoring to deeper insight. Die tiefere Einsicht kann darin bestehen, dass Lösungsbestandteile umgewichtet werden oder Sie erkennen, dass zwischen manchen Bestandteilen eine engere Beziehung besteht, als zunächst gedacht. Das sollte sich dann auch in der Struktur des Codes ausdrücken.
    Wie gesagt: Anlass für ein solches Refactoring ist keine Schwierigkeit, Änderungen anzubringen, sondern die Erkenntnis, das Struktur und Problem nicht mehr optimal zueinander passen. Durch ein refactoring to deeper insight erhöht sich die Verständlichkeit von Code.
    Beispiel: Sie ziehen die Funktion BonitätPrüfen() aus einer Kundenklasse raus in eine eigene Klasse Bonitätsprüfer, nicht weil sie schwieriger zu ändern wäre in der Kundenklasse oder darin zu unschönen Abhängigkeiten führen würde, sondern weil sich herausstellt, dass die Bonitätsprüfung ein zentraler Bestandteil der Anwendung ist, der verdient, in einer eigenen Klasse oder gar Komponente repräsentiert zu sein.

Mit dieser Unterteilung von Refactoring nach Zwecken, können wir nun besser in unseren Gesprächen unterscheiden, worüber wir sprechen. Wenn zum Beispiel ein Kunde hört, wir würden Zeit in Refactoring stecken und zuckt, weil er denkt, die innere Qualität müsse wohl schlecht sein, dann können wir schneller das Missverständnis aufdecken. Denn wo er an #1 gedacht hat, haben wir in Wirklichkeit über #3 gesprochen.

Oder wir können uns Maximen formulieren:

  • Vermeide Refactoring #1 von vornherein dadurch, dass du hohe innere Qualität produzierst mittels Flow-Design und/oder TDD.
  • Denke an Refactoring #2 im Zuge jeder Änderung an vorhandener hoher innerer Qualität.
  • Sei offen für tiefere Einsichten, die du im Code durch Refactoring #3 manifestierst, damit der Code noch besser verständlich wird.

Mir hat diese Unterscheidung jedenfalls in der letzten Zeit geholfen.

In diesem Sinne: happy refactoring!

Spendieren Sie mir doch einen Kaffee, wenn Ihnen dieser Artikel gefallen hat…

Keine Kommentare: