Code-Smells sind keine Bugs. Ein fehlerhaftes Programm stürzt ab, liefert falsche Ergebnisse oder besteht einen Test nicht. Ein Programm mit Code-Smells kann jahrelang einwandfrei laufen, doch jede Änderung kostet mehr als nötig, jede neue Funktion birgt unerwartete Risiken und jeder Refactoring-Versuch deckt Abhängigkeiten auf, von denen niemand wusste, dass sie existieren. Code-Smells sind die strukturellen Merkmale von Code, die zukünftige Probleme vorhersagen: Sie verursachen keinen sofortigen Absturz, machen aber jede zukünftige Änderung schwieriger, langsamer und riskanter als nötig.
Der Begriff wurde durch Martin Fowler und Kent Beck in Fowlers Werk populär gemacht. Refactoring: Verbesserung des Designs vorhandenen Codes (1999), in dem 22 Code-Smells katalogisiert und jeweils einer entsprechenden Refactoring-Technik zugeordnet wurden. Dieser Katalog gilt weiterhin als Standardwerk, und die von Fowler benannten Smells – Long Method, God Class, Duplicated Code, Feature Envy, Divergent Change, Shotgun Surgery und andere – finden sich heute branchenweit in SonarQube-Regelsätzen, statischen Analysetools und Checklisten für Code-Reviews wieder.
Code-Smells beseitigen
SMART TS XL hilft, sie in komplexen Systemen abzubilden und zu beheben.
Mehr InfosWas ist ein Code-Geruch?
Ein Code-Smell ist ein oberflächliches Merkmal von Quellcode, das auf ein tieferliegendes Struktur- oder Designproblem hindeutet. Der Code lässt sich kompilieren, besteht die Tests und erzeugt korrekte Ausgaben, aber seine Struktur erschwert das Lesen, Erweitern und sichere Modifizieren. Fowlers Definition lautet: „Ein oberflächliches Anzeichen, das üblicherweise einem tieferliegenden Problem im System entspricht.“
Code-Smells sind keine Verstöße im selben Sinne wie Syntaxfehler oder fehlgeschlagene Assertions. Sie sind Indikatoren, Muster, die erfahrene Entwickler als Warnsignale erkennen, selbst wenn kein unmittelbarer Fehler sichtbar ist. Die Gefahr besteht darin, dass sie sich kumulativ auswirken: Eine einzelne lange Methode in einer 10,000 Zeilen umfassenden Codebasis ist eine geringfügige Unannehmlichkeit. Hunderte langer Methoden, redundante Logik, verteilt auf Dutzende von Modulen, und zentrale Klassen im Abhängigkeitsdiagramm ergeben ein System, das sich nur schwer sicher ändern lässt.
Code-Gerüche vs. Bugs vs. Technische Schulden
Diese drei Konzepte sind zwar verwandt, aber dennoch unterschiedlich, und ihre Verwechslung führt zu einer falschen Priorisierung:
| Konzept | Definition | Sofortiges Versagen? | Wie findet man |
|---|---|---|---|
| Fehler | Code, der zu fehlerhaftem Verhalten führt | Ja, die Tests schlagen fehl, Benutzer melden Fehler. | Testen, Überwachen, Fehlerprotokolle |
| Geruchscode | Strukturmuster, das zukünftige Probleme vorhersagt | Nein, der Code läuft korrekt. | Code-Review, statische Analyse |
| Technische Schulden | Die angehäuften Kosten vergangener Abkürzungen und schlechter Entscheidungen | Nein, aber sie summieren sich im Laufe der Zeit | Kennzahlen, Komplexitätsanalyse, Aufwandsschätzungen für Refactoring |
Code-Smells sind der Mechanismus, durch den sich technische Schulden anhäufen. Jede dem Code hinzugefügte lange Methode stellt eine Einheit technischer Schulden dar; ihre „Zinszahlung“ besteht in der zusätzlichen Zeit, die jeder zukünftige Entwickler aufwendet, um sie zu verstehen, und in der Zeit, die jede zukünftige Änderung benötigt, um die Nebenwirkungen ihrer Größe zu vermeiden.
Was ist ein Code-Smell in SonarQube?
SonarQube klassifiziert Code-Probleme in drei Kategorien: Bugs (definitiv falsch), Schwachstellen (Sicherheitsprobleme) und Code riecht (Wartungsprobleme). Die Code-Smells von SonarQube entsprechen direkt Fowlers Katalog und umfassen Regeln für lange Methoden (über konfigurierbaren Zeilenschwellenwerten), doppelte Blöcke, zu viele Parameter, komplexe kognitive Komplexitätswerte, fehlende Fehlerbehandlung und Verletzungen der Architekturkopplung. Die Code-Smell-Regeln in SonarQube sind die branchenweit am weitesten verbreitete automatisierte Operationalisierung von Fowlers ursprünglicher Taxonomie.
Martin Fowlers Code Smells: Die klassische Taxonomie
Fowlers ursprüngliche 22 Code-Smells, nach Kategorien geordnet, gelten weiterhin als Standardreferenz. Die Regelsätze aller wichtigen statischen Analysetools basieren auf dieser Taxonomie.
| Kategorie | Code riecht |
|---|---|
| Blähungen, Code, der zu einer unhandlichen Größe angewachsen ist | Lange Methode, große Klasse, primitive Besessenheit, lange Parameterliste, Datenklumpen |
| ObjektorientierungsmissbraucherMissbrauch von OO-Prinzipien | Switch-Anweisungen, temporäres Feld, abgelehntes Vermächtnis, alternative Klassen mit unterschiedlichen Schnittstellen |
| VeränderungsverhindererVeränderungen erschweren | Divergente Veränderung, Schrotflintenchirurgie, parallele Vererbungshierarchien |
| Verbrauchsmaterialienunnötiger Code | Kommentare (übermäßig), doppelter Code, verzögerte Klassen, Datenklassen, toter Code, spekulative Allgemeinheit |
| Kupplerübermäßige Kopplung | Neid auf Vorteile, unangemessene Intimität, Nachrichtenketten, Mittelsmann |
Zu wissen, zu welcher Kategorie ein Code-Geruch gehört, hilft bei der Priorisierung der Behebung: Bloater und Change Preventer korrelieren direkt mit hohen Refactoring-Kosten; Coupler korrelieren direkt mit architektonischer Fragilität; Dispensables lassen sich am sichersten entfernen.
Die häufigsten Code-Smells: Kurzübersicht
| Code-Geruch | Wie es aussieht | Primäres Risiko |
|---|---|---|
| Doppelter Code | Dieselbe Logik taucht an mehreren Stellen auf. | Fehlerbehebungen müssen überall angewendet werden; Kopien weichen im Laufe der Zeit voneinander ab |
| Lange Methode | Methoden mit mehr als 20-30 Zeilen und mehreren Verantwortlichkeiten | Hohe kognitive Belastung; isoliertes Verhalten schwer zu testen |
| Gottklasse / Große Klasse | Eine Klasse, die alles kann | Jede Funktionsänderung betrifft dieselbe Klasse; Zusammenführungskonflikte, Anfälligkeit |
| Lange Parameterliste | Methoden, die 4 oder mehr Parameter benötigen | Es ist leicht, falsche Werte zu übergeben; Anrufstellen sind schwer lesbar. |
| Feature-Neid | Eine Methode, die die Daten einer anderen Klasse stärker nutzt als ihre eigenen. | Enge Kopplung; eine Veränderung in der einen Klasse führt zum Zusammenbruch der anderen. |
| Divergente Veränderung | Eine Klasse, die aus vielen verschiedenen Gründen modifiziert wurde | Verstößt gegen die Einzelverantwortung; unvorhersehbare Nebenwirkungen |
| Schrotflintenchirurgie | Eine einzige Änderung erfordert Anpassungen in vielen Klassen. | Hohe Änderungskosten; leicht eine Instanz zu übersehen |
| Toter Code | Code, der nie aufgerufen oder erreicht wird | Verwirrt Entwickler; sammelt sich über Jahre an; erschwert die Migration |
| Primitive Besessenheit | Verwendung von Basistypen (Zeichenketten, Ganzzahlen) anstelle von Domänenobjekten | Validierung überall verstreut; mangelnde Ausdruckskraft |
| Datenklumpen | Dieselbe Gruppe von Feldern wurde wiederholt gemeinsam durchlaufen. | Sollte ein Domänenobjekt sein; signalisiert fehlende Abstraktion |
| Spekulative Allgemeinheit | Code, der für imaginierte zukünftige Bedürfnisse geschrieben wurde | Unnötige Komplexität; niemand versteht, warum es da ist. |
| Inkonsistente Fehlerbehandlung | Stille Fangfragen, unterschiedliche Ausnahmestrategien | Fehler bleiben unentdeckt; die Fehlersuche dauert viel länger |
Definitionen und Beispiele für Code-Smells
Doppelter Code
Der häufigste und kostspieligste Code-Geruch in großen Systemen. Duplikation entsteht durch Copy-Paste-Entwicklung, Zeitdruck und Teams, die isoliert voneinander arbeiten und unabhängig voneinander dasselbe Problem lösen. Die unmittelbare Folge ist ein erheblicher Wartungsaufwand: Jede Änderung an gemeinsam genutzter Logik muss auf jede Kopie angewendet werden.
Java
// ServiceA -- discount calculation
double calculateDiscount(double amount) {
if (amount > 1000) return amount * 0.1;
return 0;
}
// ServiceB -- same logic, copied and forgotten
double computeDiscount(double value) {
if (value > 1000) return value * 0.1;
return 0;
}
Wenn sich die Geschäftsregel ändert (Schwellenwert auf 1500, Rate auf 12 %), wird eine Kopie aktualisiert, die andere jedoch nicht. Zwei Module stimmen nun in der grundlegenden Geschäftslogik nicht mehr überein, und die Diskrepanz tritt erst im Produktivbetrieb bei einem Audit und nicht beim Testen zutage.
Fixieren: Die gemeinsame Logik wird in eine einzelne Funktion, Hilfsklasse oder gemeinsam genutzte Bibliothek ausgelagert, auf die beide Aufrufer verweisen.
Lange Methode
Eine Methode, die im Laufe der Zeit durch die Übernahme zusätzlicher Aufgaben über ihren ursprünglichen Zweck hinausgewachsen ist. Die kognitive Belastung beim Lesen einer 200-zeiligen Methode unterscheidet sich qualitativ von der beim Lesen von zwanzig 10-zeiligen Methoden, nicht nur quantitativ. Lange Methoden sind schwer zu testen, da sie zu viele Aspekte umfassen, um sie isoliert zu prüfen, und schwer zu verstehen, da der Leser den gesamten Ausführungskontext im Arbeitsgedächtnis behalten muss.
NachweisschwelleMethoden mit mehr als 20–30 Zeilen sollten überprüft werden; ab 50 Zeilen ist eine Refaktorisierung fast immer gerechtfertigt. In COBOL entspricht dies Absätzen mit mehr als 100 Anweisungen.
python
class OrderProcessor:
def process_order(self, order):
# Validate order -- 40 lines
# Calculate discounts -- 30 lines
# Update inventory -- 25 lines
# Send notification emails -- 20 lines
# Generate invoice -- 35 lines
# 150+ lines total
pass
Jede Aufgabe in dieser Methode sollte eine separate Klasse oder Funktion sein. Die Zusammenfassung dieser Aufgaben birgt das Risiko, dass jede zukünftige Aktualisierung der Rechnungsstellung, des Lagerbestands oder der Benachrichtigungen den gesamten Auftragsabwicklungsprozess destabilisiert.
Gottklasse
Eine Klasse, die Verantwortlichkeiten über mehrere Bereiche hinweg angehäuft hat und dabei das Prinzip der Einzelverantwortung so schwerwiegend verletzt, dass sie zum Mittelpunkt der Codebasis wird: Alles hängt von ihr ab, und jede Änderung an ihr erfordert ein umfassendes Verständnis von ihr.
ErkennungssignalEine Klasse mit mehr als 20-30 öffentlichen Methoden oder eine Klasse, deren Name „Manager“, „Processor“, „Handler“, „Utils“ oder „Helper“ enthält, die auf mehrere voneinander unabhängige Domänen angewendet wird.
Divergente Veränderung
Eine Klasse, die aus vielen verschiedenen, voneinander unabhängigen Gründen geändert wird. Jedes Mal, wenn sich das Datenbankschema ändert, muss diese Klasse angepasst werden. Jedes Mal, wenn sich die Preisregeln ändern, muss diese Klasse angepasst werden. Jedes Mal, wenn sich das Benachrichtigungsformat ändert, muss diese Klasse angepasst werden. Diese Klasse hat zu viele Aufgaben und sollte aufgeteilt werden.
DefinitionEine Klasse, die sich aus verschiedenen Gründen ständig verändert. Das Gegenteil von Schrotflintenchirurgie.
Schrotflintenchirurgie
Eine einzige konzeptionelle Änderung erfordert Anpassungen in vielen verschiedenen Klassen. Die Änderung eines Steuersatzes erfordert die Modifizierung einer Backend-Berechnung, einer Frontend-Validierung, eines Datenbank-Triggers, eines Batch-Jobs und einer Berichtsabfrage an fünf verschiedenen Stellen. Fehlt eine dieser Änderungen, führt dies zu inkonsistentem Verhalten.
SQL
-- Tax logic duplicated across queries
SELECT amount * 0.05 FROM invoices;
SELECT amount * 0.05 FROM payments;
SELECT amount * 0.05 FROM reports;
Die Änderung von 0.05 auf 0.07 erfordert nun das Auffinden jedes einzelnen Vorkommens in SQL-Dateien, gespeicherten Prozeduren und Anwendungscode.
Feature-Neid
Eine Methode, die mehr Zeit mit den Daten und Methoden einer anderen Klasse verbringt als mit ihren eigenen. Dies deutet darauf hin, dass das Verhalten wahrscheinlich in die andere Klasse gehört.
Java
// In ReportGenerator -- envious of Customer's data
double calculateCustomerRating(Customer customer) {
return customer.getOrderCount() * customer.getAverageOrderValue()
/ customer.getDaysSinceRegistration();
}
// This logic belongs in Customer, not ReportGenerator
Toter Code
Code, der zwar im Repository vorhanden ist, aber in der Produktionsumgebung nie aufgerufen wird. Dieser tote Code sammelt sich über Jahre an, wenn Funktionen entfernt, ersetzt oder umstrukturiert werden, ohne den alten Code zu löschen. Er erschwert Code-Reviews, verwirrt neue Entwickler beim Einstieg in die Codebasis, verkompliziert die Migrationsanalyse und wird gelegentlich versehentlich reaktiviert.
Detection: Statische Analysetools wie SonarQube, Knip (für TypeScript/JavaScript) und SMART TS XL Identifizieren Sie nicht erreichbare Funktionen, nicht aufgerufene Methoden und ungenutzte Variablen im gesamten Quellcode.
Verstöße gegen das DRY-Prinzip
Das DRY-Prinzip (Don't Repeat Yourself) besagt, dass jedes Wissen innerhalb eines Systems nur eine einzige, eindeutige Repräsentation haben darf. Verstöße gegen das DRY-Prinzip sind die Hauptursache für doppelten Code, Datenansammlungen und viele Fälle von unstrukturierter Datenintegration. Wenn Geschäftslogik an mehreren Stellen abgebildet wird, weichen diese Repräsentationen zwangsläufig voneinander ab. DRY ist das Prinzip; doppelter Code ist der Indikator für einen Verstoß.
python
# DRY violation: same validation logic in three places
def validate_email_in_registration(email):
return "@" in email and "." in email
def validate_email_in_profile_update(email):
return "@" in email and "." in email
def validate_email_in_checkout(email):
return "@" in email and "." in email
# DRY-compliant: one function, three callers
def is_valid_email(email):
return "@" in email and "." in email
Erkennungsschwellen: Wann wird Code verdächtig?
Die Erkennung von Code-Smells erfordert messbare Schwellenwerte. Nachfolgend sind die gängigen Metriken und die Werte aufgeführt, die auf einen Code-Smell hinweisen, der Aufmerksamkeit erfordert:
| Metrisch | Was es misst | Warnschwelle | Kritischer Schwellenwert |
|---|---|---|---|
| Zyklomatische Komplexität | Anzahl der Entscheidungszweige in einer Methode | Vor 10 | Vor 20 |
| Methode Länge (Zeilen) | Anzahl der Zeilen in einer Methode/Funktion | Vor 20 | Vor 50 |
| Parameteranzahl | Anzahl der Parameter, die eine Methode akzeptiert | Vor 4 | Vor 7 |
| Klassenlänge | Anzahl der Zeilen in einer Klasse | Vor 200 | Vor 500 |
| Duplizierungsrate | Prozentsatz des duplizierten Codes | Über 3% | Über 10% |
| Kognitive Komplexität | Wie schwierig der Code zu verstehen ist | Vor 15 | Vor 25 |
| Afferente Kopplung (Ca) | Anzahl der Klassen, die von dieser Klasse abhängen | Vor 15 | Vor 30 |
| Efferente Kopplung (Ce) | Anzahl der Klassen, von denen diese Klasse abhängt | Vor 15 | Vor 30 |
Diese Schwellenwerte sind in SonarQube konfigurierbar, und die meisten statischen Analyseplattformen ermöglichen benutzerdefinierte Regeln basierend auf diesen Metriken. Die Klassen und Methoden, die die kritischen Schwellenwerte überschreiten, haben höchste Priorität beim Refactoring: Sie sind die wahrscheinlichsten Quellen zukünftiger Fehler und die wartungsintensivsten Komponenten.
Tools zur Erkennung von Code-Smells
Die automatisierte Erkennung ist der einzige skalierbare Ansatz, um Code-Smells in großen Codebasen zu identifizieren. Manuelle Überprüfungen erfassen nur einen Bruchteil dessen, was automatisierte Tools finden, und sind für Legacy-Systeme mit Millionen von Codezeilen nicht skalierbar.
| Werkzeug | Muttersprache | Was es erkennt |
|---|---|---|
| SonarQube / SonarCloud | Java, Python, JS/TS, C# und mehr | Vollständige Fowler-Geruchstaxonomie, Sicherheits-Hotspots, Duplikate |
| Karomuster + PMD | Javac | Stilverstöße, Duplikate, Komplexitätsmetriken |
| ESLint + typescript-eslint | JavaScript, TypeScript | Lange Funktionen, Komplexität, ungenutzter Code |
| Pylint + Radon | Python | Komplexitäts-, Stil- und Wartbarkeitsindex |
| ReSharper / Rider | C# | Redundanter Code, lange Methoden, Kopplungsprobleme |
| Clippy | Rest | Idiomatische Verstöße, häufige Muster, die in Rust als Code-Smells gelten. |
| CodeKlima | Mehrere Sprachen | Komplexität, Duplizierung, Wartbarkeitswert |
| SMART TS XL | COBOL, JCL, Java, Python, RPG, SQL, .NET | Sprachübergreifende Duplikation, toter Code, Kopplung, Abhängigkeitsdrift |
Code riecht nach Rost Diese werden hauptsächlich von Clippy erkannt, das idiomatische Rust-Muster durchsetzt. Zu den häufigsten Rust-spezifischen Indizien gehören unnötiges Klonen und der Missbrauch von … unwrap() in Produktionspfaden, übermäßig verschachtelten Übereinstimmungsausdrücken und Funktionen, die zurückgeben sollten Result Verwenden Sie stattdessen Panikmeldungen.
Code-Gerüche und technische Schulden: Der Zusammenhang
Technische Schulden sind die Kosten vergangener Entscheidungen, bei denen Geschwindigkeit Vorrang vor Qualität hatte. Code-Smells sind der Mechanismus, durch den sich diese Schulden in der Codestruktur manifestieren. Der Zusammenhang ist direkt: Jeder ungelöste Code-Smell stellt eine Einheit technischer Schulden dar, und die Zinsen entsprechen dem zusätzlichen Zeitaufwand, der für jede zukünftige Änderung nötig ist, um diesen zu umgehen.
Wie im Kontext von Auswirkungsanalyse für das SoftwareänderungsmanagementDie strukturellen Probleme, auf die Code-Smells hinweisen – übermäßige Kopplung, doppelte Logik, Ansammlung von totem Code –, vergrößern direkt den Umfang jeder Änderung, da sie es schwieriger machen, die Auswirkungen einer bestimmten Änderung zu isolieren.
Erklären Sie technische Schulden anhand von Code-Smells.Bei 40 % Code-Duplizierung kostet jede Fehlerbehebung das 1.4-Fache des Sollwerts. Ist die zentrale Verarbeitungsklasse eine Art „God Class“, von der alles abhängt, erfordert jede neue Funktion das Verständnis und Testen der gesamten Klasse. Bei inkonsistenter Fehlerbehandlung ist bei jedem Produktionsvorfall mehr Untersuchungszeit nötig, da die Fehlersignale unzuverlässig sind. Technische Schulden sind nicht abstrakt, sondern die Summe dieser sich gegenseitig verstärkenden Ineffizienzen.
Die CISQ-Studien zeigen übereinstimmend, dass Entwickler 30–40 % ihrer Zeit mit der Beseitigung technischer Schulden verbringen, anstatt neue Funktionen zu entwickeln. Die Code-Smell-Dichte ist das direkteste Maß dafür, wie viel technische Schulden sich angehäuft haben.
Wie SMART TS XL Erkennt Code-Smells im Unternehmensmaßstab
Einzelne Tools wie SonarQube und Clippy arbeiten innerhalb einer einzigen Programmiersprache. In Unternehmensumgebungen, in denen COBOL-Programme auf Datensätze schreiben, die von Java-Diensten gelesen werden, in denen JCL-Jobstreams Programme in mehreren Sprachen aufrufen und in denen dieselbe Geschäftslogik unabhängig voneinander in drei verschiedenen Systemen aus drei verschiedenen Jahrzehnten dupliziert wurde, können einsprachige Tools das Gesamtbild nicht erfassen.
SMART TS XL statische Code-Analyse erkennt gleichzeitig Code-Smells in allen Sprachen der Umgebung: doppelte Logik zwischen einem COBOL-Copybook und einer Java-Utility-Klasse, toten Code in RPG-Programmen, der von keinem JCL-Job aufgerufen wird, God-Class-Muster in COBOL-Programmen, bei denen ein einziger Absatz die Arbeit von fünfzig erledigt, und inkonsistente Fehlerbehandlungsmuster über die Sprachgrenze hinweg.
Das Zuordnung von Anwendungsabhängigkeiten Die Funktion identifiziert architektonische Indizien, die einzelne Tools auf Dateiebene nicht erkennen können: welche Komponenten die stärkste Kopplung aufweisen (am stärksten abhängig sind, das höchste Risiko besteht, dass Änderungen etwas kaputt machen), wo zirkuläre Abhängigkeiten zwischen Modulen bestehen, die eigentlich unabhängig sein sollten, und wo doppelte Geschäftslogik unabhängig in verschiedenen Systemen gepflegt wurde, ohne dass eine Kopie von der anderen Kenntnis hatte.
Das Wirkungsanalyse Die Fähigkeit, Code-Gerüche gezielt zu erkennen und zu beheben, macht diese Problematik nutzbar: Vor der Refaktorisierung einer stark gekoppelten Komponente listet die Folgenabschätzung alle abhängigen Komponenten auf, die getestet, validiert oder aktualisiert werden müssen. Dadurch wird die „Refactoring-Lähmung“, die Teams in großen, fehlerhaften Codebasen häufig erleben, in ein strukturiertes, zielgerichtetes Sanierungsprogramm verwandelt, bei dem jede Änderung einen definierten Umfang und kein unbekanntes Risiko birgt.
Für Teams, die durchführen Modernisierung des Altbestands Bei Programmen ist die Code-Smell-Analyse die Grundlage des Modernisierungsplans: Toter Code wird vor Beginn der Migration eliminiert (wodurch der Umfang reduziert wird), die duplizierte Logik wird in kanonischen Implementierungen konsolidiert, die am stärksten gekoppelten Komponenten werden zuletzt modernisiert (nachdem alles, was von ihnen abhängt, behandelt wurde), und die God Classes werden vor der Konvertierung in eine neue Sprache zerlegt, da die Konvertierung einer God Class nach Java eine God Class in Java erzeugt.
Umgang mit Code-Smells: Ein Priorisierungsrahmen
Nicht jeder Code-Smell erfordert ein sofortiges Refactoring. Der richtige Ansatz ist eine risikobasierte Priorisierung:
Priorität 1, Gerüche in Bauteilen mit hoher Änderungsrate. Code, der sich häufig ändert und eine hohe Komplexität oder starke Kopplung aufweist, verursacht die meisten Fehler. Diese Komponenten verursachen die höchsten Kosten pro Änderung und die meisten Produktionsausfälle. Beheben Sie diese Fehler zuerst.
Priorität 2, Gerüche an architektonischen Grenzen. Gottklassen und stark gekoppelte Komponenten, von denen alles abhängt, bergen das größte Risiko bei Änderungen, sind aber auch am kostspieligsten, wenn sie nicht korrigiert werden. Diese erfordern vor einem Refactoring eine äußerst sorgfältige Folgenabschätzung.
Priorität 3, Doppelte Codeabschnitte über Systemgrenzen hinweg. Wenn dieselbe Geschäftslogik in mehreren Systemen vorhanden ist, müssen Änderungen gleichzeitig in allen Kopien koordiniert werden. Die Konsolidierung dieser Redundanz reduziert den Koordinationsaufwand und verhindert Abweichungen.
Priorität 4, Entfernung von totem Code. Toter Code ist die sicherste Kategorie, die man angehen kann: Ihn zu entfernen, beeinträchtigt das Verhalten nicht, sondern deckt lediglich zuvor verborgene Abhängigkeiten auf. Er sollte vor jeder Migration oder Konvertierung entfernt werden, um unnötigen Aufwand für die Konvertierung von Code zu vermeiden, der nie aufgerufen wird.
Priorität 5, Stil- und Strukturgerüche in Bereichen mit geringem Risiko. Lange Methoden und Parameterlisten in stabilem Code mit geringer Änderungsrate können opportunistisch angegangen werden, wenn benachbarter Code aus anderen Gründen geändert werden muss; dabei können die umgebenden Code-Gerüche gleichzeitig beseitigt werden.
Die Disziplin, Code-Smells systematisch zu erkennen, zu messen und zu beheben, anstatt erst dann reaktiv zu handeln, wenn ein Code-Smell bereits zu einem Produktionsausfall geführt hat, unterscheidet Entwicklungsteams, die ihre Liefergeschwindigkeit über die Zeit aufrechterhalten, von solchen, die sich mit dem Wachstum ihrer Systeme zunehmend verlangsamen.