Lessons Learned @ NZZ – Teil 5 – Refactoring von Fat Controllern

Im letzten Teil der Serie habe ich ja beschrieben, was ein (Symfony2)-Controller tun sollte bzw. was meine Erkenntnisse bezüglich fat Controllern ist. Ein Artikel auf test.ical.ly gibt ein paar gute Tips, wie man fat Controller verhindern kann.

Was kann man nun tun, wenn man riesige Controller hat (aus was für Gründen auch immer) und diese wieder in schlanke, verständliche, lesbare Controller refactoren will? Ich beschreibe nun eine Vorgehensweise, welche sich für mich schon einige Male bezahlt gemacht hat. Vielleicht könnt ihr auch davon profitieren.

Code studieren und grob verstehen?

Als ersten Schritt muss man versuchen im groben zu verstehen, was der Controller macht.

  • Was für Logik beinhaltet der Controller?
  • Welche Services / Klassen werden verwendet?
  • Welche Daten werden für die HTML / JSON / XML Response aufbereitet?
  • Welche Templates werden mit den Daten befüllt?

Funktionale Tests schreiben

Falls noch keine Tests vorhanden sind, sollte unbedingt versucht werden, die Controller mit funktionalen Tests abzudecken, um für das Refactoring Sicherheit zu gewinnen. Man soll schliesslich ohne Bedenken/Angst das Refactoring durchführen können. Da aktuell der Code wahrscheinlich sehr verdrahtet und abhängig voneinander ist, sind funktionale Tests die richtige Wahl. Ausserdem kann man mit funktionalen Tests auch viel Code mit verhältnismässig wenigen Tests abdecken.

Auslagern in kleine private Methoden

Nachdem die Tests geschrieben sind, kann man mit dem Auslagern des Controller-Codes in kleine private Methoden beginnen. Die privaten Methoden verbleiben hierbei noch im Controller, werden aber später in andere Klassen ausgelagert. Man sollte einfach kleine zusammenhängende Code-Blöcke finden und gute Funktionsnamen vergeben.

Ich empfehle ausserdem, dass die Code-Blöcke strikte in Integrations- oder Operations-Funktionen unterteilt werden. Der Blogpost von Ralf Westphal hat mich sehr beeindruckt und ist für mich ein sehr schlüssiges Vorgehen.

Während des Auslagerns, findet man eventuell noch weitere Testfälle, welche man dann natürlich ergänzen sollte. Ausserdem wird einem auch immer mehr klar, was der Code eigentlich genau alles tut/kann.

Klassendesign erstellen

Nachdem man nun viele kleine Methoden hat, sollte man Papier und Stift zur Hand nehmen und Klassen identifizieren, in welche die Methoden verschoben werden können. Es muss kein perfektes UML sein, eine einfach Skizze mit Kästchen und Pfeilen reicht schon. Man sollte einfach ein Gefühl für die neue Struktur erhalten. Ausserdem lohnt es sich eigentlich immer, wenn man das neue Klassendesign mit einem zweiten Entwickler kurz durchgeht/bespricht. Normalerweise kommt da immer wertvoller Input zurück.

Refactoring in die neuen Klassen

In diesem Schritt werden die Methoden in die vorher neu gebildeten Klassen verschoben. Währen dem Refactoring kann es gut sein, dass noch weitere Klassen dazu kommen oder auch wegfallen. Man sollte das ganze so lange weiterführen, bis man das Gefühl hat, dass die Methoden am richtigen Ort sind. Natürlich sollte man jeweils nach einigen kleinen Refactorings die Tests wieder laufen lassen, um zu prüfen, ob der Code noch das tut, was er vorher schon getan hat.

Codereview eines Entwicklers

Als letzten Schritt empfehle ich, dass der Code nochmals von einem anderen Entwickler angeschaut wird. Er soll vor allem darauf achten, ob er den Code versteht und falls eine Modifikation nötig wäre, das auch tun könnte, ohne den Code stundenlang studieren zu müssen.

Feedback erwünscht

Da dies ein sehr subjektives Vorgehen ist, würde mich Euer Feedback freuen.

  • Sind das sinnvolle Schritte? Zu viel, zu wenig?
  • Wie packt ihr (Controller)-Refactorings normalerweise an?

 

1 Response

Leave a Reply

Your email address will not be published. Required fields are marked *