digital patterns

Detect not well implemented C++ design patterns automatically

Thursday, April 15, 2021

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 of objects. Some of them are very popular like singleton, factory, and strategy.  Others are not widely used like the flyweight pattern.

Sometimes the patterns are not well implemented by developers. This could generate some design issues and affect the benefits of using them. It’s interesting to detect where they are not well implemented, and correct their implementation.

To detect these kinds of issues we need a maximum of information about the source code including:

  • Attributes of classes, methods, and fields.
  • The inheritance between classes.
  • Dependencies between classes, methods, and fields.
  • Where classes are instantiated.

CppDepend generates a code model which contains all these data and permits to query them using CQLinq. Let’s try to detect the misusing 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 became controversial, and not all architects and designers recommend it, here’s an article talking about the singleton controversy.

A common mistake of implementing a singleton pattern is to not 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 itself, a static method returning this field. And not contains a private constructor.

pattern1

Strategy

There are common situations when classes differ only in their behavior. For this case, it is a good idea to isolate the algorithms in separate classes in order to have the ability to 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 about the concrete implementations. However,  for some implementations, the concrete classes are used directly by the Context one. Here’s a sample of this mistake:

pattern3

Let’s search with CQLinq all classes using this strategy pattern. For this purpose, we can search for abstract classes having multiple derived classes and where the client uses directly the methods of the concrete implementations instead of the abstract ones.

pattern2

The result of this query will give us the derived types used directly by other methods instead of using the abstract ones. You have just to search for methods using them to know where to correct the strategy pattern implementation.

However it will not give us exactly the places where the strategy pattern is not well implemented, But some potential places where the problem could exist and the developer will check manually if it’s an issue or not.

Conclusion

The design patterns improve the design quality. However, if they are not well implemented they could be a source of many issues and bugs.

This post was originally published in https://cppdepend.com/blog/?p=1054