Blog 5 min read

Tracking the hidden duplicate code in a C++ code base.

Share this article
Tracking the hidden duplicate code in a C++ code base.

It’s well known that the presence of duplicate code has a negative impact on software development and maintenance. Indeed, a major drawback is that when an instance of duplicate code is changed to fix bugs or add new features, its counterparts have to be changed simultaneously.

The most common cause of duplicate code is copy-and-paste operations, where the source code is exactly the same in two or more places. This practice is discouraged in many articles, books, and websites. However, it’s not always easy to follow the recommendations, and developers often choose the easy solution: copy and paste.

There are many tools for detecting this kind of cloned code; CCFinderX is one of the interesting open source tools available. CCFinderX is a code-clone detector that detects code clones (duplicated code fragments) in source files written in Java, C/C++, COBOL, VB and C#. It enables user-side customization of a preprocessor and provides interactive, metrics-based analysis.

Using the appropriate tool makes it easy to detect duplicate code produced by copy-and-paste operations; however, there are some cases where cloned code is not trivial to detect.

Hidden duplicate codeCase 1: Modified copy-and-pasted code.

As described above, the main problem with copy-and-pasted code is that when an instance of duplicate code is changed, its counterparts have to be changed simultaneously. Unfortunately, this is not always the case, and the duplicate code instances become different.

To avoid this kind of hidden duplicate code, don’t hesitate to use a tool like CCFinderX to discover the duplicate code instances, and at least tag them by adding comments if you don’t have time to refactor your code. This is very useful when a developer tries to change a duplicate code instance: they will be notified that the same code exists elsewhere. However, if the developer is unaware of the duplication, they may change only one instance, and it will become very difficult to detect the modified duplicate code later.

Case 2: Similar functionality

Copy/paste operations are not the only source of duplicate code; another source is the independent implementation of similar functionality.

Here’s a brief description of this second source of duplicate code from 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.

Tracking hidden duplicate code

When the duplicate code is not exactly the same, no tool can give you reliable results: it can only report potential duplicate code, and it’s the developer’s responsibility to check whether it’s really cloned code or just a false positive.

Each tool uses a specific algorithm to track this kind of duplicate code. We didn’t test all of these tools, but I think most of them are worth trying at least once: they could give you interesting results that help you improve the design and implementation of your code, as we will see later in this post.

In our case, we will use an algorithm that consists of defining sets of methods that use the same members, i.e., calling the same methods, reading the same fields, and writing the same fields. We call these sets suspect-sets. Suspect-sets are sorted by the number of common members used.

CppDepend implements this algorithm as a CppDepend Power-Tool. Power-Tools are a set of open-source tools based on the CppDepend.API. The source code of the Power-Tools can be found in $CppDependInstallPath$\CppDepend.PowerTools.SourceCode\CppDepend.PowerTools.sln.

Let’s see how effective this algorithm is at finding duplicate code in the Irrlicht 3D engine code base.

Case study: Irrlicht 3D engine

The Irrlicht Engine is an open-source, high-performance real-time 3D engine written in C++. It is completely cross-platform.

Here are two examples of suspicious duplicate code that were detected:

1- Exact duplicate code

In this case, the 18 methods detected use the same 3 methods, read the same 2 fields and write the same 9 fields.

clone5

After checking the source code of these methods, they turn out to contain exact duplicate code. However, other tools are better suited to detect this kind of duplication, and our algorithm provides no additional value when it comes to detecting exact clones.

2- Similar functionality

Here’s a second suspected duplication: it involves four methods that use the same 11 methods, read the same 6 fields and write the same 2 fields.

clone6

After checking the source code of these four methods, the code is not exactly the same. However, they implement the same layout algorithm, so in this case I would recommend refactoring.

To better explain this case, here’s the relationship between the classes involved in the duplicate code:

clone7

OnSetConstants is declared in the IShaderConstantSetCallBack interface and implemented by all derived classes. All four implementations have the same layout algorithm, and in such cases the template method pattern is a good solution to refactor the existing implementation.

When testing this algorithm on many open-source C++ projects, we were very surprised to find that many cases of duplicate code are similar to this one, and that the template method pattern is rarely used.

Conclusion

Tracking duplicate code is very useful for improving both the implementation and the design of your projects. Fortunately, many tools exist to detect cloned code, and it is a good idea to run one of these tools periodically and, at a minimum, tag duplicate instances.

Share this article