Code-Smell

Unter Code-Smell, kurz Smell (engl. ‚[schlechter] Geruch‘) oder deutsch übelriechender Code versteht man in der Programmierung ein Konstrukt, das eine Überarbeitung des Programm-Quelltextes nahelegt. Dem Vernehmen nach stammt die Metapher Smell von Kent Beck und erlangte weite Verbreitung durch das Buch Refactoring von Martin Fowler. Unter dem Begriff sollten handfestere Kriterien für Refactoring beschrieben werden, als das durch den vagen Hinweis auf Programmästhetik geschehen würde.

Bei Code-Smell geht es nicht um Programm- oder gar Syntaxfehler, sondern um funktionierenden Programmcode, der aber schlecht strukturiert ist. Das größte Problem liegt darin, dass der Code für den Programmierer schwer verständlich ist, so dass sich bei Korrekturen und Erweiterungen häufig wieder neue Fehler einschleichen. Code-Smell kann auch auf ein tieferes Problem hinweisen, das in der schlechten Struktur verborgen liegt und erst durch eine Überarbeitung erkannt wird.

Verbreitete Smells

Die folgenden von Martin Fowler und Kent Beck beschriebenen Smells[1] beziehen sich auf die objektorientierte Programmierung, haben aber naheliegende Entsprechungen unter anderen Programmier-Paradigmen.

Code-Duplizierung
Der gleiche Code kommt an verschiedenen Stellen vor.
Lange Methode
Eine Methode (Funktion, Prozedur) ist zu lang.
Große Klasse
Eine Klasse ist zu umfangreich, umfasst zu viele Instanzvariablen und duplizierten Code. Siehe auch Gottobjekt.
Lange Parameterliste
Anstatt ein Objekt an eine Methode zu übergeben, werden Objekt-Attribute extrahiert und der Methode als lange Parameterliste übergeben.
Divergierende Änderungen
Für eine Änderung muss eine Klasse an mehreren Stellen angepasst werden.
Schrotkugeln herausoperieren (engl. Shotgun Surgery)
Dieser Smell ist noch gravierender als divergierende Änderungen: Für eine Änderung müssen weitere Änderungen an vielen Klassen durchgeführt werden.
Neid (engl. Feature Envy)
Eine Methode interessiert sich mehr für die Eigenschaften – insbesondere die Daten – einer anderen Klasse als für jene ihrer eigenen Klasse.
Datenklumpen
Eine Gruppe von Objekten kommt häufig zusammen vor: als Felder in einigen Klassen und als Parameter vieler Methoden.
Neigung zu elementaren Typen (engl. Primitive Obsession)
Elementare Typen werden benutzt, obwohl auch für einfache Aufgaben Klassen und Objekte aussagekräftiger sind.
Case-Anweisungen in objektorientiertem Code
Switch-Case-Anweisungen werden benutzt, obwohl Polymorphismus sie weitgehend überflüssig macht und das damit zusammenhängende Problem des duplizierten Codes löst.
Parallele Vererbungshierarchien
Zu jeder Unterklasse in der einen Hierarchie gibt es immer auch eine Unterklasse in einer anderen Hierarchie.
Faule Klasse
Eine Klasse leistet zu wenig, um ihre Existenz zu rechtfertigen.
Spekulative Allgemeinheit
Es wurden alle möglichen Spezialfälle vorgesehen, die gar nicht benötigt werden; solch allgemeiner Code braucht Aufwand in der Pflege, ohne dass er etwas nützt.
Temporäre Felder
Ein Objekt verwendet eine Variable nur unter bestimmten Umständen – der Code ist schwer zu verstehen und zu debuggen, weil das Feld scheinbar nicht verwendet wird.
Nachrichtenketten
Das Gesetz von Demeter wird verletzt.
Middle Man (Vermittler)
Eine Klasse delegiert alle Methodenaufrufe an eine andere Klasse.
Unangebrachte Intimität
Zwei Klassen haben zu enge Verflechtungen miteinander.
Alternative Klassen mit verschiedenen Schnittstellen
Zwei Klassen machen das gleiche, verwenden hierfür aber unterschiedliche Schnittstellen.
Inkomplette Bibliotheksklasse
Eine Klasse einer Programmbibliothek benötigt Erweiterungen, um in einem für sie geeigneten Bereich verwendet werden zu können.
Datenklasse
Klassen mit Feldern und Zugriffsmethoden ohne Funktionalität.
Ausgeschlagenes Erbe (engl. Refused Bequest)
Unterklassen brauchen die Methoden und Daten gar nicht, die sie von den Oberklassen erben (siehe auch Liskovsches Substitutionsprinzip)
Kommentare
Kommentare erleichtern im Allgemeinen die Verständlichkeit. Kommentare erscheinen jedoch häufig genau dort notwendig zu sein, wo der Code schlecht ist. Kommentare können somit ein Hinweis auf schlechten Code sein.

Weitere Smells und Programmierungs-Anti-Pattern

Neben den von Fowler erwähnte Smells gibt es noch eine Reihe von Code-Smells die oft auch unter Programmierungs-Anti-Pattern erwähnt werden:

Nichtssagender Name (engl. Uncommunicative Name)
Name, der nichts über Eigenschaften oder Verwendung des Benannten aussagt. Aussagekräftige Namen sind wesentlich für das Verständnis von Programmcode.
Redundanter Code
Ein Stück Code, das nicht (mehr) verwendet wird.
Exhibitionismus (engl. Indecent Exposure)
Interne Details einer Klasse sind unnötigerweise Teil ihrer Schnittstelle nach außen.
Contrived complexity (engl.)
Erzwungene Verwendung von Entwurfsmustern, wo einfacheres Design ausreichen würde.
Zu lange Namen
Insbesondere die Verwendung von Architektur- oder Designbestandteilen in den Namen von Klassen oder Methoden.
Zu kurze Namen
Die Verwendung von „x“, „i“ oder Abkürzungen. Der Name einer Variable sollte ihre Funktion beschreiben.
Über-Callback
Ein Callback, der versucht, alles zu tun.
Komplexe Verzweigungen
Verzweigungen, die eine Menge von Bedingungen abprüfen, die mit der Funktionalität des Codeblocks nichts zu tun haben.
Tiefe Verschachtelungen
Verschachtelte if/else/for/do/while-Statements. Sie machen den Code unlesbar.

Architektur-Smells

Neben den von Beck und Fowler adressierten Smells im Quelltext von Anwendungen treten Smells auch in der Architektur von Softwaresystemen auf. Diese wurden von Stefan Roock und Martin Lippert beschrieben.

Zu den Architektur-Smells zählen unter anderem:

  • Zyklische Benutzungsbeziehungen zwischen Paketen, Schichten und Subsystemen
  • Größe und Aufteilung der Pakete oder Subsysteme

Siehe auch

Literatur

  • Stefan Roock, Martin Lippert: Refactorings in großen Softwareprojekten: Komplexe Restrukturierungen erfolgreich durchführen. dpunkt, ISBN 978-3-89864-207-1.
  • Martin Fowler: Refactoring. Wie Sie das Design vorhandener Software verbessern. Addison-Wesley, München 2000, ISBN 3-8273-1630-8, S. 67–82 (englisch: Refactoring. Improving The Design Of Existing Code. Übersetzt von Bernd Kahlbrandt).

Weblinks

  • Refactoring Eine Überblicksarbeit, die im Abschnitt 2.3 unter dem Titel "Bad Smells" einige wichtige Smells erklärt.

Einzelnachweise

  1. Martin Fowler: Refactoring. Wie Sie das Design vorhandener Software verbessern. Addison-Wesley, München 2000, ISBN 3-8273-1630-8, S. 67–82 (englisch: Refactoring. Improving The Design Of Existing Code. Übersetzt von Bernd Kahlbrandt).