2017-12-20 7 views
1

私が含まれていないこれらのelse-if条件をもっとたくさん持っています。循環器系の複雑さを減らすために、これをどのようにリファクタリングすることができますか?私はJavaでこの関数の循環的複雑度を軽減することができますどのように循環的複雑さを減らすために、複数のif文java

if (ONE.equalsIgnoreCase(eachTag.getNodeName())) 
{ 
    myclassDto.setOne(formatter 
      .getElementValueAfterNullCheckWithTrim((Element) eachTag)); 
} 
else if (TWO.equalsIgnoreCase(eachTag.getNodeName())) 
{ 
    myclassDto.setTwo(formatter 
      .getElementValueAfterNullCheckWithTrim((Element) eachTag)); 
} 
else if (THREE.equalsIgnoreCase(eachTag.getNodeName())) 
{ 
    myclassDto.setThree(formatter 
      .getElementValueAfterNullCheckWithTrim((Element) eachTag)); 
} 
else if (FOUR.equalsIgnoreCase(eachTag.getNodeName())) 
{ 
    myclassDto.setFour(formatter 
      .getElementValueAfterNullCheckWithTrim((Element) eachTag)); 
} 
else if (FIVE.equalsIgnoreCase(eachTag.getNodeName())) 
{ 
    myclassDto.setFive(formatter 
      .getElementValueAfterNullCheckWithTrim((Element) eachTag)); 
} 
else if (SIX.equalsIgnoreCase(eachTag.getNodeName())) 
{ 
    myclassDto.setSix(formatter 
      .getElementValueAfterNullCheckWithTrim((Element) eachTag)); 
} 

答えて

2

それはあなたが(それは本当に複雑ではないですが)、あれば同じように「複雑」だながら、あなたのコードは、読みやすく、次のようになります。

  • は(GETNODENAMEの値を抽出し、switch文
  • を使用します)
  • 予めgetElementValueAfterNullCheckWithTrim(によって返される値を抽出する)

    String value = formatter.getElementValueAfterNullCheckWithTrim((Element) eachTag); 
    String nodeName = eachTag.getNodeName(); 
    
    switch (nodeName) { 
        case ONE: 
         myclassDto.setOne(value); 
         break; 
        case TWO: 
         myclassDto.setTwo(value); 
         break; 
        ... 
    } 
    
  • 予め

編集: あなたのDTOをリファクタリングする場合がありますので、それは

myclassDto.setValue(nodeName, value) 
+0

実際のアーキテクチャを考えれば、DTOリファクタリング部分は非常に重要です。スイッチを使用すると –

+0

を使用すると、複雑さが19から17に低下します。しかし、10に減らす必要があります。 – user3431624

+0

私の答えで言ったように、 'switch'を使うことは' if'を使うのと同じように複雑です。それはもっと読みやすい。 DTOのリファクタリングはどうですか?あなたのDTOがデータを受け入れるのに効率的でない、つまり100セットの***()メソッドを持っているなら、あなたはより低い複雑さの数字を得るだろうと思っています。 – SurfMan

1

のように、私は彼らが対応関数に文字列のマッピングを定義したい、使用する方が簡単です。これは静的にすることができます。

次に、マッピングをループして、適切なもの(filter)を見つけて機能を適用することができます。

private static final Map<String, BiConsumer<MyClassDto, Element>> MAPPING = new HashMap(); 

static 
{ 
    mapping.put(ONE, MyClassDto::setOne); 
    mapping.put(TWO, MyClassDto::setTwo); 
    //... 
    mapping.put(SIX, MyClassDto::setSix); 
} 


//... 

MAPPING.entrySet().stream() 
    .filter(pair -> pair.getKey().equalsIgnoreCase(eachTag.getNodeName())) 
    .map(Map.Entry::getValue) 
    .forEach(func -> func.accept(
     myClassDto, 
     formatter.getElementValueAfterNullCheckWithTrim((Element) eachTag) 
    )); 

あなたはMAPPINGequalsIgnoreCase(例えば「AAA」と「AAA」)によって平等に扱われるの異なる鍵を含めることができる場合を検討する必要があります。

forEachdaniuのように)の代わりにfindFirst().ifPresent()を使用するのが1つの解決策ですが、これはいくつかのエラーケースをマスクする可能性がありますので注意して使用してください。

+0

これは私のアプローチでしたが、同等の結果で 'forEach'を行うことはできません。複数のマッピングがトリガされ、複数の「BiConsumer」が呼び出される可能性があります。したがって、 'findFirst()。ifPresent()'。また、ストリームの外側の 'getNodeName'もおそらく。 – daniu

+0

@daniu私が持っている問題は、 'findFirst'がいくつかのバグを見つけにくいかもしれないということです。異なるケース文字列( "AAA"と "aaa")を持つ2つのマッピングがあり、 'HashMap'に予測可能な反復順序がない場合、' findFirst'を使用すると、各関数の間で前後にスワップすることがあります。これは追跡するのが非常に難しいでしょう。 2つの「等しい」マッピングがないことを保証したい場合は、キーを反復して重複をチェックする関数を記述する方がよいでしょう。 – Michael

+0

合意しましたが、コードに "aaa"と "AAA"を追加すると、両方とも「BiConsumer」と呼ばれます。たとえば、一意性制約を持つデータベースに一致を追加すると、それは失敗します。私は 'mapPING'の' LinkedHashMap'で 'findFirst'を使用したいと思います(これは確定的な繰り返しを提供すると思います)。 OPの単純なケースではこれが問題ではありません;) – daniu

関連する問題