Complejidad Ciclomática, o la métrica esencial para apreciar la calidad de un diseño


 

Publicado por Javier Garzás el miercoles 19 de julio de 2006 a las 20:01

Ultima modificación el el miercoles 19 de julio de 2006

 

Corría el 1976 cuando Thomas McCabe publicó un artículo en el que argumentaba como la complejidad del código puede definirse desde su flujo de control, o dicho de una manera más exhaustiva del número de rutas linealmente independientes, definiendo para ello una de las métricas más útiles en ingeniería del software, y que denominó “complejidad ciclomática”. Dicho así pudiera parecer poco relevante, pero si pensamos sobre ello esta métrica permitió que desde entonces se pudiera comparar la complejidad de los algoritmos de una manera sencilla, y con cierta independencia del lenguaje en que se programaran, y, como veremos luego, además permitiría apreciar la calidad del diseño software, de una manera rápida y con independencia del tamaño de la aplicación.

En sí el concepto en que se basó McCabe no era nuevo, ya que de alguna forma supone la adaptación de la prueba general de compresibilidad de Flesch-Kincaid (que si bien suena bastante raro es bastante conocida en otros ámbitos y que se aplica para medir la comprensibilidad de un texto).

Entrando en los entresijos de la métrica la complejidad ciclomática se calcula desde el grafo asociado a un algoritmo: donde las aristas entre nodos son los saltos en la secuencia, debidos a sentencias condicionales, bucles o saltos tipo “go to”. Y desde ahí existen varios algoritmos, el más conocido:

v(G) = e − n + 2

G es el flujo grama del algoritmo

e es el número de arcos del flujo grama

n es el número de nodos del flujo grama

Si bien en un código estructurado (aquel que no tiene “go tos” o similares) existe una manera más simple de calcularla y es contando el número de decisiones (“ifs”) más uno, o el número de bucles cerrados en el grafo más uno. Aún así esta “versión reducida” del cálculo puede ser compleja, ya que cuando nos encontremos con bucles (tipo for, por ejemplo) tendremos que descomponerlos en “ifs” simples. Y es por ello que en la actualidad existen numerosas herramientas que permiten hacer el cálculo.

¿Y por qué es tan importante? Bien, yo lo primero que diría es que es una herramienta esencial cuando necesitas “tomar la temperatura” del diseño de una aplicación software de un tamaño considerable, ya que se puede obtener fácilmente y de manera automatizada.

Y digo la calidad del diseño, ya que si bien es una métrica que se calcula desde un algoritmo cuando su valor es alto indica problemas de diseño. Por ejemplo, si existen muchas sentencias tipo “case” con muchas cláusulas la complejidad ciclomática será alta y deduciré que pocas veces esas cláusulas se han situado en sub-clases y el “case” se ha sustituido por el uso del polimorfismo (buena práctica de OO donde las haya).

También una complejidad ciclomática media alta me estará indicando que el diseño – código es poco comprensible (y por ello costoso de cambiar) y que es complejo de probar (se dice que la complejidad ciclomática me dice el número de test unitarios totales para probar el 100% de los algoritmos)

Para terminar, y por dar algunas guías, sin pretender ser exhaustivo podríamos decir que:

1-10 simple

11-20 moderado

21-50 complejo

50 – muy complejo