2011-12-05 3 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, 나는 다른 표현이에 기여하는 것을 이해하지 못하고 단지 7 case 문이있다, 그러나 (10)과 복잡성을 계산 복잡성.

많은 소스를 통해 검색했지만 전체 수를 계산할 수있는 목록을 가져올 수 없습니다.

아무도 도와 드릴 수 있습니까? 아니면 C# 코드에서 제어 흐름 다이어그램을 생성 할 수있는 도구가 있습니까?

+0

이 질문에 대한 답변이 없지만 스위치 분기 이외에 VS 예외가 발생할 수있는 경우를 계산합니다. 예를 들어,'elementId == null'의 경우, 메소드는 두 번째 행을 실행하려고하는 NullReferenceException을 던집니다. 이것은 별도의 실행 경로로 간주 될 수 있습니다. – Gebb

답변

3

가장 먼저 할 일은 시도하고 그래프를 사용 된 Cyclomatic 복잡성을 시각화입니다 ... 미리 감사합니다. 당신이 코드를 통해가는 동안 나는 더 나은 다음에 표정이 이해하기 위해 (10)을 계산하기 위해 관리 : 하나의 가능한 경로가 여기에 있기 때문에,

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

이 하나의 복잡성을을 가지고, 그리고 그 표시하는 것입니다 메시지.

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

우리가 2 일의 복잡성을이이 시간

는 경우 잠시, 대한, foreach 문에 추가됩니다. 이 경우에는 두 가지 경로가 있습니다. someCondition이 true이면 메시지가 표시되고 (첫 번째 가능한 경로) someCondition이 false이면 메시지가 표시되지 않습니다 (두 번째 가능한 경로).

당신은 Windows의 폐기의 구현에서의 모습은 다음과 같습니다 양식이있는 경우 :하기 위해 충족해야 다음

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

당신이 & & 두 값의 경우 3의 복잡성을이 내부의 표현을 평가하십시오. 즉, 이 모두disposing 인 경우 (components != null)이 참이면 첫 번째 경로가 있음을 의미합니다. disposing이 거짓이면 두 번째 경로가 있습니다. 세 번째 경로는 components이 null 일 수 있으므로 false로 평가됩니다. 그러므로 당신은 3의 순환 적 복잡성을 가지고 있습니다.

switch의 경우 +1을 받고, 내면에 나타나는 case (및 default) 개마다 +1이됩니다. 당신의 방법의 경우에, 당신은 과 switch을 합쳐서 8 개로 만들고 case 문을 6 개 가지고 있습니다.

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 인 이유를 알아내는 데 어려움을 겪을 수 있지만 작성중인 내용을 이해할 수는 없습니다.