web-dev-qa-db-ja.com

このメソッドの循環的複雑度は、許可されているよりも大きい

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で検証されている間、例外を下回る

例外:このメソッド「isVoNotNull」の循環的複雑度は12であり、許可されている10を超えています。

この例外を解決するにはどうすればよいですか、またはコードから複雑さを取り除くにはどうすればよいですか?

重複したコードを分析し、再利用可能なメソッドにリファクタリングする必要があります。

元のスニペットを指定すると、

_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()alreadynullをチェックするとすると、さらに単純化できます。

_StringUtils.isNotBlank(this.xxx)
_

これを可変回数呼び出す必要があることを考えると、ループ内ですべてをチェックする 可変数の引数 を取るメソッドにリファクタリングするのが最善です。

_public static boolean isNoneBlank(String... strings) {
    for (String string : strings) {
        if (!StringUtils.isNotBlank(string)) {
            return false;
        }
    }
    return true;
}
_

または、すでにJava 8 with Streams and Lambda support:

_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);
}
_

これはすべて Do n't Repeat Yourself(DRY) ソフトウェアエンジニアリングの原則のアプライアンスでした。

そうは言っても、 msandiford が指摘しているように、Apache Commons Lang StringUtilsはバージョン3.2以降 すでに まさにこのメソッドを持っていることがわかりました。したがって、まだ持っていない場合は、Apache CommonsLangを少なくとも3.2にアップグレードすることを検討してください。

_public boolean isVoNotNull() {
    return StringUtils.isNoneBlank(cardNo, otp, password, userid, type, walletMobileNo);
}
_
15
BalusC

他の人が指摘しているように、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);
}
4
clstrfsck

文字列を配列に追加し、空白ではなく無効性をループで確認します。もちろん最悪のパフォーマンスですが、その意味のない限界を超えるはずです。

コード例:

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, ...);
}

もちろん、循環的複雑度を減らすためにさらに多くのメソッドに割り込むこともできますが、それではクラスの読み方と理解がさらに難しくなります。コードメトリクスは、開発のマントラとしてではなく、問題を調査するためにのみ使用する必要があります。たとえば、循環的複雑度が100の100個のメソッドを持つ非常に愚かなクラスをリファクタリングして、完全なコードメトリクスを持つが理解できないようにすることができます。コードメトリクスを決して見ないでください。コーディングメトリクスを使用せずに良い解決策を考えてください。

1
CoffeDeveloper

StringUtils.isNotBlank

https://commons.Apache.org/proper/commons-lang/apidocs/org/Apache/commons/lang3/StringUtils.html#isNotBlank%28Java.lang.CharSequence%29

"CharSequenceが空(" ")ではなく、nullでも、空白だけでもないかどうかを確認します。"

関数はすでにオブジェクトがnullかどうかをチェックしているので、単純化できます

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);
}

多分少しトリッキーですが、それはうまくいきます

0
Troncador