
La complejidad ciclomática es una métrica de código que puede ver en muchos IDE, como Visual Studio. Si bien no es una ciencia exacta, le da una idea general de la complejidad de las funciones, clases y espacios de nombres, lo que puede ser útil cuando se busca código para refactorizar.
¿Qué es la complejidad ciclomática?
La complejidad ciclomática básicamente mide qué tan lejos se ramifica su código. Siempre que haya un if
instrucción u otro bloque de control como un bucle, la complejidad ciclomática aumenta, ya que el gráfico se parecerá cada vez más a un árbol.
Si imagina su código como una serie de acciones (funciones, llamadas a métodos, asignaciones de variables) vinculadas a través del flujo de control, obtendrá un gráfico abstracto que puede utilizar para comprender mejor la complejidad. Para flujos de control comunes como if
declaraciones e for
bucle, los gráficos se ven así:
La fórmula es simple; tome el número de aristas en el gráfico (las flechas que conectan todo) y reste el número de nodos en el gráfico (las acciones en sí).
Complexity = Edges -- Nodes + 2
Por ejemplo, este código tiene una complejidad ciclomática de uno, ya que no hay ramas y simplemente llama a WriteLine una y otra vez. Dado que es solo un código perfectamente lineal, el número de nodos cancelará el número de bordes, dando una complejidad ciclomática de uno.
public void TestFunction() { Console.WriteLine("Test"); Console.WriteLine("Test"); Console.WriteLine("Test"); Console.WriteLine("Test"); Console.WriteLine("Test"); }
Para código más complicado con ramas, la complejidad será mayor. Este código, que contiene un archivo switch
instrucción, tiene una complejidad de 6, porque hay muchos caminos diferentes que puede tomar el código. Cada case
en la declaración de cambio agrega complejidad, ya que puede conducir a diferentes salidas con diferentes entradas.
public void TestFunction(string arg) { switch(arg) { case "one": Console.WriteLine("Test"); break; case "two": Console.WriteLine("Test"); break; case "three": Console.WriteLine("Test"); break; case "four": Console.WriteLine("Test"); break; case "five": Console.WriteLine("Test"); break; } Console.WriteLine("Test"); }
La complejidad ciclomática solo se calcula dentro del alcance de la función. Si una función llama a otra función que tiene una alta complejidad ciclomática, solo se cuenta como un único nodo y no agrega nada al llamador, a pesar de que técnicamente agrega complejidad al programa en un sentido general.
¿Es útil la complejidad ciclomática?
La complejidad ciclomática no es una métrica perfecta. Es una métrica muy simple y examina los matices del código en sí. Por supuesto, aún puede tener código terrible con baja complejidad o código decente con alta complejidad. Pero, en general, sigue siendo lo suficientemente útil como para tener una idea general de lo complejo que es un programa.
En su mayor parte, la complejidad de 6 a 8 probablemente esté bien siempre que el código en sí esté bien formateado. Cualquier cosa entre 8-15 es cuestionable y cualquier cosa por encima de 15 probablemente no sea buena. Cualquier cosa por encima de los 25 es casi seguro un problema a menos que se demuestre lo contrario.
Si bien tener una alta complejidad ciclomática en una función determinada no es el fin del mundo, puede ser indicativo de un problema mayor. Las funciones muy complejas son más difíciles de mantener y propensas a más errores, ya que hay más cosas que pueden salir mal. Y las funciones más complejas conducen directamente a pruebas unitarias más complejas, lo que puede hacer que el código sea difícil de mantener a largo plazo debido a la dificultad de las pruebas.
Visual Studio y otros IDE calcularán las complejidades agregadas de clases y espacios de nombres completos, lo que puede ser útil para rastrear clases más complejas. Puede ordenar según la complejidad más alta y obtener más información sobre las funciones individuales.
A menudo, la revisión del código puede tener en cuenta la complejidad ciclomática, al mismo tiempo que marca funciones problemáticas que pueden requerir una revisión manual. Esto puede convertirlo en una herramienta muy útil para mantener una base de código limpia y ordenada.
Buscando un código incorrecto
Muchos IDE, como Visual Studio, tendrán herramientas integradas para calcular la complejidad ciclomática y otras métricas de código para toda la base del código.
Para hacer esto desde Visual Studio, haga clic en Analizar> Calcular métricas de código> Por solución.
Aparecerá el panel "Métricas de código" mostrando un análisis detallado de la solución. Puede ordenar por complejidad en orden descendente para ver los espacios de nombres más problemáticos.
Además de la complejidad, Visual Studio también cuenta con un "Índice de mantenibilidad" que asigna una puntuación al método de 0 a 100 más fácilmente que se puede mantener, así como "Acoplamiento de clases", que enumera el número de clases a las que hace referencia esa función. o clase.
Aquí, Visual Studio destacó un método mío de 400 líneas que obtuvo una puntuación enorme de 72 en la escala de complejidad y un 14/100 en el índice de mantenibilidad (presentado como un triángulo de advertencia amarillo) y hace referencia a 65 clases diferentes.
Podría ser enviado directamente a las cinco etapas del dolor en el resultado. "¡Pero esta es una corrutina realmente larga que tiene muchas tareas por hacer!" Me digo a mí mismo, tratando de negar que el código que escribí es matemáticamente malo, hasta el punto de que Visual Studio lanza una advertencia. Una complejidad de 72 definitivamente debe limpiarse.
En este caso, la solución fue simple: la corrutina tiene muchas tareas por hacer, así que divido esas tareas en corrutinas más pequeñas y reemplazo el método principal con llamadas a subrutinas. El código general no ha cambiado, y tampoco la complejidad general de la clase en sí, pero ahora la función principal no es una monstruosidad de 400 líneas.
Deja una respuesta