Cyclomatic complexity & SW safety
Cyclomatic complexity is a software metric that measures the complexity of a program. It provides a quantitative measure of program complexity by analyzing the number of linearly independent paths in its control flow. By evaluating the number of decision points and potential execution paths, cyclomatic complexity can help developers identify areas that may require additional testing, refactoring, or optimization. It serves as a useful software quality assurance tool, helping to improve code readability, maintainability, and overall software quality.
?
The cyclomatic complexity of a program is initially set to 1, and it increments by 1 whenever a decision or condition is encountered. The complexity is impacted by the analysis scope, with the potential for an entire program to have a high cyclomatic complexity?while a module could have a CYC of 6. A higher CYC signifies increased program complexity, posing challenges for maintenance and unit testing. Thus, it is essential to consider cyclomatic complexity at each scope (program, class, and method) to effectively handle complexity and testing requirements.
?
The complexity thresholds for risk management are as follows:
?
1-CYC between 1-10: The program is classified as simple, with minimal risk involved.
2-CYC between 11-20: The code is considered more complex, indicating a moderate level of risk.
3-CYC between 21-50: The program falls into the complex category, presenting a high level of risk.
4-CYC above 50: The program is deemed untestable, signifying a very high risk level.
?
Let's take an example by code provides a basic structure code for reading the steering wheel sensor value and controlling the E-motor.
?
#include <iostream>
?
// Function to read the steering wheel sensor value
int readSteeringWheelSensor() {
???// Replace this with your actual implementation to read the sensor value
???int sensorValue = 0;
???std::cout << "Enter steering wheel sensor value: ";
???std::cin >> sensorValue;
???return sensorValue;
}
?
// Function to control the electrical motor based on the sensor value
void controlMotor(int sensorValue) {
???// Replace this with your actual implementation to control the motor
???if (sensorValue > 0) {
???????std::cout << "Motor rotating clockwise." << std::endl;
???} else if (sensorValue < 0) {
???????std::cout << "Motor rotating counter-clockwise." << std::endl;
???} else {
???????std::cout << "Motor stopped." << std::endl;
???}
}
?
int main() {
???// Read sensor value
???int sensorValue = readSteeringWheelSensor();
?
???// Control the motor based on the sensor value
???controlMotor(sensorValue);
?
???return 0;
}
?
领英推荐
To calculate the cyclomatic complexity of the code provided, we need to determine the number of decision points or branches in the control flow. Each decision point adds 1 to the cyclomatic complexity. Let's analyze the code:
The total cyclomatic complexity of the code is 1.
?
Let's update the code to achieve a cyclomatic complexity result of 2, I introduced an additional nested if statement inside the controlMotor() function. The outer if condition checks if the sensorValue is not equal to zero, which acts as the first decision point. If the condition is true, it proceeds to the nested if-else block to determine the direction of motor rotation. This results in a cyclomatic complexity of 2 as you can see :
#include <iostream>
?
// Function to read the steering wheel sensor value
int readSteeringWheelSensor() {
???// Replace this with your actual implementation to read the sensor value
???int sensorValue = 0;
???std::cout << "Enter steering wheel sensor value: ";
???std::cin >> sensorValue;
???return sensorValue;
}
?
// Function to control the electrical motor based on the sensor value
void controlMotor(int sensorValue) {
???// Replace this with your actual implementation to control the motor
???if (sensorValue != 0) {
???????if (sensorValue > 0) {
???????????std::cout << "Motor rotating clockwise." << std::endl;
???????} else {
???????????std::cout << "Motor rotating counter-clockwise." << std::endl;
???????}
???} else {
???????std::cout << "Motor stopped." << std::endl;
???}
}
?
int main() {
???// Read sensor value
???int sensorValue = readSteeringWheelSensor();
?
???// Control the motor based on the sensor value
???controlMotor(sensorValue);
?
???return 0;
}
?
The relationship between cyclomatic complexity and Part 6 of ISO 26262, specifically concerning verification and software architectural design, is evident in Tables 1 and 3. Table 1 highlights the importance of enforcing low complexity during software integration verification, indicating the need to introduce the cyclomatic complexity concept of integrated software components for effective verification and risk reduction. Similarly, Table 3 emphasizes the significance of an appropriate hierarchical structure (1a) and limited size and complexity of software components (1b) in software architectural design. These principles stress the management of complexity, size, and structural organization to achieve a well-balanced design aligned with ISO 26262 requirements. By incorporating strategies to handle cyclomatic complexity, such as minimizing decision points and independent paths, software architects can foster a structured and manageable design that ensures safety and reliability within the ISO 26262 framework.
?
In the automotive industry, it is recommended to have a cyclomatic complexity (CYC) of less than 10 for critical system software. While this guideline may align with ASIL (Automotive Safety Integrity Level) requirements, writing code with low complexity often results in increased code length and maintenance effort. Breaking down complex logic into smaller components may oversimplify the code, potentially sacrificing elegance and flexibility. Achieving a balance between complexity and performance can be challenging. To address these challenges, aiming for a CYC of less than 10 for ASIL C and D code, less than 20 for ASIL B and A, or it may be less than 30 for ASIL A requirements can be tolerable.
BMS Software and Functions Engineer
1 年Thank you for sharing, It is a challenging task as you stated, lowering the CYC means more sw units, more separate test cases, more interfaces definition ... ??