Rechtzeitig und regelmäßig den Quellcode aufräumen Refactoring-Prozesse und Werkzeuge zur Code-Pflege

Ein Gastbeitrag von Dr. Veikko Krypczyk & Elena Bochkor * 8 min Lesedauer

Anbieter zum Thema

Ein sorgfältig gepflegter Quellcode ist eine solide Grundlage für eine kontinuierliche Entwicklung des Anwendungssystems. In der Fachwelt bezeichnet man diesen Prozess der Qualitätssicherung als Refactoring. Dies dient dem Zweck, technische Schulden zu vermeiden und abzubauen.

Funktionen des Refactoring-Tools Visual Assist in Visual Studio.
Funktionen des Refactoring-Tools Visual Assist in Visual Studio.
(Bild: Krypczyk & Bochkor / Microsoft)

Das Ziel von Refactoring besteht vor allem darin, Redundanzen und Unzulänglichkeiten im Quellcode zu beseitigen. Erste, einfache und leicht umsetzbare Maßnahmen der Verbesserung sind eine Überarbeitung der Benennung von Klassen, von Methoden und anderen Objekten. Weiterführende Maßnahmen zielen auf eine Optimierung der Quellcodestrukturen.

Während des Refactoring-Prozesses ist es entscheidend, dass die Funktionalität des Quellcodes dabei unverändert bleibt. Das bedeutet, dass der Code nach dem Refactoring die gleichen Ergebnisse liefern muss, wie vor dem Prozess der Bereinigung und Optimierung. Um dies zu erreichen, werden die Aufgaben des Refactoring i.d.R. in kleinen Schritten durchgeführt.

Idealerweise erfolgt dieser Prozess regelmäßig und ist Teil des normalen Entwicklungsprozesses. Jeder Schritt muss sorgfältig und detailliert genug durchgeführt werden, dass sichergestellt werden kann, dass keine unerwünschten Nebeneffekte auftreten. Mit anderen Worten: Es ist unbedingt zu vermeiden, dass nach der Verbesserung und Optimierung des Quellcodes zwar dessen Struktur und Lesbarkeit erhöht ist, aber (neue) Fehler in die Software gekommen sind.

Um dies sicherzustellen, sind umfangreiche Tests – im Idealfall automatisiert – nach jedem abgeschlossenen Refactoring-Prozess durchzuführen. Durch ein umfassendes Refactoring sollten beispielsweise sämtliche nicht benötigte Codeabschnitte entfernt werden. Das Prinzip lautet: „Remove dead Code“. Bereits durch die Neubenennung von Variablen und Funktionen können einige Verbesserungen erzielt werden.

Variablen, Methoden, Funktionen usw., die weniger treffend benannt sind, beeinträchtigen den Lesefluss und das Verständnis des Quellcodes. Im Verlauf des Refactoring-Prozesses ist es wichtig, „nichtssagende“ Bezeichnungen zu überarbeiten und anzupassen, damit jede Variable oder Funktion genau das tut, was der Leser vom Namen erwartet.

Ein Abschnitt mit vielen Variablen und anderen Bezeichnern erschwert den Überblick und das Verfolgen des Leseflusses. Übermäßig komplexe Verzweigungen und stark verschachtelte Schleifen sind schwer lesbar und führen zu Verwirrung. Daher sollte man sich bemühen, komplizierte Strukturen im Quellcode zu zerlegen und zu vereinfachen, um sicherzustellen, dass der Code für den Leser verständlich und nachvollziehbar ist. Zusätzlich ist es sinnvoll, die Sichtbarkeit aller Variablen auf das absolut Notwendige zu beschränken, um die Wahrscheinlichkeit von Seiteneffekten zu reduzieren.

Im Kontext des Refactoring wird oft von „Code-Smells" gesprochen. Der Begriff beschreibt funktionierenden, jedoch schlecht strukturierten Quellcode. Eine undurchsichtige Codestruktur ist nicht nur schwer verständlich, sondern auch anfällig für Fehler. Es gibt zwei Hauptkategorien von Code-Smells: Klassenübergreifende und klasseninterne Code-Smells.

Beispiele für klassenübergreifende Code-Smells sind parallele Vererbungshierarchien oder alternative Klassen, die zwar dasselbe tun, jedoch an verschiedenen Schnittstellen agieren. Klasseninterne Code-Smells beziehen sich unter anderem auf umfangreiche Parameterlisten, temporäre Felder, kommentarlose Funktionen, Code-Duplikate, lange Methoden usw. Das Ziel des Refactoring besteht darin, diese Code-Smells zu eliminieren und somit für einen verbesserten „Geruch" des Quellcodes zu sorgen.

Das alles sind Beispiele für Unzulänglichkeiten im Quellcode. Es ist trotz umfassender Erfahrungen nicht möglich, sofort einen „perfekten“ Quellcode zu schreiben. Überarbeitungen und Qualitätsverbesserungen sind stets angezeigt und führen zur fortlaufenden Notwendigkeit eines Refactorings.

Refactoring-Werkzeuge im Überblick

Ohne gute Werkzeugunterstützung ist ein Refactoring komplexer Projekte nicht effizient machbar. Einige Refactoring-Funktionen sind bereits in den integrierten Entwicklungsumgebungen (IDE) enthalten. Diese genügen i.d.R. für Basisaufgaben, wie beispielsweise eine Umbenennung von Variablen.

Es gibt jedoch auch spezielle eigenständige Tools bzw. Plug-ins und Extensions, welche in Entwicklungsumgebungen integriert werden können. Diese erweitern den Funktionsumfang und ermöglichen ein schnelleres Vorgehen bei der Überarbeitung des Quellcodes. Dabei unterstützen sie nicht nur den Prozess der Umsetzung, sondern sie sind auch bei der Analyse des Quelltextes hilfreich.

Refactoring-Werkzeuge variieren je nach Programmiersprache, Plattform und spezifischen Anforderungen. Viele IDEs bieten eingebaute Refactoring-Funktionen, beispielsweise IntelliJ IDEA, Eclipse, Visual Studio und NetBeans (siehe Tabelle).

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Softwareentwicklung und DevOps

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung
IDE
Beschreibung
Visual Studio
https://visualstudio.microsoft.com/de/
 
Dabei handelt es sich um eine beliebte IDE für .NET-Entwicklung und bietet
umfassende Refactoring-Werkzeuge für C# und andere .NET-Sprachen. Es
unterstützt Operationen wie Umbenennen, Extrahieren von Methoden, Umordnen
von Parametern usw.
IntelliJ IDEA
https://www.jetbrains.com/idea/
 
Eine beliebte integrierte IDE für Java-Entwicklung, die eine Vielzahl von
Refactoring-Funktionen bietet. Das Tool unterstützt zahlreiche
Refactoring-Operationen wie Umbenennen, Extrahieren von Methoden, Verschieben
von Codeblöcken usw.
Eclipse
https://www.eclipse.org/
 
Das ist eine weit verbreitete Java-IDE, die umfangreiche Unterstützung für
Refactoring bietet. Es enthält Funktionen wie Umbenennen, Extrahieren von
Methoden, Umstrukturieren von Code und viele andere.
NetBeans
https://netbeans.apache.org/
 
Diese Java-IDE stellt auch Refactoring-Werkzeuge bereit. Ähnlich wie IntelliJ IDEA
und Eclipse bietet NetBeans Funktionen wie Umbenennen, Extrahieren von
Methoden, Umstrukturieren von Code und andere Refactoring-Optionen.
 

Neben den eingebauten Funktionen für das Refactoring in den IDEs gibt es auch Erweiterungen bzw. Plug-ins, welche die IDEs um solche Funktionen ergänzen und so genannte Standalone-Refactoring-Tools, die unabhängig von einer bestimmten IDE arbeiten. Die Integration in eine IDE ist grundsätzlich eine sehr gute Lösung, denn die Überarbeitung des Quellcodes sollte regelmäßig stattfinden und ein Teil der Programmierung (Implementierung) der Software werden.

Beispielsweise ist ReSharper von JetBrains ein leistungsstarkes Refactoring-Tool für die .NET-Entwicklung, speziell für die Integration in Visual Studio. Weitere Refactoring-Werkzeuge sind auf bestimmte Programmiersprachen spezialisiert. Dazu gehört beispielsweise Visual Assist, https://www.wholetomato.com/, welches für eine Verbesserung der Codierungsqualität von Quellcode in den Programmiersprachen C++ und C# verwendet werden kann.

Andere Tools konzentrieren sich auf die vorausgehende Analyse des Quellcodes, bevor man versucht, diesen zu optimieren. Dazu zählt beispielsweise das Werkzeug SonarQube. Das ist ein statisches Analysewerkzeug, das auch Code-Smells identifizieren kann. Es unterstützt Entwickler dabei, Qualitätsprobleme im Code zu erkennen und zu beheben. Zeigen wir jetzt die Arbeit mit einem konkreten Tool. Dabei geht es insbesondere auch um die Unterstützung der Codequalität für C++ und C# bei der Entwicklung von Games mit den Spiele-Engines Unreal (C++) und Unity (C#).

Optimierung von C++ und C#-Code mit Visual Assist

Integration von Visual Assist als Extension in Visual Studio 2022.
Integration von Visual Assist als Extension in Visual Studio 2022.
(Bild: Krypczyk & Bochkor / Microsoft)

Visual Assist ist ein Plug-in für Microsoft Visual Studio und erweitert die Funktionalitäten der integrierten Entwicklungsumgebung. Dieses Tool bietet vielfältige Funktionen, um die Produktivität von Entwicklern in den Sprachen C, C++ und C# zu steigern. Die nahtlose Integration als Plug-in in Visual Studio umfasst die Erweiterung der Benutzeroberfläche um einen eigenen Menüpunkt und eine zusätzliche Symbolleiste.

Die Refactoring-Funktionen können präzise an die Anforderungen des Refactoring-Prozesses angepasst werden, wobei ein umfassender Optionsdialog den Entwickelnden die Möglichkeit gibt, gezielt auszuwählen, welche Unterstützung sie benötigen. Insbesondere in Entwicklungssituationen, in denen nicht alle Features erforderlich sind oder einige sogar die integrierten Funktionen von Visual Studio ersetzen können, ist es entscheidend, dass Developer frei entscheiden können, welchen Support und welches Werkzeug sie bevorzugen.

Funktionen des Refactoring-Tools Visual Assist in Visual Studio.
Funktionen des Refactoring-Tools Visual Assist in Visual Studio.
(Bild: Krypczyk & Bochkor / Microsoft)

Visual Assist bietet eine breite Palette von Funktionen über ein eigenes Menü und Unterstützungsbereichen, die sich wie folgt zusammenfassen lassen:

  • Suche und Navigation: Schnelle Navigation im Quellcode durch intelligente Verknüpfungen und kontextsensitives Springen.
  • Refactoring: Automatisierte Tools zum Umstrukturieren und Optimieren von Code.
  • Code-Generierung: Generierung von Code-Snippets und automatisches Vervollständigen von Code.
  • Code-Assistenz: Intelligente Vorschläge während der Codeeingabe zur Steigerung der Effizienz.
  • Code-Verständnis: Verbessertes Verständnis des Codes durch die Anzeige von Zusammenhängen und Strukturen.
  • Code-Korrektur: Automatische Fehlerkorrektur und Anpassung an Coding-Standards.
  • Code-Inspektion (nur für C/ C++): Detaillierte Inspektion des Codes auf mögliche Fehlerquellen und Verbesserungspotenzial.
  • Code-Snippets: Vordefinierte Code-Snippets für häufig verwendete Muster und Strukturen.

Ein Schwerpunkt von Visual Assist liegt auf der Suche und Navigation im Quellcode, wobei Funktionen wie „FIND BY CONTEXT“ und „FIND REFERENCES“ es Entwicklern und Entwicklerinnen ermöglichen, effizient nach Verweisen auf Symbole und Bezeichner im Quelltext zu suchen und deren Verwendung nachzuverfolgen.

Refactoring in besonderen Situationen

Das Refactoring von Quellcode wird dann komplizierter, wenn umfassende Bibliotheken und Frameworks zum Einsatz kommen. Das gilt insbesondere dann, wenn dadurch der Umfang der Programmiersprache um eigene Schlüsselwörter, Klassennamen und andere Bezeichner ergänzt wird. In diesem Fall kommt ein Tool an seine Grenzen, wenn es lediglich die Syntax der Programmiersprache als Referenz zu Grunde legt.

Auch hier gibt es spezielle Lösungen. Am Beispiel der Spieleentwicklung soll dieses demonstriert werden. Bei der Spieleentwicklung kommen sehr häufig die Spiele-Engines Unreal und Unity zum Einsatz. Eine Vielzahl von Spielen aller Genres wird mit Hilfe dieser Tools erstellt. Als Programmiersprache verwendet die Unreal Engine C++, bei Unity kommt C# zum Einsatz.

Visual Assist bietet in der aktuellen Version eine spezielle Unterstützung für beide Spiele-Engines. Im Fall der Unreal Engine umfasst dies beispielsweise die Unterstützung für bestimmte Schlüsselwörter, Präprozessor-Makros und das Einrichten der Lösung (Solution Setup). Die Bandbreite dieser Unterstützung kann über ein eigenes Dialogfeld konfiguriert werden.

Um die Funktionalität des Tools bei der Arbeit mit C++-Code und der Verwendung der Unreal Engine besser zu verstehen, sind möglicherweise die folgenden Erläuterungen hilfreich. Die Unreal Engine erleichtert das Schreiben von Quellcode für wiederkehrende Funktionen mithilfe von Makros erheblich. Die Kompilierung eines Unreal C++-Projekts erfolgt in zwei Phasen.

Unterstützung von speziellen Schlüsselwörtern und Datentypen der Unreal Engine.
Unterstützung von speziellen Schlüsselwörtern und Datentypen der Unreal Engine.
(Bild: Krypczyk & Bochkor / Microsoft)

Während der ersten Phase liest das UnrealHeaderTool (UHT) die C++-Header-Dateien, um Unreal-Makros zu identifizieren und den erforderlichen Code zu generieren, der die Makros ersetzt. In der zweiten Phase kompiliert der C++-Compiler den resultierenden Code. Typische Makros tragen Bezeichner wie UCLASS, USTRUCT, UPROPERTY, UFUNCTION, UENUM, UDELEGATE, GENERATED_UCLASS_BODY usw. Ein Refactoring-Tool kann nur dann sinnvoll eingesetzt werden, wenn es diese spezifischen Spracherweiterungen in der Analyse aufgreift.

Das, was die Unreal-Engine für C++-Developer ist, das ist die Unity-Engine für C#-Developer. Visual Assists unterstützt seit dem Build 2023.4 die Engine Unity, d.h. es wird der explizite Support damit für die Syntax und Schlüsselwörter dieser Spiele Engine für C#-Entwickler aufgenommen. Entwicklerinnen und Entwickler können sukzessive auf die folgenden Grundfunktionen in Visual Assist im Zusammenspiel mit Unity zurückgreifen: verfeinerte Navigation, intelligente Autovervollständigung und Code-Refactoring. Als erste spezifische Funktion wird die Implementierung von Shadern unterstützt.

Fazit

Zusammenfassend lässt sich sagen, dass Refactoring ein kritischer Bestandteil des Software-Entwicklungsprozesses ist, der darauf abzielt, die Qualität und Wartbarkeit von Code zu verbessern, ohne die ursprüngliche Funktionalität zu beeinträchtigen. Insgesamt trägt Refactoring dazu bei, einen gesunden und nachhaltigen Code zu schaffen, der den Anforderungen der Softwareentwicklung gerecht wird und es Developern ermöglicht, effektiv und effizient zu arbeiten. Es ist ein integraler Bestandteil der Softwareentwicklung, der langfristig zur Qualität und Langlebigkeit von Softwareprojekten beiträgt.

* Über die Autoren
Dr. Veikko Krypczyk ist Softwareentwickler, Trainer und Fachautor und u.a. auf die Themen Mobile Development, WinUI 3 und .NET MAUI spezialisiert. Sein Wissen gibt er über Fachartikel, Seminare und Workshops gern an Interessierte weiter und steht mit seiner Expertise auch für eine individuelle Unterstützung in Projekten zur Verfügung. Elena Bochkor arbeitet primär am Entwurf und Design mobiler Anwendungen und Webseiten. Weitere Informationen zu den Autoren unter Larinet.com.

(ID:49869844)