Blog 5 Min. Lesezeit

Versteckten duplizierten Code in einer C++-Codebasis aufspüren.

Diesen Artikel teilen
Tracking the hidden duplicate code in a C++ code base.

Es ist allgemein bekannt, dass duplizierter Code die Softwareentwicklung und -wartung negativ beeinflusst. Ein wesentlicher Nachteil besteht darin, dass bei Änderungen an einer duplizierten Codepassage – etwa zur Fehlerbehebung oder zum Hinzufügen neuer Funktionen – auch ihre Gegenstücke gleichzeitig angepasst werden müssen.

Die häufigste Ursache für duplizierten Code sind Copy-and-Paste-Vorgänge, bei denen derselbe Quellcode an zwei oder mehr Stellen vorkommt. Von dieser Praxis wird in zahlreichen Artikeln, Büchern und auf Websites abgeraten. Dennoch ist es nicht immer einfach, diese Empfehlungen einzuhalten, und Entwickler wählen häufig den bequemeren Weg: Kopieren und Einfügen.

Es gibt zahlreiche Werkzeuge, um diese Art von geklontem Code zu erkennen; CCFinderX ist eines der interessanten verfügbaren Open-Source-Werkzeuge. CCFinderX erkennt Codeklone (duplizierte Codefragmente) in Quelldateien, die in Java, C/C++, COBOL, VB und C# geschrieben sind. Es ermöglicht die benutzerseitige Anpassung eines Präprozessors und bietet interaktive, metrikbasierte Analysen.

Mit dem passenden Werkzeug lässt sich durch Copy-and-Paste entstandener duplizierter Code leicht erkennen. Es gibt jedoch Fälle, in denen Codeklone deutlich schwieriger aufzuspüren sind.

Versteckter duplizierter CodeFall 1: Nachträglich veränderter Copy-and-Paste-Code.

Wie oben beschrieben, besteht das Hauptproblem von Copy-and-Paste-Code darin, dass bei einer Änderung einer duplizierten Codepassage auch ihre Gegenstücke gleichzeitig geändert werden müssen. Leider geschieht das nicht immer, sodass sich die ursprünglich identischen Codepassagen mit der Zeit voneinander unterscheiden.

Um diese Art versteckter Duplikate zu vermeiden, sollten Sie ein Werkzeug wie CCFinderX einsetzen, um duplizierte Codepassagen zu finden. Wenn für ein Refactoring keine Zeit bleibt, sollten Sie sie zumindest mit Kommentaren kennzeichnen. Das ist besonders hilfreich, wenn ein Entwickler später eine dieser Passagen ändern möchte: Er wird darauf hingewiesen, dass derselbe Code auch an anderer Stelle existiert. Ist ihm die Duplizierung dagegen nicht bekannt, ändert er möglicherweise nur eine Instanz – und das nachträgliche Erkennen des veränderten Duplikats wird erheblich schwieriger.

Fall 2: Ähnliche Funktionalität

Copy-and-Paste ist nicht die einzige Ursache für duplizierten Code. Eine weitere Quelle ist die unabhängige Implementierung ähnlicher Funktionalität.

Hier ist eine kurze Beschreibung dieser zweiten Ursache für duplizierten Code aus Wikipedia:

Functionality that is very similar to that in another part of a program is required and a developer independently writes code that is very similar to what exists elsewhere. Studies suggest, that such independently rewritten code is typically not syntactically similar.

Versteckten duplizierten Code aufspüren

Wenn duplizierter Code nicht exakt identisch ist, kann kein Werkzeug vollkommen zuverlässige Ergebnisse liefern. Es kann lediglich potenzielle Duplikate melden; anschließend muss der Entwickler prüfen, ob tatsächlich ein Codeklon oder nur ein Fehlalarm vorliegt.

Jedes Werkzeug verwendet einen eigenen Algorithmus, um diese Art von Duplikaten aufzuspüren. Wir haben nicht alle verfügbaren Werkzeuge getestet, doch die meisten sind zumindest einen Versuch wert: Sie können interessante Ergebnisse liefern, die Ihnen helfen, Design und Implementierung Ihres Codes zu verbessern, wie wir später in diesem Beitrag sehen werden.

In unserem Fall verwenden wir einen Algorithmus, der darin besteht, Gruppen von Methoden zu bilden, die dieselben Member verwenden, also dieselben Methoden aufrufen sowie dieselben Felder lesen und schreiben. Diese Gruppen nennen wir Suspect-Sets. Die Suspect-Sets werden nach der Anzahl der gemeinsam verwendeten Member sortiert.

CppDepend implementiert diesen Algorithmus als CppDepend Power-Tool. Power-Tools sind eine Sammlung von Open-Source-Werkzeugen auf Basis der CppDepend.API. Den Quellcode der Power-Tools finden Sie unter $CppDependInstallPath$\CppDepend.PowerTools.SourceCode\CppDepend.PowerTools.sln.

Sehen wir uns an, wie effektiv dieser Algorithmus duplizierten Code in der Codebasis der Irrlicht-3D-Engine findet.

Fallstudie: Irrlicht-3D-Engine

The Irrlicht Engine ist eine quelloffene, leistungsfähige Echtzeit-3D-Engine, die in C++ geschrieben wurde und vollständig plattformübergreifend ist.

Hier sind zwei Beispiele für verdächtigen duplizierten Code, die erkannt wurden:

1 – Exakt duplizierter Code

In diesem Fall verwenden die 18 erkannten Methoden dieselben drei Methoden, lesen dieselben zwei Felder und schreiben dieselben neun Felder.

clone5

Eine Prüfung des Quellcodes dieser Methoden zeigt, dass sie tatsächlich exakt duplizierten Code enthalten. Für diese Art von Duplikaten sind jedoch andere Werkzeuge besser geeignet; bei der Erkennung exakter Klone bietet unser Algorithmus keinen zusätzlichen Nutzen.

2 – Ähnliche Funktionalität

Hier ist ein zweiter Verdachtsfall: Er betrifft vier Methoden, die dieselben elf Methoden verwenden, dieselben sechs Felder lesen und dieselben zwei Felder schreiben.

clone6

Bei der Prüfung des Quellcodes dieser vier Methoden zeigt sich, dass der Code nicht exakt identisch ist. Sie implementieren jedoch denselben Layout-Algorithmus, weshalb ich in diesem Fall ein Refactoring empfehlen würde.

Um diesen Fall besser zu veranschaulichen, sehen Sie hier die Beziehungen zwischen den Klassen, die an dem duplizierten Code beteiligt sind:

clone7

OnSetConstants ist im Interface IShaderConstantSetCallBack deklariert und wird von allen abgeleiteten Klassen implementiert. Alle vier Implementierungen verwenden denselben Layout-Algorithmus; in solchen Fällen ist das Template-Method-Pattern eine gute Lösung für das Refactoring der bestehenden Implementierung.

Beim Testen dieses Algorithmus auf zahlreichen Open-Source-C++-Projekten waren wir überrascht, wie viele Fälle von dupliziertem Code diesem Beispiel ähneln und wie selten das Template-Method-Pattern eingesetzt wird.

Fazit

Das Aufspüren duplizierten Codes ist sehr hilfreich, um sowohl die Implementierung als auch das Design Ihrer Projekte zu verbessern. Glücklicherweise gibt es zahlreiche Werkzeuge zur Erkennung von Codeklonen. Es empfiehlt sich, eines dieser Werkzeuge regelmäßig auszuführen und gefundene Duplikate zumindest entsprechend zu kennzeichnen.

Diesen Artikel teilen