Mit Codewiederholung (auch Code-Duplizierung) wird in der Programmierung eine wörtliche Wiederholung von Codepassagen in Quelltexten bezeichnet. Bei der Softwarewartung, der Modifikation oder der Erweiterung des Programmcodes kann Codewiederholung sehr leicht zu Programmfehlern führen und sollte daher so weit wie möglich unterlassen werden.
Beschreibung
Zur Codewiederholung kommt es häufig aus Bequemlichkeit, weil es einfacher zu sein scheint, einen bereits vorhandenen Quelltext zu kopieren und gegebenenfalls zu modifizieren, anstatt den ursprünglichen Code so anzupassen, dass er allgemeiner eingesetzt werden kann. Aus verschiedenen Gründen sollten Codewiederholungen jedoch unbedingt vermieden werden:
- Es besteht die Gefahr, dass der Quellcode kopiert wurde, bevor alle Fehler behoben wurden. In der Folge muss der Fehler an verschiedenen Stellen des Quelltextes gesucht und behoben werden.
- Auch bei der Wartung der Software müssen Anpassungen und Erweiterungen nicht nur an einer Stelle, sondern an allen relevanten Stellen im Quelltext durchgeführt werden.
- Der Quelltext wird durch Codewiederholungen länger und unübersichtlicher.
- Der Compiler oder Interpreter müssen unnötig viel Programmcode auswerten.
- Die Zuständigkeit und Verantwortlichkeit für bestimmte Codesequenzen ist nicht mehr einfach zu erkennen und zu regeln, wenn Codewiederholungen eingesetzt werden.
Die Code-Duplizierung wird als Anti-Pattern angesehen, widerspricht dem Prinzip „Don’t repeat yourself“ (DRY) und gilt als das am häufigsten auftretende Merkmal für schlechten Code. Sie führt aus den genannten Gründen die Liste der so genannten Code Smells[1] an.
Vermeidung
Zur Vermeidung von Codewiederholungen gibt es zum Beispiel die Möglichkeit der Verwendung von symbolischen Konstanten, der Implementierung von Unterprogrammen und Modulen oder die Vererbung von Objekteigenschaften und Objektmethoden, wie beispielsweise bei der Polymorphie. Diese Maßnahmen ermöglichen die Wiederverwendbarkeit von Programmcode.
Durch Refactoring[2] kann Codewiederholung relativ einfach aufgelöst werden. Es existieren verschiedene Algorithmen, um Codewiederholung aufzudecken. Beispiele hierfür sind der Rabin-Karp-Algorithmus, Baker’s algorithm[3] und Visual clone detection.[4]
Analyse
Es gibt verschiedene Werkzeuge zur statischen Analyse von Programmcode, die auch Codewiederholungen finden können. Eines der ältesten und bekanntesten dieser Werkzeuge ist Lint. Daneben existieren zahlreiche freie Werkzeugen wie das PMD-Plugin CPD (Copy/Paste Detector), Clone Digger (für Python und Java), Cppcheck (für C++ und C) und ConQAT (für Ada, ABAP, C#, C, C++, Cobol, Java, Visual Basic, PL/I) sowie proprietäre Werkzeuge wie CCFinder (Code Clone Finder) oder Simian (Similarity Analyser).
Beispiele
Symbolische Konstante
Mit Codewiederholung
Die möglicherweise fehlerhaft gerundete oder unvollständig eingegebene Kreiszahl (3,1416) muss an mehreren Stellen des Quelltextes behandelt werden:
Kreisumfang = Radius * 2 * 3,1416 Kreisfläche = Radius * Radius * 3,1416
Ohne Codewiederholung
Mithilfe einer symbolischen Konstanten wird die Kreiszahl nur ein einziges Mal deklariert und initialisiert:
Kreiszahl = 3,1416 Kreisumfang = Radius * 2 * Kreiszahl Kreisfläche = Radius * Radius * Kreiszahl
Funktionsaufruf
Mit Codewiederholung
Die mehrfach eingegebene nicht-triviale Anweisung zur Berechnung des Kreisumfangs muss an mehreren Stellen des Quelltextes behandelt werden:
Kreisumfang1 = Radius1 * 2 * Kreiszahl Kreisumfang2 = Radius2 * 2 * Kreiszahl Kreisumfang3 = Radius3 * 2 * Kreiszahl
Ohne Codewiederholung
Mithilfe eines Unterprogrammes zur Berechnung des Kreisumfangs und dessen dreimaligem Funktionsaufruf kann die Codewiederholung leicht vermieden werden:
Unterprogramm Kreisumfang (Radius) = Radius * 2 * Kreiszahl Kreisumfang1 = Kreisumfang (Radius1) Kreisumfang2 = Kreisumfang (Radius2) Kreisumfang3 = Kreisumfang (Radius3)
Vererbung
Mit Codewiederholung, ohne Vererbung
Die beiden graphischen Objekte Kreis und Dreieck werden unabhängig voneinander modelliert, und deren gemeinsame Eigenschaften Farbe und Strichstärke, sowie die jeweilige Methode zum Zeichnen werden beide Male behandelt:
Kreis hat: Farbe, Strichstärke, Methode zum Zeichnen, Radius Dreieck hat: Farbe, Strichstärke, Methode zum Zeichnen, SeiteA, SeiteB, SeiteC
Ohne Codewiederholung durch Vererbung
Mithilfe von Vererbung kann die Codewiederholung vermieden werden:
GraphischesObjekt hat: Farbe, Strichstärke, Methode zum Zeichnen Kreis ist GraphischesObjekt, hat zusätzlich: Radius Dreieck ist GraphischesObjekt, hat zusätzlich: SeiteA, SeiteB, SeiteC
Literatur
- 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).
- A Workbench for Clone Detection Research (PDF; 359 kB), E. Juergens, F. Deissenboeck, B. Hummel, ICSE '09: Proc. of the 31st International Conference on Software Engineering, 2009
- Java - exemplarisch: learning by doing, Kapitel 12.6 Mustervorlage für den Klassenentwurf, Ägidius Plüss, Verlag Oldenbourg Wissenschaftsverlag, 2004, ISBN 9783486200409
Weblinks
Einzelnachweise
- ↑ http://www.empros.ch/vielfach/faustregeln/502149936a0f4bb0f/codesmell.php
- ↑ http://wwwcs.uni-paderborn.de/cs/ag-engels/ag_dt/Courses/Lehrveranstaltungen/Siemens-Seminar/Ausarbeitungen/Heidenreich-Adrian.pdf
- ↑ Brenda S. Baker. A Program for Identifying Duplicated Code. Computing Science and Statistics, 24:49–57, 1992.
- ↑ Visual Detection of Duplicated Code (PDF; 45 kB) by Matthias Rieger, Stephane Ducasse.