2011-12-05 7 views
3

C#プロジェクトの各メソッドに対して、グラフフローを計算する方法を示すために、コントロールフロー図(ノードとエッジを持つ単純なフローグラフ)を作成する必要がありますサイクロマティックな複雑さ。C#コードの完全なリスト循環的複雑さ+1 +1

私はまずVS 2010を使って循環的複雑さを数えました。そして、結果値がVSから数えられたものと同じであることを確認するためにグラフを作成します。しかし、私はここでいくつかの問題に出会った。なぜなら、どの表現が実際に循環的複雑さのために+1を考慮しているのかわからないからです。

のは、ここに一つの例を見てみましょう。この方法では

public ActionResult Edit(string id, string value) 
    { 
     string elementId = id; 
     // Use to get first 4 characters of the id to indicate which category the element belongs 
     string fieldToEdit = elementId.Substring(0, 4); 

     // Take everything AFTER the 1st 4 characters, this will be the ID 
     int idToEdit = Convert.ToInt32(elementId.Remove(0, 4)); 

     // The value to be return is simply a string: 
     string newValue = value; 

     var food = dbEntities.FOODs.Single(i => i.FoodID == idToEdit); 

     // Use switch to perform different action according to different field 
     switch (fieldToEdit) 
     { 
      case "name": food.FoodName = newValue; break; 
      case "amnt": food.FoodAmount = Convert.ToInt32(newValue); break; 
      case "unit": food.FoodUnitID = Convert.ToInt32(newValue); break; 
      // ** DateTime format need to be modified in both view and plugin script 
      case "sdat": food.StorageDate = Convert.ToDateTime(newValue); break; 
      case "edat": food.ExpiryDate = Convert.ToDateTime(newValue); break; 
      case "type": food.FoodTypeID = Convert.ToInt32(newValue); break; 

      default: throw new Exception("invalid fieldToEdit passed"); 

     } 
     dbEntities.SaveChanges(); 
     return Content(newValue); 
    } 

、VSが10として循環的複雑度を計算ししかし、わずか7 case文があり、私は他の式はに貢献し理解していません複雑。

私は多くの情報源から検索しましたが、の完全なリストは数えられませんでした。

誰でもこれを助けることができますか?または、C#コードからコントロールフローダイアグラムを生成できるツールがありますか?

は、あなたが最初にやるべきこと...事前に

+0

私はこれに答えていないが、私の推測では、スイッチブランチに加えて、例外がスローされる可能性があるケースを数えます。たとえば、 'elementId == null'の場合、メソッドは2行目の実行を試みるNullReferenceExceptionをスローします。これは別の実行パスと見なすことができます。 – Gebb

答えて

3

ありがとうグラフを使用してサイクロマティック複雑さを試してみて、視覚化です。

public void MyMethod() 
{ 
    Console.WriteLine("Hello ShennyL"); 
} 

そこここに一つだけの可能なパスがあり、そしてそれは表示することですので、これは、1の循環的複雑度を持っている:あなたのコードを経由しながら、私はより良い次でこの外観を理解するために10を計算するために管理しましたメッセージ。

public void AnotherMethod() 
{ 
    if (someCondition) 
    { 
     Console.WriteLine("Hello Shennly"); 
    } 
} 

今回は私たちが循環の複雑さが2になっています。foreachの場合は+1が加算されます。この場合、2つのパスがあります。 someConditionがtrueの場合、メッセージが表示され(最初の可能なパス)、someConditionがfalseの場合、メッセージは表示されません(2番目の可能なパス)。

あなたはそれがこのようになり、Windowsフォームでの廃棄の実装を見ている場合:

ここ
protected override void Dispose(bool disposing) 
{ 
    if (disposing && (components != null)) 
    { 
     components.Dispose(); 
    } 
    base.Dispose(disposing); 
} 

あなたは両方の値がために真でなければなりません& &の場合、3の循環的複雑度を持っています内部の式を評価する。つまり、の両方がdisposingの場合、(components != null)の場合は、最初のパスがあります。 disposingがfalseの場合、2番目のパスがあります。 3番目のパスは、componentsがヌルになる可能性があるため、falseと評価されます。したがって、あなたは3つの周期的複雑さを持っています。

switchの場合は、+1が表示され、内側に表示される各case(およびdefault)に対して+1が表示されます。あなたの方法の場合、caseの文が6つあり、defaultswitchの合計が8つあります。

public ActionResult Edit(string id, string value)     
{     
    string elementId = id; // First path, cyclomatic complexity is 1 

    string fieldToEdit = elementId.Substring(0, 4); // Same path, CC still 1 

    int idToEdit = Convert.ToInt32(elementId.Remove(0, 4)); // Same path, CC still 1 

    string newValue = value; // Same path, CC still 1 

    var food = dbEntities.FOODs.Single(i => i.FoodID == idToEdit); // Boolean expression inside your lambda. The result can go either way, so CC is 2. 

    switch (fieldToEdit) // Switch found, so CC is 3 
    {     
     case "name": food.FoodName = newValue; break; // First case - CC is 4 
     case "amnt": food.FoodAmount = Convert.ToInt32(newValue); break; // Second case - CC is 5 
     case "unit": food.FoodUnitID = Convert.ToInt32(newValue); break; // Third case - CC is 6 
     case "sdat": food.StorageDate = Convert.ToDateTime(newValue); break; // Fourth case - CC is 7 
     case "edat": food.ExpiryDate = Convert.ToDateTime(newValue); break; // Fifth case - CC is 8 
     case "type": food.FoodTypeID = Convert.ToInt32(newValue); break; // Sixth case - CC is 9 

     default: throw new Exception("invalid fieldToEdit passed"); // Defaul found - CC is 10 

    }     
    dbEntities.SaveChanges(); // This belongs to the first path, so CC is not incremented here.     
    return Content(newValue);     
}   
:あなたは(私はあなたのコードに私のコメントを追加し、あなたのコメントを削除しています)試してみて、それがこのように分けることができ、グラフの面であなたのコードを可視化する場合、私は、冒頭で述べたよう

私はいくつかの点で間違っているかもしれませんが、基本的にこれは循環的複雑さの計算の背後にあるアイデアです。また、これを減らすことができない場合があることを理解する必要があります(スイッチ/ケースを使用する必要がある場合は、CCが増加します)。さらに、変数にひどい名前がついている場合(コードを難読化しようとした場合のように)、循環的な複雑さは、命名がひどいことを理解できないため、低い値を返すことがあります。命名は複雑さを増し、コードでコメントを使用しない場合、6ヵ月後にサイクロマティックな複雑さが3である理由を理解するのは難しくなりますが、書かれていることは理解できません。

関連する問題