Blog 4 min read

Tracking C++ Code Smells: Database Approach

Share this article
Tracking C++ Code Smells: Database Approach

Static analysis is not only about directly finding bugs, but also about finding bug-prone situations that can hurt code readability and maintainability. Static analysis can handle many other properties of the code:

  • Code metrics: for example, methods with too many loops, if, else, switch and case statements end up being hard to understand, hence hard to maintain. Counting these through the code metric Cyclomatic Complexity is a great way to assess when a method becomes too complex.
  • Dependencies: if the classes of your program are entangled, the effects of any changes in the code become unpredictable. Static analysis can help to assess when classes and components are entangled.
  • Immutability: types that are used concurrently by several threads should be immutable; otherwise you’ll have to protect state read/write access with complex lock strategies that will end up being unmaintainable. Static analysis can make sure that some classes remain immutable.
  • Dead code: dead code is code that can be removed safely, because it is not invoked anymore at runtime. Not only can it be removed, but it must be removed, because this extra code adds unnecessary complexity to the program. Static analysis can find most of the dead code in your program (yet not all).
  • API breaking change: if you present an API to your client, it is very easy to remove a public member without noticing and thus break your clients’ code. Static analysis can compare two states of a program and warn about this pitfall.
  • API usage: some APIs are intended to be used carefully. For example, a class that holds disposable fields must generally be disposable itself, except when the disposable field’s lifetime is not aligned with the class instance’s lifetime — which then smells like a design problem.

A code smell can also be considered a bug-prone situation; here’s its definition from Wikipedia:

In computer programming, code smell, (or bad smell) is any symptom in the source code of a program that possibly indicates a deeper problem. According to Martin Fowler, "a code smell is a surface indication that usually corresponds to a deeper problem in the system". Another way to look at smells is with respect to principles and quality: "smells are certain structures in the code that indicate violation of fundamental design principles and negatively impact design quality". Code smells are usually not bugs—they are not technically incorrect and do not currently prevent the program from functioning. Instead, they indicate weaknesses in design that may be slowing down development or increasing the risk of bugs or failures in the future. Bad code smells can be an indicator of factors that contribute to technical debt. Robert C. Martin calls a list of code smells a "value system" for software craftsmanship.

Many interesting tools exist to detect bugs in your C++ code base, like Cppcheck, Clang-Tidy and the Visual Studio analyzer. But what about detecting code smells?

While static analysis tool creators can decide which situations are considered bugs, that’s not the case for code smells, which depend on the development team’s choices. For example, one team could consider that a method with more than 20 lines is complex, while another team could set the maximum at 30. If a tool provides detection of code smells, it must also provide the possibility to customize it.

Code as Data is the best way to detect code smells

Static analysis is the idea of analyzing source code for various properties and reporting on those properties, but it’s also, philosophically, the idea of treating code as data. This is deeply weird to us as application developers, since we’re very much used to thinking of source code as instructions, procedures, and algorithms. But it’s also deeply powerful.

After the analysis of a source file, we can extract its AST and generate a model containing much interesting information about the code. This way, we can query it using a code query language similar to SQL.

CppDepend provides a code query language named CQLinq to query the code base like a database. Developers, designers and architects can define their own queries to easily find code smells.

With CQLinq we can combine the data from code metrics, dependencies, API usage and other model information to define very advanced queries that match specific code smells.

Here’s an example of a CQLinq query that matches the most complex methods:

bugs

Summary

It’s better to combine many C++ tools to detect problems in your C++ code base: some tools detect bugs, while others also detect code smells. With CppDepend we try to combine many tools: we provide an easy way to define your queries, and we can also import results from other static analysis tools to query them with CQLinq.

Share this article