It is probably safe to claim that modern embedded systems contain more and more software, thereby also increasing the risk of introducing software errors. A good strategy to improve the situation is to avoid problems in the first place. This may sound easier said than done, but in fact it can be done fairly easily by measuring and managing the code complexity, as software with a high complexity level is likely to contain more bugs than software of lower complexity.
Please note that in this context, code complexity is not the same as code size (lines of code). A large C function can be of low complexity, and a small C function can be of high complexity. Code complexity measures the amount of decision logic in a C function, not the amount of code in it.
Code complexity is usually presented using a standard measure called the cyclomatic value of code complexity (also known as the McCabe index, giving tribute to its inventor). It calculates the amount of decision logic in a C function. It is therefore an excellent predictor of bug probability, and can also be used to provide judgments on the soundness and confidence for a software implementation in general. The cyclomatic value of code complexity measures the number of independent execution paths (the structural complexity) through a function, assigning a numerical value to the complexity of each C function. The more iterations and conditional code a function has; the higher its complexity level.
The tables above show guidelines on how different code complexity levels affect the number of bugs, and the risk of introducing new bugs while correcting existing bugs. By monitoring and managing code complexity levels, your product can be released with higher quality and lower maintenance costs.
A complex function is likely to include more errors, and is more difficult to understand, test and maintain. Functions that are too complex should be simplified by rewriting or refactored by splitting into several smaller functions, thereby creating less error-prone functions of reduced complexity.
Normal general purpose embedded projects ought to strive for a maximum code complexity level of 10 for most C functions, while safety critical software may not allow a higher complexity level than 5, or even 3 for the most safety critical parts of the code.
It is possible (and sometimes necessary) to allow complexity levels above the defined limit, but it should only be done in certain C functions when there is a specific reason to allow it, and the decision is actively and conciusly made. For the rare cases when you accept functions with a complexity level above your defined limit (such as 10 for general purpose embedded projects), it is good practice to use manual source code reviews to ensure the software quality in those functions.
Limiting software complexity is a great way of reducing the risk of bugs, to reduce development and testing costs, as well as simplifying maintenance for years to come. Our embedded C/C++ IDE for ARM developers, Atollic TrueSTUDIO, is equipped with code complexity measurement as a standard feature, thus empowering embedded developers with a new, very powerful tool for improving software quality.
If you use Atollic TrueSTUDIO Pro, I strongly encourage you to test our code complexity measurement features, as they are included as standard, and most likely will help you to improve your software quality quite a lot!
In case you want to learn more on improving your software quality by performing code complexity measurement and management, read this whitepaper: