zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Refactor this method to reduce its Cognitive Complexity from 18 to the 15 allowed.

to The 15 from this 18 method Allowed
2023-09-11 14:14:18 时间

Cognitive Complexity, Because Testability != Understandability

Cyclomatic Complexity   

Cognitive Complexity

With those rules in mind, let's take another look at those first two methods:

 

As I mentioned, one of the biggest beefs with Cyclomatic Complexity has been its treatment of switch statements. Cognitive Complexity, on the other hand, only increments once for the entire switch structure, cases and all. Why? In short, because switches are easy, and Cognitive Complexity is about estimating how hard or easy control flow is to understand.

On the other hand, Cognitive Complexity increments in a familiar way for the other control flow structures: for, while, do while, ternary operators, if/#if/#ifdef/..., else if/elsif/elif/..., and else, as well as for catch statements. Additionally, it increments for jumps to labels (goto, break, and continue) and for each level of control flow nesting:

 As you can see, Cognitive Complexity takes into account the things that make this method harder to understand than getWords - the nesting and the continue to a label. So that while the two methods have equal Cyclomatic Complexity scores, their Cognitive Complexity scores clearly reflect the dramatic difference between them in understandability.

 

In looking at these examples, you may have noticed that Cognitive Complexity doesn't increment for the method itself. That means that simple domain classes have a Cognitive Complexity of zero:

 

 So now class-level metrics become meaningful. You can look at a list of classes and their Cognitive Complexity scores and know that when you see a high number, it really means there's a lot of logic in the class, not just a lot of methods.

 

PDF https://www.sonarsource.com/docs/CognitiveComplexity.pdf

 Sequences of logical operators

For similar reasons, Cognitive Complexity does not increment for each binary logical operator. Instead, it assesses a fundamental increment for each sequence of binary logical operators.

For instance, consider the following pairs:

a && ba && b && c && d

a || ba || b || c || d

Understanding the second line in each pair isn’t that much harder than understanding the first.

On the other hand, there is a marked difference in the effort to understand the following two lines:

a && b && c && d

a || b && c || d

Because boolean expressions become more difficult to understand with mixed operators, Cognitive complexity increments for each new sequence of like operators. For instance

 

优化的话,只能把复杂的部分,拆分到另外一个方法里面。然后让原来的方法调用新的方法。

https://www.cnblogs.com/chucklu/p/12671821.html  只要是调用深度不是层层嵌套,就还可以接受

 

How can the cyclomatic complexity be 27 in a method with 13 event handler subscriptions?

Remember that the Code Analysis is looking at the IL in your assembly, not your source code. There is nothing in the IL that natively supports lambda expressions, so they are a construct of the compiler. You can find the specifics of what is ouput here. But basically your lambda expression is turned into a private static class that is an anonymous deligate. However, rather that create an instance of the anonymous deligate every time it is referenced in code, the deligate is cached. So each time you assign a lambda expression, it does a check to see an instance of that lambda deligate has been created, if so it uses the cached deligate. That generates an if/else in the IL increasing the complexity by 2. So in this functions complexity is 1 + 2*(lambda express) = 1 + 2 *(13) = 27 which is the correct number.

 

Does LINQ and Lambda expressions reduce Cyclomatic-complexity?

I suspect that the discrepancy may be due to deferred execution. When you use LINQ with lambda expressions, you're specifying code which will be run if you then iterate over the collection.

Personally I'm not so worried about cyclomatic complexity, but I'm absolutely sure that (when used appropriately) LINQ improves readability. That's what I really care about :)

 

3 Tips To Reduce Cyclomatic Complexity In C#

Tip #1 – SWITCH/CASE
 
Avoid use of switch/case statements in your code. Use Factory or Strategy design patterns instead.
不过目前的sonarqube扫描,会把switch case的复杂度算成1
 
Tip #2 – IF Expressions
Reduce IF expressions in your code. Use the Single Responsibility principle for extracting a piece of code to other methods and make the method for just one responsibility. That change will reduce Cyclomatic Responsibility and improve maintainability for your code.
 
Tip #3 – BE COOL
Don't kill yourself because of Cyclomatic Complexity.
 
It’s better to keep your code simple and follow single responsibility principles than refactoring all your code making it hard to understand.
 
“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” Martin Fowler.
 
Adopt an acceptable metric of CC(cyclomatic complexity) for your business and your daily life. This article is a guide for you, not a rule.