Blog 2 min read

Automatically Detect Poorly Implemented C++ Design Patterns.

Share this article
Automatically Detect Poorly Implemented C++ Design Patterns.

Design patterns are solutions to software design problems you find again and again in real-world application development. Patterns are about reusable designs and interactions between objects. Some of them are very popular, like singleton, factory, and strategy; others are not widely used, like the flyweight pattern.

Sometimes developers implement patterns poorly, which can introduce design issues and reduce their benefits. It is useful to identify poorly implemented patterns and correct their implementation.

To detect these kinds of issues, we need as much information as possible about the source code, including:

  • Attributes of classes, methods, and fields.
  • Inheritance relationships between classes.
  • Dependencies between classes, methods, and fields.
  • Where classes are instantiated.
CppDepend

generates a code model that contains all this data and lets you query it using CQLinq. Let’s try to detect the misuse of two patterns: Singleton and Strategy.

Singleton

The singleton pattern is a design pattern that restricts the instantiation of a class to one object. However, using this pattern has become controversial, and not all architects and designers recommend it; here’s an article about the singleton controversy.

A common mistake when implementing the Singleton pattern is failing to make the constructor private.

The following query detects all classes with the same traits as a singleton — i.e. classes containing one static field referencing themselves and a static method returning this field — but without a private constructor.

pattern1

Strategy

There are many situations where classes differ only in their behavior. In this case, it is a good idea to isolate the algorithms in separate classes, so you can select different algorithms at runtime. The strategy pattern is a good candidate for such needs.

Here’s the UML diagram of this pattern:

Strategy_Pattern_in_UML

As the diagram shows, the context class uses the abstract class “Strategy” and has no knowledge of the concrete implementations. However, in some implementations the concrete classes are used directly by the context class. Here’s a sample of this mistake:

pattern3

Let’s search with CQLinq for all classes using this strategy pattern. To do this, we can search for abstract classes with multiple derived classes where the client directly uses methods from the concrete implementations instead of the abstract class.

pattern2

The result of this query gives us the derived types used directly by other methods instead of the abstract ones. You then simply need to find the methods that use them to determine where the Strategy pattern implementation should be corrected.

However, this will not identify the exact places where the Strategy pattern is poorly implemented. Instead, it highlights potential problem areas that a developer can then review manually.

Conclusion

Design patterns can improve design quality. However, if they are poorly implemented, they can become a source of issues and bugs.

Share this article