Let op! Internet Explorer wordt niet meer ondersteund. Hierdoor kan de website mogelijk niet goed functioneren, gebruik een alternatieve browser om optimaal gebruik te maken van deze website. Klik hier om een alternatieve browser te downloaden.

Demystifying Code Complexity

A Closer Look at Different Definitions of Code Complexity

Author:

Author Rob Goud

Rob Goud

Chief Services Officer Follow Rob Goud on LinkedIn

Welcome to the first installment of our blog series on code quality metrics! In this series, we’ll be exploring various code quality metrics that align with ISO 25010 standards and play a pivotal role in software development. At TIOBE Software, we’re dedicated to helping you understand the intricacies of code quality beyond the basics. Our motto, “When quality is more than a code checker,” reflects our commitment to providing you with insights that go beyond the surface. Let’s kick things off by delving into the fascinating world of “Code Complexity.”

The Complexity Conundrum

Code complexity of source code refers to how intricate or convoluted the code’s logic and structure are. It’s a crucial metric that directly impacts the quality, maintainability, and overall longevity of your software projects. As your codebase grows, so does its complexity, potentially leading to bugs, maintenance nightmares and reduced agility. As the saying goes, “Keep it simple, stupid,” but as we all know, reality often leans towards complexity.

When striving to develop high-quality software, it’s essential to strike a balance between functional richness and the complexity of your code. Complexity tends to creep into codebases, making them harder to understand, debug, and maintain. There’s a trade-off at play: while sophisticated algorithms and intricate structures might enhance functionality, they can also increase the risk of errors and hinder future enhancements.

Diverse Definitions

Code complexity is multifaceted, and there’s no one-size-fits-all definition. Different methodologies offer distinct ways of quantifying complexity. Let’s explore a few prominent ones:

  • McCabe Cyclomatic Complexity: This metric assesses code based on control flow. It counts decision points (e.g., if statements, loops) to estimate how many paths through the code exist. The higher the McCabe complexity, the more intricate the code’s control flow.
  • NPath Complexity: NPath dives into potential execution paths within code. It considers combinations of branching statements, painting a comprehensive picture of how convoluted code execution can be.
  • Cognitive Complexity: Cognitive complexity factors in how challenging code is for developers to comprehend. It weighs nested structures and logical operators, aiming to reflect how many mental leaps are needed to grasp the code’s behavior.
  • Halstead Difficulty: Halstead focuses on operator and operand counts. It’s a mathematical abstraction that quantifies program size and vocabulary to provide insight into code comprehension.

Let’s consider a simple Python function that determines whether the input parameter is a prime number.

Now, let’s quantify its complexities:

  • McCabe Cyclomatic Complexity (MCC): We can count the decision points (branches) in the function.
    • Decision points include the different if conditions and loops.
    • For the given function, the number of decision points (P): 7.
    • McCabe Cyclomatic Complexity (MCC) = P + 1 = 7 + 1 = 8
  • NPath Complexity: The NPath complexity is calculated by considering the number of possible paths through the code based on the different branches and decision points. It’s calculated as the sum of 2^(number of paths) per nesting level.
    • For the is_prime function, there are 3 if-statements and a while loop on the highest level and another if-statement within the while loop.
    • NPath complexity is: 2^4 + 2^1 = 18
  • Cognitive Complexity: Cognitive complexity takes into account nested control structures and their impact on code readability.
    • For the given function there is one while loop within the function and 4 if conditions with logical operators.
    • Cognitive Complexity = 5
  • Halstead Difficulty: Halstead complexity metrics are based on the program’s operands and operators. For the given function:
    • N1 = number of distinct operands = 10 (n, 1, False, 3, True, 2, 0, 5, I, 6)
    • N2 = number of distinct operators = 8 (<=, %, ==, or, =, *, +, +=)
    • n2 = total occurrences of operators = 17.
    • Halstead Difficulty (D) = (N1/2) * (n2/N2) = (10/2) * (17/8) ≈ 10.6

Conclusion: Navigating the World of Code Complexity

As we conclude this journey into the world of code complexity, it’s clear that the complexity metrics we’ve explored are like different lenses through which we can examine the intricacies of software code. McCabe’s decisive forks, NPath’s labyrinthine paths, cognitive complexity’s readability challenges, and Halstead’s mathematical puzzle – all contribute to a holistic understanding of code’s convolutions.

In our next blog, we’ll explain why it’s crucial to measure code complexity across your projects. We’ll unveil the insights and practical implications of these complexity metrics and how they serve as guiding lights for architects, developers, and quality assurance teams alike. Until then, embrace the complexity, balance it wisely, and keep your code quality soaring high.