Should we prefer cognitive complexity over cyclomatic complexity?

I found the rule that scores 1 for a javascript function is unfair because it punishes functional programming practice of writting small composible functions

My project is getting into a state that the cyclomatic complexity is average and congnitive complexity is about 10% of average

As the congnitive complexity is claimed to be fairer and that is the case for me, why is Sonarqube keeping 2 complexity metrics anyway?

Hi,

Cyclomatic Complexity is about testability - what’s your minimum number of unit tests to exercise all the code? Cognitive Complexity is about understandability. So if you’re trying to put a measurement on this (admittedly inherently subjective) value then prefer Cognitive Complexity.

Does that make sense?

 
Ann

Hi,

Regarding testability, it makes sense only if a function is public

Consider the following example, the score is 6 for 6 lambda expressions

const getFullName = x => x.firstName +  '  '  + x.lastName;
const getSummary = x => `${getFullName(x)}, ${x.orders.length} orders`;
const postCodeEq = postCode => customer => customer.postCode === postCode;
const findSummariesByPostCode = postCode => customers => 
  customers
    .filter(postCodeEq(postCode))
    .map(getSummary);

If I changed it to imperative code, the score would be lowered to 3 for 1 function, 1 for for and 1 for if

const findSummariesByPostCode = (postCode, customers) => {
  const summaries =[ ]
  for (var i = 0; i < customers.length; i++) {
    var customer = customers[i];
    if (customer.postCode === postCode) {
      var fullName = customer.firstName +  '  '  + customer.lastName;
      var summary = `${fullName}, ${customer.orders.length} orders`;
      summaries.push(summary);
    }
  }
  return summaries;
}

But it doesn’t make sense to say the imperative version is less complex and more testable.

On the other hand, the cognitive complexity gets it right, 0 for the functional version and 2 for the imperative version

Thanks

Hi,

What language(s) are you examples in?

 
Thx,
Ann

Hi,
This is JavaSscript.

I noticed a function is not counted as 1 point for Java. I don’t know why different decisions were made for different languages

https://docs.sonarqube.org/latest/user-guide/metric-definitions/

Hi,

Thanks for getting back to me.

That’s an excellent question, and we’ve added it to the internal list for discussion.

 
Ann

Hi

Thanks for putting my issue on your list

I also took a look at our C# code and found out a plain DTO ended up with a complexity of 63 because each property consists of a pair of getter/setter which scores 2.

I think the rule that scores 1 for a function heavily distorts reality and should be removed

Thanks

Hi,

That’s just how Cyclomatic Complexity works. Remember, I said that Cyclomatic complexity is about testability. To thoroughly test your class you need at least one test case for each method, and that’s what’s being reflected in that “scores 1 for a function”.

But your perception that it “heavily distorts reality” is quite common among developers and one of the things that lead us to formulate Cognitive Complexity.

 
Ann

Hi,

Yes, my previous statement was not accurate. Public functions / methods do increase the need of additional test cases so it makes sense to +1

The issue I have been facing is about private/internal functions. It is a good and common practice to break down a big function to small functions with single responsibility, this kind of refactoring doesn’t increase the need of test cases