Um Code Smells und ihre Behebung mittels Refactorings geht es in
der einhundertsiebenundvierzigsten Episode des
Anwendungsentwickler-Podcasts. TL;DR Bei meinen Code-Reviews geben
mir Codesmells konkrete Hinweise darauf, welche Stellen ich
überarbeiten sollte. Als IT-Azubi kannst du damit etwa mehrfach
vorhandenen Code oder Methoden mit zu vielen Aufgaben erkennen und
Probleme mit anderen Entwickler:innen präzise besprechen. Mit
passenden Refactorings lässt sich der Code schrittweise verbessern,
während er lauffähig bleibt. Ob du einen Smell behebst, hängt von
seinen Folgen und dem Aufwand ab; eine bewusst beibehaltene Stelle
verdient einen Kommentar, der den Grund erklärt. Kapitelmarken
[00:00:01] Thema: Codesmells und Refactorings [00:00:57] Codesmells
als Hilfe bei Code-Reviews mit IT-Azubis [00:02:04] Refactoring von
Martin Fowler als Grundlage [00:03:30] Was ist ein Codesmell?
[00:04:50] Einen Codesmell bewusst beibehalten [00:05:50] Woher der
Begriff Codesmell kommt [00:07:47] Probleme erkennen und mit
Entwickler:innen besprechen [00:09:38] Codesmells mit Refactorings
beheben [00:10:44] Überblick über die klassischen Codesmells
[00:13:04] Duplicate Code: mehrfach vorhandenen Code zusammenführen
[00:16:17] Comments: verständliche Namen und begründete Kommentare
[00:19:56] Long Method: Methoden auf eine Aufgabe zuschneiden
[00:22:38] Large Class: Aufgaben auf passende Klassen verteilen
[00:24:48] Long Parameter List: Parameter reduzieren oder bündeln
[00:30:42] Wenn ein Refactoring einen anderen Smell erzeugt
[00:32:05] Feature Envy: Methoden zu ihren Daten verschieben
[00:34:01] Data Clumps: zusammengehörige Werte als Objekt abbilden
[00:35:29] DTOs als bewusst einfache Klassen [00:36:27] Primitive
Obsession: fachliche Werte in eigenen Klassen kapseln [00:40:48]
Switch Statements: wiederkehrende Fallunterscheidungen [00:41:22]
Divergent Change und Shotgun Surgery [00:43:12] Parallel
Inheritance Hierarchies [00:43:56] Lazy Class [00:44:32]
Speculative Generality und YAGNI [00:45:31] Temporary Field
[00:46:26] Message Chains und Law of Demeter [00:47:54] Middle Man
[00:48:39] Inappropriate Intimacy [00:49:20] Alternative Classes
with Different Interfaces [00:50:24] Incomplete Library Class
[00:50:54] Data Class [00:51:42] Refused Bequest [00:53:09]
Codesmells in der täglichen Arbeit [00:54:14] Literatur und
weiterführende Links [00:54:43] Kommentare und Feedback Inhalt Was
ist ein Code Smell? Smells sind Indikatoren für Code, der
überarbeitungswürdig ist. Man erkennt sie anhand verschiedener
Muster (z.B. lange Methoden). Die Smells können mit Refactorings
überarbeitet und (hoffentlich) eliminiert werden. Nicht alle Smells
sind immer schlecht. Sie dienen nur als Anhaltspunkt, noch einmal
über den Code nachzudenken. Woher kommt der Name Code Smell? Kent
Becks Oma wird das Zitat "If it stinks, change it." zugesprochen,
das sich auf das Wechseln von Windeln bei Babys bezieht. Kent Beck
hat diese Idee auf Code übertragen: Wenn der Code seltsam "riecht",
sollte man ihn anpassen. Wobei helfen uns Code Smells? Mit Code
Smells können wir Stellen im Code aufdecken, die problematisch
sind, und diese überarbeiten. Dadurch wird der gesamte Code
insgesamt "besser". Die benannten Smells helfen uns durch eine
gemeinsame Sprache bei der Diskussion mit anderen Entwicklern
(ähnlich wie Design Pattern). Was können wir gegen Code Smells tun?
Das Mittel gegen Code Smells sind die Refactorings. Im Buch von
Martin Fowler* gibt es eine übersichtliche Tabelle, welche
Refactorings gegen welche Smells helfen können. Sind Code Smells
immer böse? Code Smells sind nur ein Anhaltspunkt für
Optimierungen. Der Entwickler muss selbst entscheiden, ob der Smell
schlecht ist. Einige Code Smells hängen zusammen und das Auflösen
des einen (z.B. Introduce Parameter Object) führt zur Einführung
eines anderen (z.B. Data Class). Welche Code Smells gibt es?
Duplicate Code Doppelter Code führt bei Änderungen schnell zu
Fehlern, weil zu ändernde Stellen übersehen werden. Refactorings:
Extract Method, Pull Up Method Comments Kommentare können helfen,
den Code zu verstehen, aber häufig sind sie überflüssig und können
durch sprechendere Bezeichner komplett eliminiert werden.
Refactorings: Extract Method, Rename Method Long Method Lange
Methoden sind schwieriger zu verstehen, zu testen und anzupassen.
Refactorings: Extract Method Large Class Zu große Klassen machen
häufig mehr als sie sollen und verletzen das Single Responsibility
Principle. Das macht sie u.a. schwer testbar. Refactorings: Extract
Class, Extract Subclass Long Parameter List Viele Parameter bei
Methoden deuten darauf hin, dass diese zu viele Aufgaben
übernehmen. Sie machen die Methoden schwer testbar und schwer
verständlich. Außerdem müssen die Parameterlisten tendenziell oft
angepasst werden. Refactorings: Replace Parameter with Method,
Introduce Parameter Object Feature Envy Wenn Methoden oder Klassen
sich viele Informationen "besorgen" müssen, bevor sie ihren Job
machen können, ist das ein Zeichen dafür, dass die Komponenten
besser an einer anderen Stelle aufgehoben wären. Refactorings: Move
Method Data Clumps Wenn verschiedene Daten immer zusammen
herumgereicht werden (z.B. Startdatum und Endedatum), ist das ein
Zeichen für eine fehlende Abstraktion (z.B. Zeitraum).
Refactorings: Introduce Parameter Object, Extract Class Primitive
Obsession Die Scheu vor eigenen kleinen Klassen führt oft dazu,
dass doppelter Code entsteht und eine gute Kapselung verhindert
wird. Refactorings: Replace Data Value with Object, Extract Class,
Introduce Parameter Object Switch Statements: Gleiche
Fallunterscheidungen werden häufig an mehreren Stellen benötigt und
führen zu doppeltem Code, der mit Polymorphie verhindert werden
könnte. Divergent Change: Einzelne Klassen müssen aufgrund von
verschiedenen Änderungen angepasst werden. Shotgut Surgery:
Aufgrund einer einzelnen Änderung müssen verschiedene Klassen
angepasst werden. Parallel Inheritance Hierarchies: Sonderform von
Shotgun Surgery, die das parallele Anlegen von Subklassen in
verschiedenen Hierarchien erfordert. Lazy Class: Zu kleine Klassen,
die keinen erkennbaren Mehrwert haben, sollten abgelöst werden.
Speculative Generality: Anstatt alle möglichen zukünftigen
Entwicklungen zu antizipieren, sollte besser das Prinzip You Ain't
Gonna Need It befolgt werden. Temporary Field: Instanzvariablen
sollten nicht nur während der Laufzeit einzelner Methoden verwendet
werden. Message Chains: Objekte, die Objekte aufrufen, die wieder
Objekte aufrufen, wissen zu viel über die fremde Implementierung
und sind damit stark gekoppelt. Das verletzt das Law of Demeter.
Middle Man: Zu viel Delegierung ist auch nicht gut. Inappropriate
Intimacy: Klassen sollten nicht zu viele Details anderer Klassen
kennen. Alternative Classes with Different Interfaces: Gleiche
Dinge sollten auch gleich benannt sein. Incomplete Library Class:
Wenn Librarys nicht alles tun, was wir brauchen, sollten wir sie
ergänzen, anstatt alles neu zu entwickeln. Data Class: Die guten
alten POJOs oder Java Beans. Sie verhindern häufig saubere
Kapselung und haben bei fehlender Geschäftslogik evtl. gar keine
Daseinsberechtigung. Refused Bequest: Wenn Subklassen Teile ihres
Vermächtnisses (geerbte Member) nicht nutzen wollen oder können,
ist vielleicht die Hierarchie falsch gewählt. Literaturempfehlungen
Eine sehr schöne Liste möglicher Code Smells und ihrer Auswirkungen
gibt es im Klassiker Refactoring von Martin Fowler*. * Links
Permalink zu dieser Podcast-Episode RSS-Feed des Podcasts Code
Smells Catalog of Refactorings Refactoring and Design Patterns
Zusammenfassung Codesmells im Code-Review Bei meinen Code-Reviews
mit IT-Azubis helfen mir Codesmells, konkrete Stellen zu erkennen,
die ich überarbeiten sollte. An solchen Mustern kannst du
beispielsweise erkennen, weshalb sich Code schwer lesen lässt oder
beim Testen Probleme macht. Manche fallen schon durch den Umfang
einer Methode auf, andere zeigen sich erst beim Blick auf einzelne
Zeilen. Wenn du die Namen der Smells kennst, kannst du dich mit
anderen Entwickler:innen genauer über den Code austauschen. Ein
Begriff wie Feature Envy beschreibt für jemanden, der ihn kennt,
bereits das betreffende Problem. Ähnlich wie Design Patterns
schaffen Codesmells damit eine gemeinsame Fachsprache. Wann du
einen Smell behebst Bevor ich eine auffällige Stelle ändere, prüfe
ich, welche Folgen sie hat und wie aufwendig es wäre, sie zu
überarbeiten. Je nach Kontext kann es sinnvoll sein, einen Smell
bewusst beizubehalten, etwa wenn der Umbau den Code schwerer
verständlich machen würde. Mit einem Kommentar zum Grund ersparst
du der nächsten Person, dieselbe Frage erneut durchzugehen. Beim
Refactoring überarbeitest du den Code schrittweise und hältst ihn
dabei lauffähig. Für einen Smell kommen oft mehrere Refactorings
infrage. Auch deren Folgen gehören zur Entscheidung: Wenn du etwa
eine lange Parameterliste durch eine Klasse ersetzt, kann dabei
eine Data Class entstehen, deren Aufbau du wiederum prüfen
solltest. Häufige Codesmells und passende Refactorings Duplicate
Code Wenn identischer oder sehr ähnlicher Code an mehreren Stellen
steht, musst du bei einer Änderung jede davon finden. Eine
übersehene Stelle führt dazu, dass Teile des Programms
unterschiedlich arbeiten. Das passiert beispielsweise, wenn mehrere
Switch Statements dieselben Enum-Werte behandeln und ein neuer Wert
hinzukommt. Mit Extract Method ziehst du den gemeinsamen Code in
eine Methode und rufst sie an den betreffenden Stellen auf. IDEs
wie Eclipse können diesen Schritt automatisch ausführen. Mit Pull
Up Method verschiebst du eine gleiche Methode aus mehreren
Subklassen in deren gemeinsame Basisklasse. Comments Bei
Kommentaren, die lediglich den sichtbaren Code beschreiben,
entsteht zusätzlicher Aufwand beim Lesen und Pflegen. Ändert jemand
den Code und übersieht den Kommentar, kann dieser anschließend
etwas Falsches behaupten....
Kommentare (0)
Melde dich an, um einen Kommentar zu schreiben.