Whenever I lint a piece of code I'm working on I get the This function's cyclomatic complexity is too high. (7)
. But I'm a bit confused on how I could rewrite it in such way so it works.
This would be the function that keeps throwing that message:
function () {
var duration = +new Date() - start.time,
isPastHalf = Number(duration) < 250 && Math.abs(delta.x) > 20 || Math.abs(delta.x) > viewport / 2,
direction = delta.x < 0;
if (!isScrolling) {
if (isPastHalf) {
if (direction) {
this.close();
} else {
if (this.content.getBoundingClientRect().left > viewport / 2 && pulled === true) {
this.close();
return;
}
this.open();
}
} else {
if (this.content.getBoundingClientRect().left > viewport / 2) {
if (this.isEmpty(delta) || delta.x > 0) {
this.close();
return;
}
this.open();
return;
}
this.close();
}
}
}
I would like to hear some advice on how I could structure my code in such way so I avoid this kind of situations.
Well you have only two actions in your code, but much too many conditions. Use a single if-else-statement, and boolean operators in the condition. If that was impossible, you could at least
Here's your function simplified:
and shortened:
I would prefer a simple and less nested code like below:
Bergi has already given a correct answer, but it's still too complex for my taste. Since we're not using fortran77 I think we're better off using an early return. Also, the code may be further clarified by introducing extra variables:
Actually all those
return
statements are confusing the issue, but they offer a hint to the solution.How about:
And as for:
Simplify:
(Aside: The original post left out a closing brace. If you (OP) intended that the function continues past your post, then this answer is wrong (but you should've made that clearer))
Result: We've eliminated two (repeated) decisions:
Firstly, there are three results your function can have: do nothing, call
this.close()
or callthis.open()
. So ideally the resulting function will just have one if statement which determines which result is used.The next step is to extract all boolean code into variables. Eg
var leftPastCenter = this.content.getBoundingClientRect().left > viewport / 2
.Finally, use boolean logic to simplify it step by step.
Here is how I did it:
Firstly, extract all boolean variables:
The easiest part to pull out is realizing if
isScrolling
is true, nothing ever happens. This immediately gets rid of one level of nesting:Now look at the cases
this.open()
are called. IfisPastHalf
is true,this.open()
is only called when!direction
and!(leftPastCenter && isPulled)
. IfisPastHalf
is false, thenthis.open()
is only called whenleftPastCenter
and!positiveDelta
:Flipping the ifs (so
this.close()
comes first), makes the code a bit neater, and gives my final version:It is difficult for me to do more, without knowing your codebase. One thing to note is
direction
and my new variablepositiveDelta
are nearly identical - you could possible removepositiveDelta
and just usedirection
. Also,direction
isn't a good name for a boolean, something likemovingLeft
would be better.