Rol*_*and 15 javascript cyclomatic-complexity jshint
每当我拿出一段我正在处理的代码时,我就得到了This function's cyclomatic complexity is too high. (7).但我对如何以这种方式重写它有点困惑,所以它的工作原理.
这将是不断抛出该消息的函数:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想听听一些关于如何以这种方式构建代码的建议,以避免这种情况.
Ber*_*rgi 24
那么你的代码中只有两个动作,但条件太多了.在条件中使用单个if-else语句和布尔运算符.如果这是不可能的,你至少可以
这是你的功能简化:
var duration = +new Date() - start.time,
isPastHalf = Number(duration) < 250 && Math.abs(delta.x) > 20 || Math.abs(delta.x) > viewport / 2,
isFarRight = this.content.getBoundingClientRect().left > viewport / 2,
direction = delta.x < 0;
if (!isScrolling) {
if (isPastHalf) {
if (direction)
this.close();
else {
if (isFarRight && pulled)
this.close();
else
this.open();
}
} else {
if (isFarRight) {
// Looks like the opposite of `direction`, is it?
if (this.isEmpty(delta) || delta.x > 0)
this.close();
else
this.open();
} else
this.close();
}
}
Run Code Online (Sandbox Code Playgroud)
并缩短:
var duration = +new Date() - start.time,
isPastHalf = Number(duration) < 250 && Math.abs(delta.x) > 20 || Math.abs(delta.x) > viewport / 2,
isFarRight = this.content.getBoundingClientRect().left > viewport / 2,
direction = delta.x < 0,
undirection = this.isEmpty(delta) || delta.x > 0;
if (!isScrolling) {
if ( isPastHalf && ! direction && !(isFarRight && pulled)
|| !isPastHalf && !undirection && isFarRight )
this.open();
else
this.close();
}
Run Code Online (Sandbox Code Playgroud)
首先,你的函数可以有三个结果:什么都不做,调用this.close()或调用this.open()。所以理想情况下,结果函数只有一个 if 语句来确定使用哪个结果。
下一步是将所有布尔代码提取到变量中。例如var leftPastCenter = this.content.getBoundingClientRect().left > viewport / 2。
最后,使用布尔逻辑一步一步地简化它。
这是我如何做到的:
首先,提取所有布尔变量:
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,
leftPastCenter = this.content.getBoundingClientRect().left > viewport / 2,
positiveDelta = this.isEmpty(delta) || delta.x > 0,
isPulled = pulled === true; // I'll assume the test is needed rather than just using pulled.
if (!isScrolling) {
if (isPastHalf) {
if (direction) {
this.close();
} else {
if (leftPastCenter && isPulled) {
this.close();
return;
}
this.open();
}
} else {
if (leftPastCenter) {
if (positiveDelta) {
this.close();
return;
}
this.open();
return;
}
this.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
最容易退出的部分是意识到如果isScrolling是真的,什么都不会发生。这立即摆脱了一层嵌套:
// above same
if (isScrolling) { return; }
if (isPastHalf) {
if (direction) {
this.close();
} else {
if (leftPastCenter && isPulled) {
this.close();
return;
}
this.open();
}
} else {
if (leftPastCenter) {
if (positiveDelta) {
this.close();
return;
}
this.open();
return;
}
this.close();
}
}
Run Code Online (Sandbox Code Playgroud)
现在来看一下this.open()被调用的情况。如果isPastHalf为真,this.open()则仅在!direction和时调用!(leftPastCenter && isPulled)。如果isPastHalf为假,则this.open()仅在leftPastCenter和时调用!positiveDelta:
// above same
if (isScrolling) { return; }
if (isPastHalf) {
if (!direction && !(leftPastCenter && isPulled)) {
this.open();
} else {
this.close();
}
} else {
if (leftPastCenter && !positiveDelta) {
this.open();
} else {
this.close();
}
}
Run Code Online (Sandbox Code Playgroud)
翻转 ifs(所以this.close()先来),使代码更整洁,并给出我的最终版本:
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,
leftPastCenter = this.content.getBoundingClientRect().left > viewport / 2,
positiveDelta = this.isEmpty(delta) || delta.x > 0,
isPulled = pulled === true; // I'll assume the test is needed rather than just using pulled.
if (isScrolling) { return; }
if (isPastHalf) {
if (direction || (leftPastCenter && isPulled)) {
this.close();
} else {
this.open();
}
} else {
if (!leftPastCenter || positiveDelta) {
this.close();
} else {
this.open();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在不了解您的代码库的情况下,我很难做更多事情。需要注意的一件事是direction,我的新变量positiveDelta几乎相同 - 您可以删除positiveDelta并仅使用direction. 此外,direction对于布尔值来说,这不是一个好名字,像movingLeft这样的名字会更好。