Javaプロジェクト全体の循環的複雑度を計算するには? どの方法も複雑ですが、それらすべてを 1 つの数値メトリックに集約するにはどうすればよいですか? アイデアや既存の方法はありますか?
私はツールを探しているのではなく、アルゴリズムを探しています。
多くの1
-complexity メソッドがあり、実際にはそれほど複雑ではありませんが、コードベースにとって重要性が低いため (ほとんどの場合)、単純な平均はほとんど機能しません。
Javaプロジェクト全体の循環的複雑度を計算するには? どの方法も複雑ですが、それらすべてを 1 つの数値メトリックに集約するにはどうすればよいですか? アイデアや既存の方法はありますか?
私はツールを探しているのではなく、アルゴリズムを探しています。
多くの1
-complexity メソッドがあり、実際にはそれほど複雑ではありませんが、コードベースにとって重要性が低いため (ほとんどの場合)、単純な平均はほとんど機能しません。
コード メトリクスについては本全体が書かれているので、より具体的な質問をしているのは幸運です。Java の循環的複雑度の場合、5 または 6 の循環的複雑度を超えるメソッドの数を見つけることができます (ここで数を選択します)。この数がメソッド数の特定の割合を超える場合、全体的な循環的複雑度は低くなります。パーセンテージの適切な数値はプロジェクトのサイズに完全に依存するため、メソッドの数だけで割る代わりに、次のように大きな数に対してゆっくりと成長させることで、除算のメソッド数の重みを減らすことができます。プロジェクトの成長に合わせてより安定させるための平方根または対数。
多分このようなもの:
public double evaluateCyclomaticComplexity(List<MethodStat> methodStats) {
int bad = 0;
for (MethodStat methodStat : methodStats)
if (methodStat.getCyclomaticComplexity() >= 6)
bad++;
double denominator = Math.sqrt(methodStats.size());
return bad * 100.0 / denominator;
}
ここで返される数値が小さいほど良いです。非常に悪いプロジェクトの場合、これは 100 より大きい値を返します。
分母関数は、コード ベースが大きくなるにつれて複雑さが増していくのにどれだけの速さで対応できるかを表す必要があります。通常、コードが大きくなるにつれて関数ごとの CC を低くして保守しやすくする必要があるため、プロジェクトのサイズが大きくなるにつれてゆっくりと大きくなるものが最適です。
テストし、微調整するなどしてください。最終的に、コード メトリクスを正しく取得するのは難しいことです。これは、数字を使用して「保守性」を表すオープン ソース ソフトウェアに関するジャーナル論文をいくつか読んだ後で証明できます。ここで思いついたものは、十分な時間を費やせば大幅に改善される可能性があります。
その式を見つけました:
TCC = Sum(CC) - Count(CC) + 1
TCC: Total CC
Sum(CC): Sum of CC of all functions
Count(CC): Number of functions
ソース: http://www.aivosto.com/project/help/pm-complexity.html
しかし、おそらくそれはあまりにも限定的です。
別のアイデアは、プログラムの呼び出しグラフをプログラム自体と見なし、呼び出しグラフの CC を計算することです。ノードは CC によって重み付けされます。(実現可能かどうかはわかりませんが、単なるアイデアです)
参考になるかわかりませんが、私の考えを述べたいと思います。グローバル深度カウンターを使用して、メソッド呼び出しの深度を取得し、メソッド呼び出しごとに更新できます。ここでは、同じスニペットがすべてのメソッドに手動で挿入されていることがわかりますが、すべてのメソッドにコードを自動挿入するための解決策があるかもしれません。スタック トレースの長さのレベルで、集約された複雑さを計算できると思います。
public class Cyclomatic
{
public static int max = Integer.MIN_VALUE;
static void a()
{
b();
int temp = Thread.currentThread().getStackTrace().length;
if (temp > max)
max = temp;
}
static void b()
{
c();
int temp = Thread.currentThread().getStackTrace().length;
if (temp > max)
max = temp;
}
static void c()
{
int temp = Thread.currentThread().getStackTrace().length;
if (temp > max)
max = temp;
}
public static void main(String[] args)
{
a();
System.out.println(max);
}
}
出力:
5