web-dev-qa-db-ja.com

これの循環的複雑度を減らすにはどうすればよいですか?

オブジェクトを受け取り、検出したオブジェクトのタイプに基づいて何かを行うメソッドがあります。

void receive(Object object) {
    if (object instanceof ObjectTypeA) {
        doSomethingA();
    }
    else {
        if (object instanceof ObjectTypeB) {
            doSomethingB();
        }
        else {
            if (object instanceof ObjectTypeC) {
                doSomethingC();
            }
            else {
                if (object instanceof ObjectTypeD) {
                    doSomethingD();
                }
                else {
                    // etc...
                }
            }
        }
    }
}

循環的複雑度を減らすにはどうすればよいですか?調べてみたが、あまり役に立たなかった。

16
Nathan

これにオブジェクト指向のアプローチを活用できませんか? doSomething()メソッドを持つインターフェースを作成してから、目的の動作を実装するサブクラスを作成しますか?次に、object.doSomething()を呼び出すと、適切な動作が実行されますか?

42
laz

循環的複雑度は、コードのグラフ構造に基づく尺度です。具体的には、コードを通過する可能性のあるパスの数に基づいています。詳細は こちら を参照してください。 CCと一般的なプログラマーがコードの複雑さとして認識するものとの間には相関関係がありますが、それらは同じものではありません。例えば:

  • CCはコードのセマンティクスを考慮しません。例えば呼び出されているそのようなメソッドやそのメソッド、またはアルゴリズムの数学的特性。

  • CCは、設計およびコーディングパターンを考慮していません。したがって、CCが複雑だと言っていることは、使用されているパターンを理解している人にとっては単純なことかもしれません。

CCと実際のコードの複雑さの関係は、IQと実際のインテリジェンスの関係に似ていると言えます。

したがって、循環的複雑度は、コードの複雑な部分がどこにあるかの指標として扱う必要があります...複雑度やコード品質の真の測定値としてではありません。確かに、非常に複雑なコードは必ずしも必ずしも品質が悪いわけではありません。多くの場合、複雑さは固有のものであり、それを取り除こうとすることは問題を悪化させるだけです。


この特定の例では、高いCCメジャーは、一般的なプログラマーに問題を引き起こすようなものには対応していません。最良の答え(IMO)は、メソッドをそのままにすることです。誤検知としてチョークアップします。

28
Stephen C
void receive(ObjectTypeA object) {
        doSomethingA();
}

void receive(ObjectTypeB object) {
        doSomethingB();
}

void receive(ObjectTypeC object) {
        doSomethingC();
}

...

// Your final 'else' method
void receive(Object object) {
        doSomethingZ();
}
9
MrCeeJ