code metrics – Complejidad Ciclomática ¿Qué tan complejo es tu código?

Esta métrica fue introducida por Thomas McCabe  en el año 1976. En ese año publicó un artículo donde argumentaba que la complejidad del código se da por el flujo de control (Control flow).

Flujo de control
Flujo de control

Artículos relacionados

La Complejidad Ciclomática (Cyclomatic Complexity) es una métrica que proporciona una medición de la complejidad lógica de nuestro código, está basado en la Teoría de grafos. Es una de las métricas de software de mayor aceptación, ya que ha sido concebida para ser independiente del lenguaje. El objetivo principal de esta métrica no es contar la cantidad de bucles (for, while, do, etc) sino contar el número de caminos diferentes que existen dentro de un fragmento de código. Por ese motivo algunos mencionan que el nombre más adecuado debería ser el de “Complejidad Condicional“. Además, con el resultado de este cálculo nos permite saber el número de pruebas que se deben hacer para abarcar el 100% del código.

Formula:

La complejidad ciclomática  de un método es = 1 + {el numero expresiones encontradas en un método}.

Estas expresiones son:

if | while | for | foreach | case | default | continue | && | goto  | || | catch | ternary operator ?: | ??

Para el cálculo de la complejidad ciclomática no se toman en cuenta las siguientes expresiones:

else | do | switch | try | using | throw | finally | return | object creation | method call | field access

Fuente: NDepend Code Metrics Definitions – Complejidad Ciclomática

Tabla de riesgos

El Software Engineering Institute (SEI) presento la siguiente tabla de riegos en su artículo Software Technology Reference Guide:

Complejidad ciclomática - tabla de riesgos
Complejidad ciclomática – tabla de riesgos

Ejemplos:

Nota: Estos cálculos se realizaron usando la herramienta Visual Studio Code Metrics, estos mismos pueden variar si se hacen usando la herramienta NDepend.

Caso 1:

Complejidad ciclomática: 1. Recuerden que por defecto siempre empieza en 1.

	void Caso1()
	{            
	}
	
Caso 2:

Complejidad ciclomática: 3. La expresión Else no es considerada para este cálculo. Solo se cuentan las expresiones IF.

	void Caso2()
	{
		var indice = 0;
		if (indice == 0){
		}
		else if (indice == 1){
		}
		else{
		}
	}
	
  • flujo normal, complejidad 1.
  • if (indice == 0), complejidad 1.
  • if (indice == 1), complejidad 1.

Para abarcar el 100% del código se necesitan escribir 3 pruebas unitarias.

Caso 3:

Complejidad ciclomática: 3. La expresión Default no es considerada para este cálculo. Solo se cuentan las expresiones Case.

	void Caso3()
	{
		var indice = 0;
		switch (indice){
			case 0:
				break;
			case 1:
				break;
			default:
				break;
		}
	}
	
  • flujo normal, complejidad 1.
  • case 0, complejidad 1.
  • case 1, complejidad 1.

Para abarcar el 100% del código se necesitan escribir 3 pruebas unitarias.

Caso 4:

Complejidad ciclomática: 2.

	void Caso4()
	{
		var paises = new List<string>();
		foreach ( var pais in paises)    {
		}
	}
	
  • flujo normal, complejidad 1.
  • foreach (var pais in paises), complejidad 1.

Para abarcar el 100% del código se necesitan escribir 2 pruebas unitarias.

Caso 5:

Complejidad ciclomática: 12.

	string ValidarTriangulo(int a, int b, int c)
	{
		if (a <= 0 || b <= 0 || c <= 0)
		{
			return "Triangulo Inválido";
		}

		if ((a > b + c || b > a + c || c > a + b))
		{
			return "Triangulo Inválido";
		}

		if (a == b && b == c)
		{
			return "Triangulo Equilátero";
		}

		if (a == b || b == c || a == c)
		{
			return "Triangulo Isósceles";
		}

		return "Triangulo  Escaleno";
	}
	
  • flujo normal, complejidad 1.
  • if (a <= 0 || b <= 0 || c <= 0), complejidad 3.
  • if((a > b + c || b > a + c || c > a + b)), complejidad 3.
  • if(a == b && b == c), complejidad 2.
  • if(a == b || b == c || a == c), complejidad 3.

Para abarcar el 100% del código se necesitan escribir 12 pruebas unitarias. Nota: Si quieren saber como identificar los escenarios de pruebas necesarios para abarcar al 100% este método les recomiendo que lean este articulo What the heck is cyclomatic complexity?

Conclusión

La complejidad ciclomática es una métrica de código que puede ser usado por cualquier lenguaje de programación. Esta métrica nos indica que tan complejo es nuestro código y la cantidad de pruebas unitarias que necesitamos para abarcar al 100% esta funcionalidad. Para medir la complejidad ciclomatica en aplicaciones .net podemos usar NDepend o Visual Studio Code Metrics, aunque existen más herramientas en el mercado.

Referencias:
Metal Tip:

Este artículo lo escribí escuchando la canción The Pain Inside de la banda StormZone de Irlanda del norte, les comparto el enlace.

Anuncios

4 comentarios en “code metrics – Complejidad Ciclomática ¿Qué tan complejo es tu código?

  1. No habia pensado que la complejidad ciclomatica ayudaria con la cantidad de pruebas unitarias que necesita un codigo… interesante.

    Aunque si se aplicara TDD eso no fuera necesario, lo veo mas para codigo legado, estoy en lo correcto?

    Me gusta

    1. Hola, creo que igual uses o no TDD sirve la complejidad ciclomática. Puede que tengas un método creado usando TDD pero la complejidad es alta, por ejemplo > 10, entonces sería necesario dividirlo. En este caso ya no usarías el valor de la complejidad para saber la cantidad de pruebas pero si lo usarías para saber si tu código necesita dividirse ya que es complejo.

      Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s