Code-Refactoring ist ein Verfahren in der Softwareentwicklung, bei dem die interne Struktur von Softwarecode verändert wird, ohne sein äußeres Verhalten zu ändern oder seine Funktionen zu beeinträchtigen. Diese kleineren Änderungen zielen darauf ab, den Code lesbarer und wartbarer zu machen.
Martin Fowler hat diese Praxis durch sein Buch „Refactoring“ populär gemacht, das erstmals 1999 veröffentlicht wurde. Code-Refactoring kann helfen, sogenannte „Code Smells“ (übersetzt etwa „Codegerüche“) zu beseitigen, die Fowler als „ein oberflächliches Anzeichen, das in der Regel auf ein tiefer liegendes Problem im System hinweist“ definiert. Er fügt hinzu, dass diese Code Smells „schnell zu erkennen oder erschnüffelbar“ sind und nennt lange Methoden und Klassen, die nur Daten und kein Verhalten enthalten, als Beispiele für Code Smells.
Beispiele für das Refactoring von Code sind das Korrigieren falscher Formatierungen, das Umbenennen nicht beschreibender Variablen, das Entfernen doppelter oder nicht verwendeter Funktionen und das Aufteilen großer, langer Methoden in kleinere, besser handhabbare Blöcke. Diese trivialen, verhaltenswahrenden Änderungen führen zwar seltener zu einem Bruch des Codes oder zu Fehlern, aber ihre schrittweise Wirkung kann zu einer Optimierung der Softwareleistung beitragen.
Refactoring mag wie ein einfaches Unterfangen erscheinen. Aber einige Taktiken können Softwareentwicklern zu einem strategischen Ansatz verhelfen:
● Abstraktion
● Zusammensetzung
● Verschieben von Funktionen
● Rot-Grün-Refactoring
● Vereinfachung
Abstraktion ist ein grundlegendes Konzept in der objektorientierten Programmierung. Es beinhaltet die Verallgemeinerung von Objekten, sodass komplexe Details ausgeblendet werden und nur die wesentlichen Informationen übrig bleiben.
Beim Coderefactoring wird die Abstraktion in der Regel für große Codebasen implementiert. Es besteht aus 2 Mechanismen:
Die Pull-Up-Methode zieht Code aus einer untergeordneten Klasse und verschiebt ihn in der Hierarchie nach oben zu einer abstrakten Klasse oder übergeordneten Klasse. Dies ermöglicht eine geringere Code-Duplizierung und eine bessere Wiederverwendbarkeit aller gemeinsam genutzten Attribute oder Funktionen.
● Die Push-Down-Methode verschiebt Code aus einer abstrakten Klasse oder Oberklasse in eine Unterklasse für Logik, die nicht wiederverwendbar ist oder nur für eine bestimmte Unterklasse gilt.
Bei diesem modularen Ansatz werden große Codeblöcke in kleinere zerlegt oder aufgeteilt, um sie einfacher und besser handhabbar zu machen. Die Extraktionsmethode und die Inline-Methode sind 2 Ansätze für die Komposition:
● Der Extraktionsansatz nimmt Teile einer bestehenden Methode und verschiebt sie in eine neue Methode. Dies kann z. B. bei großen Methoden mit verschiedenen Funktionen geschehen, sodass jede Funktion ihre eigene, eigenständige Methode haben kann.
Der Inline-Ansatz ersetzt den Aufruf einer Methode durch den Körper oder Inhalt der Methode selbst, wobei die Methode dann gelöscht wird. Dies gilt in der Regel für Methoden, die nur wenige Codezeilen haben und z. B. nur von einer einzigen Klasse aufgerufen werden.
Bei dieser Technik werden Attribute, Methoden und andere Funktionen zwischen Klassen verschoben, um Abhängigkeiten zu verringern und den Zusammenhalt innerhalb der Funktionen einer Klasse und zwischen den Klassen zu verbessern. Diese Umverteilung trägt zu einem logischeren und ausgewogeneren Design des vorhandenen Codes bei und erleichtert dessen Erweiterung und Pflege.
Red-Green-Refactor lehnt sich an die testgetriebene Entwicklung an, bei der Tests vor dem eigentlichen Quellcode geschrieben werden. Es handelt sich um eine iterative Strategie, die ein kontinuierliches Refactoring und Testen ermöglicht.
Dieser dreistufige Prozess umfasst die folgenden Schritte:
● Während der roten Phase schreiben Entwickler Tests, um ein bestimmtes Softwareverhalten oder eine bestimmte Funktion zu validieren. Diese Tests sollen zunächst fehlschlagen, weil der Code noch nicht erstellt wurde.
● In der grünen Phase schreiben Programmierer den Code für das angegebene Verhalten oder die Funktion. Dies kann der Mindestcode sein, der erforderlich ist, um die Tests zu bestehen, da hier das Ziel Geschwindigkeit vor Qualität ist.
● In der Refactor-Phase schließlich wird der Code verfeinert. Dabei werden alle notwendigen Verbesserungen vorgenommen, um den Code sauberer, klarer und effizienter zu machen, wobei das Verhalten des Codes erhalten bleibt und alle zugehörigen Tests bestanden werden.
Das Ziel besteht darin, den Code und die damit verbundene Logik zu vereinfachen. Dies kann in Form einer Reduzierung der Anzahl von Parametern in einer Methode, der Umbenennung von überlangen Variablen oder Methoden, der Kombination von bedingten Ausdrücken, die zum gleichen Ergebnis führen, der Entkopplung komplexer bedingter Fragmente oder sogar der Verwendung von Polymorphismus anstelle von Bedingungen geschehen.
Stellen Sie sich Code-Refactoring so vor, dass jeden Tag ein Raum aufgeräumt wird, um das Aufräumen am Ende der Woche viel einfacher und schneller zu gestalten. Das Ziel von Code-Refactoring ist es, die technische Verschuldung zu reduzieren, die entsteht, wenn Programmierer Abkürzungen verwenden, z. B. Logik duplizieren, Codierungsstandards nicht befolgen oder unklare Variablennamen verwenden.
Im Folgenden finden Sie einige Vorteile, die Software-Entwicklungsteams aus dem Code-Refactoring ziehen können:
● Verringerte Komplexität
● Verbesserte Wartbarkeit
● Verbesserte Lesbarkeit des Codes
● Schnellere Geschwindigkeit
Refactoring kann zu einfacherem Code führen. Dies hilft Entwicklern, große Codebasen besser zu verstehen. Auch neu eingestellte Programmierer profitieren davon, da sie schnell das Innenleben von unbekanntem Code erfassen können.
Code-Refactoring legt den Grundstein für eine bessere Wartung. Ein klarer Code erfordert weniger Aufwand beim Debugging, der Implementierung einer neuen Funktion, der Aktualisierung bestehender Funktionen oder der Umstellung auf die neuesten Technologien. Wie bei der vorbeugenden Wartung in der Fertigung ermöglicht das Refactoring des Codes jetzt kleinere Korrekturen, um größere Fehler in der Zukunft zu vermeiden.
Wenn Code ein Refactoring durchlaufen hat, ist er sauberer und dadurch leichter zu verstehen und zu bearbeiten. Er ist zudem einfacher zu navigieren, was wiederum zu einer Optimierung des Softwareentwicklungsprozesses beiträgt.
Ein Refactoring hat möglicherweise keine so bedeutenden Auswirkungen wie tatsächliche Codeoptimierungen, die auf die Leistung abzielen. Einfacherer, weniger sperriger Code kann jedoch dennoch zu effizienterer Software und schnelleren Laufzeit beitragen.
Refactoring kann zu klarem und sauberem Code führen, aber das Verfahren ist nicht ohne Nachteile. Hier sind einige Herausforderungen, auf die Entwicklungsteams beim Refactoring von Code stoßen können:
● Zuweisung von Entwicklern
● Einführen von Fehlern
● Altlast-Code
● schleichende Ausweitung des Umfangs
● Zeitliche Einschränkungen
Die Teams müssen entscheiden, wer am Code-Refactoring-Prozess teilnimmt und welche Aufgaben und Verantwortlichkeiten sie haben. Dies kann dazu führen, dass Programmierer von wichtigen Softwareentwicklungsaufgaben abgezogen werden – ein Kompromiss, den sich kleinere Teams möglicherweise nicht leisten können.
Selbst die kleinste Codeänderung birgt das Risiko, dass ein neuer Fehler eingeführt wird oder ein vorhandener Fehler wieder auftaucht. Bei einer komplexeren Code-Überarbeitung besteht auch die Möglichkeit, Features und Funktionen zu beschädigen oder zu verändern.
Altlast-Code bezieht sich auf alte Codebasen, die noch ihren Zweck erfüllen, aber mit veralteten Technologien entwickelt wurden und nicht mehr aktiv unterstützt oder gewartet werden. Beim Refactoring kann es zu Abhängigkeits- und Kompatibilitätsproblemen kommen. Dies erfordert eine gründlichere Codeanalyse und einen detaillierten Plan, um alle den Altlast-Code betreffenden Änderungen vorzunehmen.
Es kann verlockend sein, mehr als nötig zu reparieren, vor allem, wenn kein Plan vorhanden ist oder keine klaren Ziele festgelegt wurden. Insbesondere bei der logischen Umstrukturierung kann sich der Umfang ausweiten, wenn die Programmierer sich keine Zeit für die Untersuchung des Codes und die Ermittlung der verbesserungswürdigen Bereiche genommen haben.
Das Code-Refactoring kann viel Zeit in Anspruch nehmen, die den meisten Entwicklungsteams fehlt. Sie müssen die Notwendigkeit des Refactorings mit der Einhaltung der Projektfristen in Einklang bringen und abwägen, wann und wie viel überarbeitet werden soll.
Bevor Sie sich auf den Weg zum Code-Refactoring machen, sollten Sie die folgenden Tipps beachten, um die Herausforderungen bei diesem Prozess zu meistern:
● Das Timing ist wichtig
● Planung ist entscheidend
● Analysieren und standardisieren
● Testen und dokumentieren
Der Zeitpunkt für das Refactoring von Code ist ebenso wichtig wie das Warum oder Wie. Es kann Teil der regelmäßigen Wartungsaktivitäten eines Software-Entwicklungsteams sein oder in Code-Reviews integriert werden.
Das Refactoring ist auch ein Muss, bevor neue Funktionen hinzugefügt, umfangreiche Updates implementiert, auf neuere Stacks umgestellt oder Programmierschnittstellen (APIs) oder Bibliotheken aktualisiert werden. Sie schafft einen skalierbaren und anpassungsfähigeren Framework, auf dem in Zukunft aufgebaut werden kann.
Das Code-Refactoring kann zeitaufwändig sein, was eine entsprechende Planung voraussetzt. Entwicklungsteams müssen ihre Ziele und den Umfang berücksichtigen. Sie können in kleinen Schritten vorgehen und sich ein paar Tage lang auf winzige Änderungen wie das Löschen von totem Code, die Korrektur von Formatierungen oder das Entfernen von Duplikaten konzentrieren. Wenn es sich um eine umfangreichere Bereinigung handelt, dann wird das Refactoring zu einem Projekt mit Fristen und einem längeren Zeitrahmen.
Einfache Refactoring-Aufgaben erfordern vielleicht nicht viel Analyse. Bei Techniken, die sich auf die Logik beziehen, ist es jedoch unerlässlich, den gesamten zugehörigen Code zu verstehen. Die Ermittlung des Grundprinzips hinter der Codestruktur kann Programmierern zu fundierteren Entscheidungen und gezielteren Änderungen verhelfen.
Auch die Befolgung der Codierungsstandards und Designprinzipien eines Teams kann die Integrität bewahren und die Architektur der Codebasis beibehalten.
Beim Refactoring geht es nicht nur um die Verbesserung des Codes, sondern auch um die Verbesserung des Codes. es geht auch darum, dafür zu sorgen, dass diese Verbesserungen funktionieren. Deshalb sind Tests wichtig, um zu bestätigen, dass die Software selbst und ihr Verhalten intakt bleiben.
Die Entwickler können zwar ihre eigenen Integrations- und Unit-Tests durchführen, aber die Einbeziehung des QA-Teams ist entscheidend. Sie können funktionale Tests zur Überprüfung von Funktionen durchführen sowie Regressionstests, um zu prüfen, ob der umstrukturierte Code keine Fehler einführt oder Funktionen beeinträchtigt.
Auch die Dokumentation von Änderungen muss Teil des Prozesses sein. Dies erleichtert die Nachverfolgung von Änderungen und ermöglicht ein reibungsloseres Code-Refactoring in der Zukunft.
Mehrere Tools können dabei helfen, die Code-Refaktorierung zu beschleunigen und zu automatisieren. Hier sind einige beliebte:
● Integrated Development Environment (IDE)
● Statische Code-Analysatoren
● Weitere Ressourcen
Viele der heutigen IDEs verfügen bereits über eine integrierte Unterstützung für automatisiertes Refactoring, ohne dass Code beschädigt oder Fehler eingeführt werden. Einige bieten sogar KI-gestützte Refactoring-Empfehlungen.
Zu den IDEs, die für das Code-Refactoring verwendet werden können, gehören IntelliJ IDEA für Programmiersprachen, die auf der Java Virtual Machine (JVM) basieren, PyCharm für Python und die ReSharper Visual Studio-Erweiterung für C#, C++ und .NET.
Statische Analysatoren bewerten den Code, ohne ihn auszuführen. Diese Analysatoren erkennen häufige Programmierfehler und Probleme mit der Codequalität und ermöglichen den Entwicklern, diese frühzeitig im Softwareentwicklungsprozess zu beheben.
Beispiele für statische Codeanalysatoren sind Codacy und das Open-Source-PMD, die beide mehrere Programmiersprachen unterstützen, JArchitect für Java, NDepend für .NET und den RuboCop Linter and Formatter für Ruby.
Refactoring.com ist die Website von Martin Fowler, die einen Online-Katalog mit Refactoring-Methoden aus seinem Buch enthält. Refactoring.Guru ist eine weitere Website, auf der Refactoring-Techniken und Designmuster besprochen werden.
Künstliche Intelligenz (KI) kann beim Code-Refactoring-Prozess helfen. Generative KI-Anwendungen basieren auf großen Sprachmodellen (Large Language Models, LLMs), die komplexe oder große Codebasen analysieren und die Semantik und den Kontext dahinter verstehen können. Auf dieser Grundlage liefern sie umgehend Refactoring-Empfehlungen in Echtzeit.
IBM® watsonx Code Assistant nutzt beispielsweise IBM® Granite-Modelle, um Fehler und verbesserungswürdige Bereiche zu identifizieren. Anschließend schlägt es gezielte Korrekturen vor, die mit den etablierten Codierungskonventionen eines Teams übereinstimmen und so das Refactoring von Code vereinfachen und beschleunigen. Andere ähnliche KI-Refactoring-Tools sind Amazon CodeGuru Reviewer, GitHub Copilot und ChatGPT von OpenAI.
Für diejenigen, die mit Altlast-Code arbeiten, kombiniert IBM watsonx Code Assistant for Z generative KI und Automatisierung, um Entwickler bei der Modernisierung ihrer Anwendungen zu unterstützen. Der watsonx Code Assistant for Z Refactoring Assistant ermöglicht es Programmierern, ihre Anwendung in modularere und wiederverwendbare Dienste umzuwandeln. Es verwendet Code-Analysealgorithmen zur Modernisierung von COBOL-Anwendungen.
Wie bei jedem KI-System müssen die Entwickler die Ergebnisse der KI-gestützten Code-Refactoring-Tools auf ihre Genauigkeit hin überprüfen. Zudem sind Tests erforderlich, um sicherzustellen, dass alle vorgeschlagenen Änderungen wie erwartet funktionieren.
Instana vereinfacht Ihre Cloud-Migration durch umfassende Überwachung und umsetzbare Erkenntnisse.
Nutzen Sie generative KI für eine beschleunigte und vereinfachte Modernisierung von Mainframe-Anwendungen.
Optimieren Sie Legacy-Anwendungen mit Hybrid Cloud und KI-gestützten Modernisierungsservices und -strategien.