-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
High cyclomatic complexity on switch statements #840
High cyclomatic complexity on switch statements #840
Comments
Am I right, that both variants are equal? CC for the first case should be 2. |
I'm not an expert at all, but as I understand cyclomatic complexity, you have to count any individual path of the control flow graph of a function. And |
I'm not an expert either. My point is: cyclomatic complexyty counts different flows through a method. And it's usefull, because you can understand, how many tests should be written for this method. So, |
Hi, I'm still not an expert ;) But I can't agree with the knowledge so far.
has a complexity of 7 while a function with this body
only get's 3 as it's complexity value - even if the first version looks easier to read (simply think of a version with n more entries - while the complexity of the first function is 7+n, the second one remains 3). According to http://gmetrics.sourceforge.net/gmetrics-CyclomaticComplexityMetric.html, the analysis is pretty easy
If this is true (for Java), I think we should not add more complexity to this system by adding some exceptions. I only just started to read http://www.literateprogramming.com/mccabe.pdf, but this fits to my understanding of "maximum number of linearly independent circuits" in the control flow graph... Simply try to draw such a graph for your function.. |
According to this list, both of your functions should have a complexity of 4 (what's comparable). |
I just found another source (http://www.verifysoft.com/en_mccabe_metrics.html) that describes the analysis this way:
While this sounds quite intuitive in the first place, I can't agree with the explanation: "Case branch does not increase v(G), because it does not increase the number of branches in the control flow". This is simply not true. Also |
Thank's. That's an interesting article. |
Here are results: So, you were right. |
Oh. Strange things =). Last commit. |
Hey. Take a look. |
As stated above, I can't follow the argumentation of verifysoft. Especially because they write
So |
Ringht. I'm reading McCabe PDF with Fortran examples =). The truth is out there. |
The original cyclomatic complexity counted the number of decision points, which exclude && and ||. The concept of extended cyclomatic complexity includes Boolean operators to attempt to also convey the complexity of the decisions themselves. The question here isn't which one is right, but rather which one JSHint is attempting to follow. Perhaps both? Google "extended cyclomatic complexity" for verification. |
Just to clarify my previous comment, cases where |
Can you please name one case, where var x = y && z;
// goes to
var x;
if (y == z) {
x = true;
} else {
x = false;
}
if (x && y) {
} else {
}
// goes to
if (x) {
if (y) {
} else {
// see below
}
} else {
// same as in the above else branch
}
while (x && y) {
}
// goes to
while (true) {
if (!x) break;
if (!y) break;
}
// or something similar |
Fair enough. The language that cyclomatic complexity was original targeted to analyze didn't have a pervasive "default assign" pattern. You can exclude the caveat about In general, original cyclomatic complexity meant the number of branching code paths... the number of blocks that get executed as a result of a conditional split. |
Well, actually no. I take it back again, I'm confusing myself. The reason I made that caveat is that the assignment that takes place is due to the side effects of the conditional. Original cyclomatic complexity talks about the number of control flow paths: http://testingwarrior.blogspot.com/2011/12/cyclomatic-complexity-with-example.html If your boolean |
I don't see the point in that example, it definitely doesn't do what the console log's imply: function f(someVal) {
switch (someVal) {
case 1 || 2 || 3: // <-- this evaluates to `1`
console.log("1 to 3")
break;
default:
console.log("Other")
break;
}
}
f(1);
// "1 to 3"
f(2);
// "Other" |
Why && doesn't increase cyclomatic complexity count ? function functionWithCyclomaticComplexityDueToAndOperator_1(a, b) {
return a && b;
}
// => jshint return complexity 1
function functionWithCyclomaticComplexityDueToOrOperator_2(a, b) {
return a || b;
}
// => jshint return complexity 2
function functionWithCyclomaticComplexityDueToNegativeAndOperator_1(a, b) {
return !(!a && !b);
}
// => jshint return complexity 1 Looks strange... I can increase the complexity of the code without be warned ? |
I don't know how exactly it's working but let me guess it's because the analysis is done on bytecode and not source? So it's after compiling and the last statement got optimized by compiler into the first one. |
The function with && has only one path, as both sides of && are always evaluated. || has two paths: the left side lone evaluation and the left + right evaluation |
@rwaldron, sounds like a bug to me. |
Yes, and for future reference I should avoid commenting or reviewing issues on days that I'm playing video games or otherwise not focusing on the subject at hand. |
Lol. that's like every day for me. |
So there two different issues?
BTW:Sorry for reviving old thread. |
No, you just made this up! This is just a bug like any other in the source code. A condition that should be increasing complexity isn't. |
Ok never mind.. I said in beginning I don't know how this one exactly works and the whole thread is a bit confusing. So for !(!a && !b) and a && b should be given 2. |
is cyclomatic complexity worthy of its own unit test file? Or should it just be a part of core tests... I could be wrong but I'm not seeing any current tests around it. |
@paul-wade Line 2089 in 9d021ee
|
Thanks @lukeapage I missed that |
@lukeapage The original issues is in regards to switch statements. Does your pull request handle just && or both? |
if you read through this issue carefully i think the conclusion was that either |
I'm not sure logical consistency is the right thinking here. Logically sure || and a few fall through case statements should be the same. In terms of maintaining code would you find it easier to read a switch with a few fall through case statements or an if with a bunch of ||. I'd also argue that visual studio, code maid, reshaper, intellij consistently do not increase complexity for an empty case. Isn't consistency with other languages/analyzers also important? |
If you search around about cyclomatic complexity you will see some implement OR/empty switch cases as increasing complexity and some don't. But they are always consistent because they are equivalent code. It is highly likely those c# tools are showing info from the same source. Are you sure they are increasing complexity for || but not for empty case statements? JavaScript is a different language from c# and I've found code measuring PHP that does count OR - so it may also be a microsoft convention - none of which are reasons for us to go one way or another. JSHint has included OR and empty switch for a long time, so there isn't really a reason to change that I see. |
interestingly http://jscomplexity.org/ has the exact same behaviour as jshint at the moment (+1 for ||, +1 for empty switch, +0 for &&) though it is an option. |
Bountysource decided to update their Terms of Service:
|
Thanks for the heads-up, Gustavo! It would be a shame for that money to go back to Bountysource, especially when Luke contributed a fix almost five years ago. I've merged the fix, resolving the conflicts that have been introduced in a half-decade of development. |
Currently, every case in a switch block increments the cyclomatic complexity regardless of whether or not it falls through.
This has a complexity of 4:
This has a complexity of 2 while being logically equivalent:
I'm not an expert in cyclomatic complexity by any means, so I'm honestly not sure if this is correct or not. Even if this is the expected behavior, it seems like it would be nice to at least have a flag which could make these two function calculate the same cyclomatic complexity.
The text was updated successfully, but these errors were encountered: