Aller au contenu

Improving Software Quality

Introduction

You now have run your own, simple, application developed for Mbed OS with Mbed Studio. Before developing a more complex application, we need to make sure that our application meets certain quality standards. This codelab aims at adding this dimension to your project so as to have sound foundations for future work.

What you’ll build

In this codelab, you will understand the required tools and guidelines for building qualitatively good software. Of course, those should be used while creating any type of software. You will also understand how to interpret the results delivered by the tools used in order to improve your work.

What you’ll learn

  • How to set up the tools for ensuring certain quality standards.
  • Start ensuring quality throughout the entire development lifecycle.
  • Understand the different elements composing quality and how to interpret the results provided by the different analysis tools.

What you’ll need

  • You need to have completed the Getting started with Mbed OS.
  • You need to have started the C++ Basics and completed the related exercices.
  • You need to install a number of additional software components as documented in the codelab.
  • You need python3 to be installed on your machine. In case it is not already installed, download the installer from this link. For Windows users, you may also follow these instructions.

Enforcing a common coding style: clang-format

In most cases, software is developed by many contributors. Imposing a common coding style can improve the readability and maintainability of the code of and by all contributors. Code consistency is also important for code reviews, where different contributors revise code written by others.

In this course, we will use clang-format, which is a relatively easy-to-use tool for enforcing a common code style for your projects written in C++.

Installation

Head to clang-format - LLVM Download Page, download and install the appropriate package.

A direct link to the installer for Windows is given here. For other operating systems, you may issue the following commands:

  • MacOS: brew install clang-format
  • Linux: sudo apt install clang-format

Run a first clang-format operation

For using clang-format, you first need to create a configuration file named .clang-format at the root of your project - where you will run the clang-format tool. This file contains various configuration parameters such as:

---
BasedOnStyle: Google
IndentWidth: 4
---
Language: Cpp
ColumnLimit: 90
AlignConsecutiveAssignments: true
DerivePointerAlignment: false
PointerAlignment: Left
BinPackArguments: false
BinPackParameters: false
IndentAccessModifiers: false
The parameters for configuring clang-format are described here. From this documentation, you should be able to understand the options used in the configuration file illustrated above.

For using clang-format, you may then run the command clang-format -i main.cpp. In this command, -i means that the file is edited in place. This means that if clang-format detects required changes in the file, it will modify the file with the required changes. Without the -i option, clang-format simply outputs the modified file on the console without modifying the file itself.

Guideline checker: cpplint

cpplint is a command-line tool used for checking that C++ code follows the Google’s C++ style guide.

The guidelines cover a wide range of rules, ranging from notation to dos and dont’s for writing C++ code. The overall goal is to make the code more readable and more robust.

Whether it is a good idea to apply Google guidelines for our project is certainly a good question. At this point, it is important to apply one guideline and it is up to debate whether this is the best tool among existing ones.

Installation

You simply need to enter pip3 install cpplint for installing the cpplint tool on your system. Run cpplint --version for checking that the installation was successful.

Run a first cpplint analysis

Before running your first analysis, you may add the file “cpplint.cfg” at the root of your code repository, with the following content:

linelength=90
filter=-build/include_subdir,-whitespace/indent,-build/namespaces,-build/c++11
By default, this configuration file is read by cpplint and the configuration is applied for all files analyzed in this directories and in the sub-directories.

To see a list of all category filters in cpplint, you may simply type cpplint --filter= (with no argument). This will list all available filters. Available options may be listed with cpplint --help. Options may be entered in the command line or in the “cpplint.cfg” file.

Once you created the configuration file, you may simply enter cpplint main.cpp. On Windows, if the tool is not found, check that it is indeed present in your $PATH.

Run an example that produces errors/warnings

One of the common errors detected by cpplint for C++ programs is the use of C-style type casts. The error is detected because in C++, one should use the C++ type cast operators rather than C-style casts (e.g. (int) value). This makes conversions more robust and better documented. For more details, you may read the task of the embedded C++ lessons dedicated to the conversion topic.

For demonstrating how cpplint detects the issue, it is enough to add the following code in your main() function.

int val = 3;
float fval = val * 4.0;
val = (int) fval;
If you run cpplint main.cpp with the modified “main.cpp” file, you should get the following error message:
main.cpp:21:  Using C-style cast.  Use static_cast<int>(...) instead  [readability/casting] [4]
If you modify the code as
val = static_cast<int>(fval);
then the correction should be accepted by cpplint.

Issues detected by cpplint

There may be issues flagged by cpplint that may seem not trivial. If some issues are not clear to you, you may:

  • check Google’s Styleguide concerning the rationale of the rule
  • have a look at the Styleguide Script as it may help the understanding
  • disable a rule with the --filter option, with a clear written justification.

Copyrighting your work

No matter what software one writes, a copyright shall always be specified - no matter whether open source or proprietary in its nature. With cpplint, in case you forget to apply this rule, the following error will be shown ” No copyright message found. You should have a line: Copyright [year] <Copyright Owner>” in any file containing code.

An example of such copyright can be found below:

  /**
  ******************************************************************************
  * @file        : monnalisa.hpp
  * @brief       : pensive woman module
  * @author      : Leonardo Da Vinci <leo@davinci.net>
  * @date        : 19. March 1503
  ******************************************************************************
  * @copyright   : Copyright (c) 1503 
  *                Haute école de peinture de Florence
  * @attention   : SPDX-License-Identifier: MIT OR Apache-2.0
  ******************************************************************************
  * @details
  * Pensive woman module for impressing humankind
  ******************************************************************************
  */

Static C++ Code Analysis: cppcheck

cppcheck is a static analysis tool for C/C++ code. It helps to detect bugs based on pre-defined rules that may be adapted to different needs - also for embedded software.

Static analysis means that the analysis happens on the code itself and not on a running program. It focuses on detecting code that:

  • may produce undefined behavior,
  • uses patterns that may be dangerous, or
  • do not follow the defined coding style.

Installation

In order to install it, head to cppcheck - Download, download and install the appropriate package (while ignoring Windows warning as the installer is not signed) - make sure you install Python Addons as well.

Do not forget to add the application to your $PATH (as the installer is not doing it for you…).

Run a first cppcheck analysis

For our first analysis - to ensure all works - we will make use of the blinky program written in the Getting started with Mbed OS codelab.

Run the cppcheck tool and inspect the results. You can run the tool for analyzing the “main.cpp” file by entering:

cppcheck main.cpp

The analysis should run smoothly and you should not get any warning.

Run an analysis that produces errors/warnings

If you add the following two lines in your main() function:

char a[10];
a[10] = 0;
then when running cppcheck again, you should get the following error:
main.cpp:25:7: error: Array 'a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]
     a[10] = 0;
The bug of accessing an array element that is out of bounds is detected by cppcheck.

It is important to point out that this bug is also detected by the compiler. When compiling the modified code, you should indeed see the following warning in the compile output:

[Warning] main.cpp@25,6: array index 10 is past the end of the array (which contains 10 elements) [-Warray-bounds]
This demonstrates that the compiler itself does perform some static analysis and can generate warnings or errors. Since C++ does not perform any range check at runtime, detecting possible out of bounds access at compile time is even more important. With the standard Mbed OS compiler flags, such a bug is not considered as an error but it is possible to turn it to an error by adding the “-Werror=array-bounds” compiler flag.

Fixing issues found by any of the tools

It is important that any fix/bug correction made to your code are done using the proper git branch process. For this purpose, you need to:

  • Create a dedicated branch on your repository: you should create a different dedicated branch for a specific code release and you should name it accordingly.
  • Fix the identified issues in this branch: no other changes should be implemented in this particular branch and in particular, implementing fixes and features should not be mixed.
  • Commit your changes: add a clear commit message for each specific change implemented in this branch. Remember that small commits are usually better than larger ones. So, you should commit one change at a time and not all changes at once.

Putting all together: pre-commit

You are now capable of checking your code and of implementing fixes to it by following the proper git guidelines. We still need to make sure that any change in the code goes through the entire continuous checking pipeline. How can one ensure this?

One way would be to check it centrally using a CI/CD pipeline on a git repository, but that would be late (and consume energy for nothing). One probably better approach is to use pre-commit, that does exactly what its name implies. pre-commit allows to run a serie of checks prior to committing.

Installation

In order to install it, head to https://pre-commit.com/ and follow the instructions.

Using it

So, once installed, we add all the tools seen so far in the pre-commit phase by following these instructions:

  • create a “.pre-commit-config.yaml” file at the root of your git project with the following content:
files: ^main.cpp
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
  rev: v4.3.0
  hooks:
  -   id: check-yaml
      args: [--allow-multiple-documents]
  -   id: end-of-file-fixer
  -   id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-clang-format
  rev: 'v14.0.6'
  hooks:
  -   id: clang-format
- repo: https://github.com/cpplint/cpplint
  rev: '1.6.1'
  hooks:
  -   id: cpplint
- repo: local
  hooks:
  -   id: cppcheck
      name: cppcheck
      require_serial: true
      entry: cppcheck --enable=all --suppress=missingInclude:* --inline-suppr -i mbed-os --std=c++14 --error-exitcode=1
      language: system
  • add .pre-commit-config.yaml to your git repository
  • install the hooks with pre-commit install
  • run the command manually by issuing pre-commit run --all-files
  • if you did a good job in fixing the issues manually, all will be green.

For a better understanding of pre-commit configuration, answer to the questions in Configuring .pre-commit.

That’s it!. From now on, all code changes will undergo the specified checks.

Wrap up

At this point, your git repository should contain the following:

  • the code developed in the Getting started codelab.
  • the test programs developed in the Testing MbedOS codelab.
  • the configuration files for all tools presented in this codelab, including the “.pre-commit-config.yaml” file.

The code should be compliant with all adopted rules and you should be capable of implementing features and fixes to the program by following all guidelines and applying the appropriate git process.

If you have accomplished all of it, you are ready to deliver the project, phase 1.

Metrics and static analysis - Going beyond

Although we will use the above tools throughout the course, there is a multitude of other metrics that will help you assess the code quality. Scitool Understand offers you many metrics or static analysis options. Free academic licenses exist for the tool and you are free to explore this further possibility.