此方法的圈复杂度大于授权
The Cyclomatic Complexity of this method is greater than authorized
我正在使用以下方法检查 null 或空字段:
public boolean isVoNotNull(){
return null != this.cardNo && StringUtils.isNotBlank(this.cardNo)
&& null != this.otp && StringUtils.isNotBlank(this.otp)
&& null != this.password && StringUtils.isNotBlank(this.password)
&& null != this.userid && StringUtils.isNotBlank(this.userid)
&& null != this.type && StringUtils.isNotBlank(this.type)
&& null != this.walletMobileNo && StringUtils.isNotBlank(this.walletMobileNo);
}
但是在使用 SonarLint 验证此代码时出现异常
EXCEPTION : The Cyclomatic Complexity of this method "isVoNotNull" is
12 which is greater than 10 authorized.
如何解决此异常或如何消除代码的复杂性?
将字符串添加到数组并使用循环检查是否为空而不是空白。当然是最差的表现,但应该打破那个无感限。
示例代码:
public boolean isVoNotNull(){
string [] stringsToCheck = new string[]{
this.cardNo,
this.otp,
// ...
}
//return CheckStringArrayNotNull(stringsToCheck);
return StringUtils.isNoneBlank(stringsToCheck);
}
// high chance this method already exists inside StringUtils
// INFACT FOUND! :)
private boolean CheckStringArrayNotNull( string [] stringsToCheck){
for(int i=0; i<stringsToCheck.length(); i++)
if( StringUtils.isNotBlank( stringsToCheck[i]) == false)
return false;
return true;
}
甚至更好,(编辑:@msandiford 似乎在这个解决方案上按时打败了我)
public boolean isVoNotNull(){
return StringUtils.isNoneBlank(cardNo, otp, ...);
}
您当然可以分解成更多方法来降低圈复杂度,但这会使 class 更难阅读和理解。代码指标应该只用于调查问题,而不是作为开发口头禅,例如我可以采用一个非常愚蠢的 class 有 100 个方法,每个方法的圈复杂度为 100 并重构它以使其具有完美的代码指标但是无法理解。永远不要看代码指标,在不使用编码指标的情况下思考好的解决方案。
StringUtils.isNotBlank
"Checks if a CharSequence is not empty (""),不为空且不只有空格。"
函数已经检查对象是否为空,那么你可以简化
public boolean isVoNotNull() {
return StringUtils.isNotBlank(this.cardNo)
&& StringUtils.isNotBlank(this.otp)
&& StringUtils.isNotBlank(this.password)
&& StringUtils.isNotBlank(this.userid)
&& StringUtils.isNotBlank(this.type)
&& StringUtils.isNotBlank(this.walletMobileNo);
}
要减少条件运算符的数量,您可以这样做:
public boolean isVoNotNull(){
Boolean[] condition = new Boolean[] {
StringUtils.isNotBlank(this.cardNo),
StringUtils.isNotBlank(this.otp),
StringUtils.isNotBlank(this.password),
StringUtils.isNotBlank(this.userid),
StringUtils.isNotBlank(this.type),
StringUtils.isNotBlank(this.walletMobileNo)
};
return BooleanUtils.and(condition);
}
也许有点棘手,但它有效
正如其他人指出的那样,null
检查是多余的,因为 isNotBlank
也会检查它。
因此,如果您使用的是 Apache StringUtils 3.2 或更高版本,则只需使用 StringUtils.isNoneBlank(...)
public boolean isVoNotNull() {
return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}
如果您使用的是较早的版本,您可以轻松编写一个:
public static boolean isNoneBlank(CharSequence... seqs) {
for (CharSequence seq : seqs) {
if (StringUtils.isBlank(seq))
return false;
}
return true;
}
或在Java 8:
public static boolean isNoneBlank(CharSequence... seqs) {
return Stream.of(seqs).allMatch(StringUtils::isNotBlank);
}
您需要分析重复的代码并将其重构为可重用的方法。
鉴于您的原始代码段,
public boolean isVoNotNull() {
return null != this.cardNo && StringUtils.isNotBlank(this.cardNo)
&& null != this.otp && StringUtils.isNotBlank(this.otp)
&& null != this.password && StringUtils.isNotBlank(this.password)
&& null != this.userid && StringUtils.isNotBlank(this.userid)
&& null != this.type && StringUtils.isNotBlank(this.type)
&& null != this.walletMobileNo && StringUtils.isNotBlank(this.walletMobileNo);
}
我们可以识别出以下重复部分:
null != this.xxx && StringUtils.isNotBlank(this.xxx)
鉴于 StringUtils#isNotBlank()
already 检查 null
,我们可以进一步简化它。
StringUtils.isNotBlank(this.xxx)
鉴于您需要调用它的次数可变,最好将其重构为采用 variable number of arguments 的方法,该方法在循环中检查它们。
public static boolean isNoneBlank(String... strings) {
for (String string : strings) {
if (!StringUtils.isNotBlank(string)) {
return false;
}
}
return true;
}
或者,如果您已经在 Java 8 上获得 Streams and Lambda 支持:
public static boolean isNoneBlank(String... strings) {
return Arrays.stream(strings).allMatch(StringUtils::isNotBlank);
}
现在您可以如下使用它:
public boolean isVoNotNull() {
return isNoneBlank(this.cardNo, this.otp, this.password, this.userid, this.type, this.walletMobileNo);
}
您可以通过删除不必要的 this
.
进一步减少样板文件
public boolean isVoNotNull() {
return isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}
这一切都是Don't Repeat Yourself (DRY)软件工程原理的应用。
也就是说,正如 pointed out, it turns out that Apache Commons Lang StringUtils
has since version 3.2 already正是这个方法。因此,如果您还没有,请考虑将 Apache Commons Lang 升级到至少 3.2。
public boolean isVoNotNull() {
return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}
我正在使用以下方法检查 null 或空字段:
public boolean isVoNotNull(){
return null != this.cardNo && StringUtils.isNotBlank(this.cardNo)
&& null != this.otp && StringUtils.isNotBlank(this.otp)
&& null != this.password && StringUtils.isNotBlank(this.password)
&& null != this.userid && StringUtils.isNotBlank(this.userid)
&& null != this.type && StringUtils.isNotBlank(this.type)
&& null != this.walletMobileNo && StringUtils.isNotBlank(this.walletMobileNo);
}
但是在使用 SonarLint 验证此代码时出现异常
EXCEPTION : The Cyclomatic Complexity of this method "isVoNotNull" is 12 which is greater than 10 authorized.
如何解决此异常或如何消除代码的复杂性?
将字符串添加到数组并使用循环检查是否为空而不是空白。当然是最差的表现,但应该打破那个无感限。
示例代码:
public boolean isVoNotNull(){
string [] stringsToCheck = new string[]{
this.cardNo,
this.otp,
// ...
}
//return CheckStringArrayNotNull(stringsToCheck);
return StringUtils.isNoneBlank(stringsToCheck);
}
// high chance this method already exists inside StringUtils
// INFACT FOUND! :)
private boolean CheckStringArrayNotNull( string [] stringsToCheck){
for(int i=0; i<stringsToCheck.length(); i++)
if( StringUtils.isNotBlank( stringsToCheck[i]) == false)
return false;
return true;
}
甚至更好,(编辑:@msandiford 似乎在这个解决方案上按时打败了我)
public boolean isVoNotNull(){
return StringUtils.isNoneBlank(cardNo, otp, ...);
}
您当然可以分解成更多方法来降低圈复杂度,但这会使 class 更难阅读和理解。代码指标应该只用于调查问题,而不是作为开发口头禅,例如我可以采用一个非常愚蠢的 class 有 100 个方法,每个方法的圈复杂度为 100 并重构它以使其具有完美的代码指标但是无法理解。永远不要看代码指标,在不使用编码指标的情况下思考好的解决方案。
StringUtils.isNotBlank
"Checks if a CharSequence is not empty (""),不为空且不只有空格。"
函数已经检查对象是否为空,那么你可以简化
public boolean isVoNotNull() {
return StringUtils.isNotBlank(this.cardNo)
&& StringUtils.isNotBlank(this.otp)
&& StringUtils.isNotBlank(this.password)
&& StringUtils.isNotBlank(this.userid)
&& StringUtils.isNotBlank(this.type)
&& StringUtils.isNotBlank(this.walletMobileNo);
}
要减少条件运算符的数量,您可以这样做:
public boolean isVoNotNull(){
Boolean[] condition = new Boolean[] {
StringUtils.isNotBlank(this.cardNo),
StringUtils.isNotBlank(this.otp),
StringUtils.isNotBlank(this.password),
StringUtils.isNotBlank(this.userid),
StringUtils.isNotBlank(this.type),
StringUtils.isNotBlank(this.walletMobileNo)
};
return BooleanUtils.and(condition);
}
也许有点棘手,但它有效
正如其他人指出的那样,null
检查是多余的,因为 isNotBlank
也会检查它。
因此,如果您使用的是 Apache StringUtils 3.2 或更高版本,则只需使用 StringUtils.isNoneBlank(...)
public boolean isVoNotNull() {
return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}
如果您使用的是较早的版本,您可以轻松编写一个:
public static boolean isNoneBlank(CharSequence... seqs) {
for (CharSequence seq : seqs) {
if (StringUtils.isBlank(seq))
return false;
}
return true;
}
或在Java 8:
public static boolean isNoneBlank(CharSequence... seqs) {
return Stream.of(seqs).allMatch(StringUtils::isNotBlank);
}
您需要分析重复的代码并将其重构为可重用的方法。
鉴于您的原始代码段,
public boolean isVoNotNull() {
return null != this.cardNo && StringUtils.isNotBlank(this.cardNo)
&& null != this.otp && StringUtils.isNotBlank(this.otp)
&& null != this.password && StringUtils.isNotBlank(this.password)
&& null != this.userid && StringUtils.isNotBlank(this.userid)
&& null != this.type && StringUtils.isNotBlank(this.type)
&& null != this.walletMobileNo && StringUtils.isNotBlank(this.walletMobileNo);
}
我们可以识别出以下重复部分:
null != this.xxx && StringUtils.isNotBlank(this.xxx)
鉴于 StringUtils#isNotBlank()
already 检查 null
,我们可以进一步简化它。
StringUtils.isNotBlank(this.xxx)
鉴于您需要调用它的次数可变,最好将其重构为采用 variable number of arguments 的方法,该方法在循环中检查它们。
public static boolean isNoneBlank(String... strings) {
for (String string : strings) {
if (!StringUtils.isNotBlank(string)) {
return false;
}
}
return true;
}
或者,如果您已经在 Java 8 上获得 Streams and Lambda 支持:
public static boolean isNoneBlank(String... strings) {
return Arrays.stream(strings).allMatch(StringUtils::isNotBlank);
}
现在您可以如下使用它:
public boolean isVoNotNull() {
return isNoneBlank(this.cardNo, this.otp, this.password, this.userid, this.type, this.walletMobileNo);
}
您可以通过删除不必要的 this
.
public boolean isVoNotNull() {
return isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}
这一切都是Don't Repeat Yourself (DRY)软件工程原理的应用。
也就是说,正如StringUtils
has since version 3.2 already正是这个方法。因此,如果您还没有,请考虑将 Apache Commons Lang 升级到至少 3.2。
public boolean isVoNotNull() {
return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}