32 Punkte von xguru 2024-09-02 | 6 Kommentare | Auf WhatsApp teilen
  • Code-Refactoring spielt eine wichtige Rolle dabei, eine Codebasis gesund zu halten
  • Falsch durchgeführtes Refactoring kann den Code jedoch im Gegenteil komplexer und schwerer wartbar machen
  • Man sollte gutes und schlechtes Refactoring unterscheiden können und wissen, wie man die Fallstricke schlechten Refactorings vermeidet

Das Gute, das Schlechte und das Hässliche am Refactoring

  • Abstraktion kann gut oder schlecht sein. Entscheidend ist zu wissen, wann und wie sie angewendet werden sollte
  • Es werden einige häufige Fallstricke und Wege zu ihrer Vermeidung erklärt (der Code aus dem Original wurde ausgelassen)

1. Den Coding-Stil stark verändern

  • Entwickler machen beim Refactoring oft den Fehler, den Coding-Stil vollständig zu ändern
  • Die Einführung neuer Bibliotheken oder die Übernahme eines völlig anderen Coding-Stils kann sich negativ auf die Wartbarkeit auswirken
  • Besser ist es, den Code idiomatischer und lesbarer zu machen, ohne ein völlig neues Paradigma oder externe Abhängigkeiten einzuführen

2. Unnötige Abstraktion

  • Es ist problematisch, übermäßig viele neue Abstraktionen hinzuzufügen, ohne den bestehenden Code verstanden zu haben
  • Das erhöht nur die Komplexität und kann den Code schwerer verständlich machen
  • Es ist besser, Logik in kleine, wiederverwendbare Funktionen aufzuteilen, ohne unnötige Komplexität einzuführen

3. Inkonsistenz hinzufügen

  • Wenn nur ein Teil der Codebasis so aktualisiert wird, dass er völlig anders funktioniert, kann das Verwirrung und Frustration auslösen
  • Wenn ein neues Muster eingeführt werden muss, sollte man sich zuerst die Zustimmung des Teams holen
  • Es ist wichtig, bei der Datenbeschaffung in der gesamten Anwendung einen konsistenten Ansatz beizubehalten

4. Den Code vor dem Refactoring nicht verstehen

  • Den Code zu lernen und gleichzeitig zu refaktorieren, ist keine gute Idee
  • Das kann Bugs erzeugen, die Performance verschlechtern und Funktionen entfernen
  • Vor dem Refactoring ist es wichtig, den Code gründlich zu verstehen und ihn zu verbessern, ohne das bestehende Verhalten zu verändern

5. Den geschäftlichen Kontext verstehen

  • Technische Entscheidungen ohne Verständnis des geschäftlichen Kontexts zu treffen, kann katastrophal sein
  • Bei einer E-Commerce-Website, die stark auf SEO angewiesen ist, kann Client-Side Rendering eine schlechte Wahl sein
  • Server-Side-Rendering-Ansätze wie Next.js oder Remix können im Hinblick auf SEO und Performance die bessere Wahl sein

6. Übermäßige Zusammenlegung von Code

  • Es ist keine gute Idee, Code zusammenzulegen, nur um ihn „sauber“ zu machen, wenn dabei Flexibilität verloren geht
  • Bei Abstraktionen sollte man immer die Anwendungsfälle berücksichtigen, die sie unterstützen sollen
  • Man sollte sicherstellen, dass die Abstraktion alle Funktionen zulässt, die die ursprüngliche Implementierung bereitgestellt hat

Auf die richtige Weise refaktorieren

  • Code-Refactoring ist notwendig. Aber es muss auf die richtige Weise erfolgen
  • Unser Code ist nicht perfekt und muss aufgeräumt werden, aber die Konsistenz mit der bestehenden Codebasis sollte gewahrt bleiben
  • Man sollte erst refaktorieren, nachdem man den Code gut verstanden hat, und Abstraktionen sorgfältig auswählen
  • Tipps für erfolgreiches Refactoring:
    • Schrittweise vorgehen: kleine, handhabbare Änderungen statt eines vollständigen Rewrite durchführen
    • Den Code gründlich verstehen, bevor wichtige Refactorings oder neue Abstraktionen eingeführt werden
    • Zum bestehenden Coding-Stil passen: Konsistenz ist der Schlüssel zur Wartbarkeit
    • Nicht zu viele neue Abstraktionen einführen: einfach halten, sofern zusätzliche Komplexität nicht wirklich nötig ist
    • Insbesondere keine neuen Bibliotheken mit stark abweichendem Programmierstil hinzufügen, ohne die Zustimmung des Teams
    • Vor dem Refactoring Tests schreiben und sie währenddessen aktualisieren. So lässt sich sicherstellen, dass die ursprüngliche Funktionalität erhalten bleibt
    • Sich gegenseitig im Team dazu anhalten, diese Prinzipien einzuhalten

Werkzeuge und Techniken für besseres Refactoring

  • Für besseres Refactoring sollte der Einsatz der folgenden Techniken und Werkzeuge erwogen werden:

Linting-Tools

  • Linting-Tools verwenden, um einen konsistenten Coding-Stil durchzusetzen und potenzielle Probleme zu erkennen
  • Mit Prettier ist eine automatische Formatierung in einem konsistenten Stil möglich
  • Mit Eslint können über benutzerdefinierte Plugins feinere Konsistenzprüfungen durchgeführt werden

Code Reviews

  • Gründliche Code Reviews einführen, um vor dem Mergen des refaktorierten Codes Feedback von Kollegen zu erhalten
  • Das hilft, potenzielle Probleme früh zu erkennen und sicherzustellen, dass der refaktorierte Code den Teamstandards und Erwartungen entspricht

Testing

  • Tests schreiben und ausführen, damit refaktorierter Code bestehende Funktionen nicht beeinträchtigt
  • Vitest ist ein besonders schneller, robuster und einfach zu nutzender Test Runner, der standardmäßig keine Konfiguration benötigt
  • Für visuelle Tests kann Storybook in Betracht gezogen werden
  • React Testing Library ist eine gute Sammlung von Utilities zum Testen von React-Komponenten (es gibt auch Varianten für Angular usw.)

(geeignete) AI-Tools

  • Refactoring-Bemühungen mit AI-Tools unterstützen, die sich an bestehende Coding-Stile und Regeln anpassen können
  • Visual Copilot ist ein besonders nützliches Tool, um beim Frontend-Coding Konsistenz zu wahren
    • Es hilft dabei, Designs in Code zu übersetzen, während es zum bestehenden Coding-Stil passt und Design-System-Komponenten sowie Tokens korrekt nutzt

Fazit

  • Refactoring ist ein notwendiger Teil der Softwareentwicklung, sollte aber sorgfältig und mit Rücksicht auf die bestehende Codebasis und die Teamdynamik durchgeführt werden
  • Das Ziel von Refactoring ist es, die interne Struktur des Codes zu verbessern, ohne sein äußeres Verhalten zu verändern
  • Die besten Refactorings sind für Endnutzer oft unsichtbar, machen das Leben von Entwicklern aber deutlich leichter
  • Sie verbessern Lesbarkeit, Wartbarkeit und Effizienz, ohne das Gesamtsystem unübersichtlich zu machen
  • Wenn man den Drang verspürt, einen „großen Plan“ für den Code zu entwerfen, sollte man einen Schritt zurücktreten, den Code gründlich verstehen, die Auswirkungen der Änderungen bedenken und schrittweise Verbesserungen vornehmen, die das Team zu schätzen weiß
  • Das zukünftige Ich und die Kollegen werden einen durchdachten Ansatz zu schätzen wissen, der die Codebasis sauber und wartbar hält

6 Kommentare

 
toaonly 2024-09-04

Es gibt auch immer wieder Leute, die ohne Testcode direkt mit dem Refactoring loslegen.
Wenn man das so sieht, wirkt es, als würden sie einen brandgefährlichen Drahtseilakt vollführen – irgendwie aufregend, haha.

 
ahwjdekf 2024-09-03

Punkt 4, „Den Code vor dem Refactoring nicht verstehen“ – das ist wirklich ein sehr treffender Punkt.

 
bichi 2024-09-02

Das sind so selbstverständliche Dinge, fast schon Grundlagenwissen, haha. Schön, dass das mal übersichtlich zusammengefasst wurde. Ich würde sagen: Wenn man refaktoriert, kommt am Ende zu 100 % besserer Code heraus. Wenn nicht, heißt das dann nicht, dass sich meine Fähigkeiten seit gestern rückwärts entwickelt haben?

Wenn ich sehe, dass hier Selbstverständlichkeiten zusammengetragen wurden, wirkt es so, als hätte jemand einen kompletten Scherbenhaufen vorgefunden und diesen Beitrag aus echter Frustration geschrieben, haha

 
kandk 2024-09-02

Eher als darum, wie man gut refaktoriert, geht es darum, wie man im Arbeitsalltag praktisch gut programmiert..
(Sieht aus wie ein Beitrag, den jemand aus Frust geschrieben hat, nachdem ein Junior ins Team kam, das Legacy-Projekt refaktorieren wollte, dabei hier und da alles unnötig kompliziert gemacht und Bugs eingebaut hat...)

 
savvykang 2024-09-02

Menschen, die die Einheit der fachlichen Arbeit und die Einheit des Codes nicht unterscheiden können oder beides verwechseln, machen solche Refactorings – unabhängig davon, wie viel oder wie wenig Berufserfahrung sie haben. Code, der sich leicht ändern und warten lässt, muss letztlich auch dann noch den fachlichen Ablauf erkennen lassen, wenn später jemand anderes dazukommt; manchmal frage ich mich, ob man das wirklich erst versteht, wenn man es in der Praxis erlebt hat.

 
savvykang 2024-09-02

Ich habe in React einmal ein Beispiel erlebt, das für übermäßige Abstraktion steht: Obwohl die Tabellenkomponente bereits durch das UI-Framework abstrahiert war, sollte man meiner Meinung nach vermeiden, per Inversion of Control eine neue Komponente ohne eigentliche Aufgabe zu erstellen, nur weil die Schemata zweier Tabellen ähnlich aussehen. Als ich Fälle gesehen habe, in denen unter dem Vorwand der Anwendung von Atomic Design zehnzeilige leere Container-Komponenten massenhaft erstellt wurden, war das sehr unpraktisch, weil man dafür an zu viele verschiedene Stellen schauen musste.

Die DRY-Regel war ursprünglich dazu gedacht, nicht einfach Code mit exakt derselben Form und derselben Funktion zu kopieren und einzufügen, aber es scheint unvermeidlich zu sein, dass manche das missverstehen. Ist aus genau diesem Kontext wohl auch die Aussage entstanden, dass man Design Patterns nicht blind vertrauen sollte?