2008-10-15 17 views
18

Recientemente, nuestra empresa ha comenzado a medir semanalmente la complejidad ciclomática (CC) de las funciones de nuestro código e informa sobre qué funciones han mejorado o empeorado. Así que hemos comenzado a prestar mucha más atención al CC de funciones.Buscando aclaraciones sobre el código de estructuración para reducir la complejidad ciclomática

He leído que CC puede calcularse informalmente como 1 + el número de puntos de decisión en una función (por ejemplo, declaración si, para bucle, seleccionar etc.), o también el número de rutas a través de una función ...

entiendo que la forma más fácil de reducir CC es utilizar la refactorización Extraer método en varias ocasiones ...

Hay algunas cosas que estoy seguro acerca de, por ejemplo, ¿Cuál es el CC de los siguientes fragmentos de código?

1)

for (int i = 0; i < 3; i++) 
    Console.WriteLine("Hello"); 

Y

Console.WriteLine("Hello"); 
Console.WriteLine("Hello"); 
Console.WriteLine("Hello"); 

Ambos hacer lo mismo, pero ¿la primera versión tiene un CC más alta debido a la sentencia for?

2)

if (condition1) 
    if (condition2) 
     if (condition 3) 
      Console.WriteLine("wibble"); 

Y

if (condition1 && condition2 && condition3) 
    Console.WriteLine("wibble"); 

Suponiendo que el lenguaje hace una evaluación de cortocircuito, como C#, entonces estos dos fragmentos de código tienen el mismo efecto ... pero es la CC del primer fragmento más alto porque tiene 3 puntos de decisión/si enunciados?

3)

if (condition1) 
{ 
    Console.WriteLine("one"); 

    if (condition2) 
     Console.WriteLine("one and two"); 
} 

Y

if (condition3) 
    Console.WriteLine("fizz"); 

if (condition4) 
    Console.WriteLine("buzz"); 

Estos dos fragmentos de código hacer cosas diferentes, pero no tienen la misma CC? ¿O la declaración if anidada en el primer fragmento tiene un CC más alto? es decir anidado si las declaraciones son mentalmente más complejas de entender, ¿pero eso se refleja en el CC?

Respuesta

8
  1. Sí. Su primer ejemplo tiene un punto de decisión y su segundo no, por lo que el primero tiene un CC más alto.
  2. Sí, tal vez, su primer ejemplo tiene múltiples puntos de decisión y, por lo tanto, un CC más alto. (Consulte la explicación a continuación.)
  3. Sí, quizás.Obviamente tienen el mismo número de puntos de decisión, pero hay diferentes formas de calcular CC, lo que significa ...

... si su empresa está midiendo CC de una manera específica, entonces debe familiarizarse con ese método (con suerte están usando herramientas para hacer esto). Existen diferentes formas de calcular CC para diferentes situaciones (declaraciones de casos, operadores booleanos, etc.), pero debe obtener el mismo tipo de información de la métrica, independientemente de la convención que utilice.

El problema más grande es lo que otros han mencionado, que su empresa parece centrarse más en CC que en el código subyacente. En general, seguro, debajo de 5 es excelente, debajo de 10 es bueno, debajo de 20 está bien, de 21 a 50 debería ser una señal de advertencia, y más de 50 debería ser una gran señal de advertencia, pero esas son guías, no reglas absolutas. Probablemente deberías examinar el código en un procedimiento que tenga un CC por encima de 50 para asegurarte de que no es solo un gran montón de código, pero tal vez haya una razón específica por la cual el procedimiento está escrito de esa manera, y no es factible (para número de razones) para refactorizarlo.

Si utiliza herramientas para refactorizar su código para reducir el CC, asegúrese de entender qué hacen las herramientas y de que no están simplemente transfiriendo un problema a otro lugar. En última instancia, desea que su código tenga pocos defectos, funcione correctamente y sea relativamente fácil de mantener. Si ese código también tiene un CC bajo, es bueno para eso. Si su código cumple con estos criterios y tiene un CC por encima de 10, quizás sea el momento de sentarse con la gestión que pueda y defender su código (y tal vez hacer que examine su política).

4

CC no es una panacea para medir la calidad. Claramente, una afirmación repetida no es "mejor" que un ciclo, incluso si un ciclo tiene un CC mayor. La razón por la cual el bucle tiene un CC más grande es que a veces puede ejecutarse y otras no, lo que lleva a dos "casos" diferentes que deben ser probados. En su caso, el ciclo siempre se ejecutará tres veces porque usa una constante, pero CC no es lo suficientemente inteligente como para detectarlo.

Lo mismo con los ifs encadenados en el ejemplo 2 - esta estructura le permite tener una declaración que se ejecutará si solo condition1 y condition2 son verdaderas. Este es un caso especial que no es posible en el caso usando & &. Entonces, la cadena if tiene un mayor potencial para casos especiales, incluso si no utiliza esto en su código.

6

Después de navegar a través de la entrada de la wikipedia y en el original paper de Thomas J. McCabe, parece que los elementos que mencionaste anteriormente son problemas conocidos con la métrica.

Sin embargo, la mayoría de las métricas tienen sus pros y sus contras.Supongo que en un programa lo suficientemente grande el valor CC podría apuntar a posiblemente partes complejas de su código. Pero ese CC más alto no significa necesariamente complejo.

+0

cuyo documento original se refiere usted? ¿Podrías proporcionar un enlace? – RickL

+0

enlace agregado y el nombre (Thomas J McCabe) – moogs

+0

Gracias, hojeé el papel, es bastante difícil de leer, ya que está en un estilo técnico preciso. – RickL

0

[Fuera del tema] Si favorece la legibilidad sobre la buena puntuación en las métricas (¿Fue J.Spolsky quien dijo, "lo que se mide, se hace"? - supongo que las métricas se abusan más de las veces, supongo), a menudo es mejor usar un booleano bien nombrado para reemplazar su declaración condicional compleja.

continuación

if (condition1 && condition2 && condition3) 
    Console.WriteLine("wibble"); 

convierten

bool/boolean theWeatherIsFine = condition1 && condition2 && condition3; 

if (theWeatherIsFine) 
    Console.WriteLine("wibble"); 
+0

Sí, normalmente haría este tipo de cosas si mejora la legibilidad. Curiosamente, la refabricación: mejorar el diseño del código existente recomendaría realizar el método Extract en la variable condicional en lugar de Extraer ... – RickL

1

Este es el peligro de aplicar cualquier métrica ciegamente. La métrica CC ciertamente tiene muchos méritos, pero como con cualquier otra técnica para mejorar el código, no se puede evaluar divorciada del contexto. Señale su gestión en la discusión de Casper Jone sobre la medición de las líneas de código (desearía poder encontrar un enlace para usted). Señala que si las líneas de código son una buena medida de productividad, los desarrolladores de lenguaje ensamblador son los desarrolladores más productivos en la tierra. Por supuesto, no son más productivos que otros desarrolladores; solo les lleva mucho más código para lograr lo que hacen los lenguajes de alto nivel con menos código fuente. Menciono esto, como digo, para que pueda mostrarles a sus gerentes cuán tonto es aplicar ciegamente las métricas sin una revisión inteligente de lo que la métrica les está diciendo.

Sugeriría que si no lo son, que su gestión sería sabio usar la medida CC como una forma de detectar puntos calientes potenciales en el código que debería revisarse más a fondo. Apuntar ciegamente al objetivo de CC más bajo sin ninguna referencia a la mantenibilidad del código u otras medidas de buena codificación es simplemente una tontería.

+2

"Medir un producto de software por líneas de código es como medir un avión por cuánto pesa". Bill Gates (creo)

4

Como todas las métricas de software, CC no es perfecto. Utilizado en una base de código suficientemente grande, puede darle una idea de dónde podría ser una zona problemática.

Hay dos cosas a tener en cuenta aquí:

  1. Lo suficientemente grande base de código: En cualquier proyecto no trivial que tendrá las funciones que tienen un valor muy alto CC. Tan alto que no importa si en uno de sus ejemplos, el CC sería 2 o 3. Una función con un CC de, digamos, más de 300 es definitivamente algo para analizar. No importa si el CC es 301 o 302.
  2. No olvide utilizar su cabeza. Hay métodos que necesitan muchos puntos de decisión. A menudo pueden ser refabricados de alguna manera para tener menos, pero a veces no pueden. No vaya con una regla como "Refactorizar todos los métodos con CC> xy". Mírelos y use su cerebro para decidir qué hacer.

Me gusta la idea de un análisis semanal. En el control de calidad, el análisis de tendencias es una herramienta muy efectiva para identificar los problemas durante su creación. Esto es mucho mejor que tener que esperar hasta que se vuelvan tan grandes que se vuelvan obvios (ver SPC para más detalles).

+0

Sí, es bastante bueno que podamos ver qué ha cambiado durante la última semana, por lo que a menudo puede ver una función en la lista en la que trabajó y recordar cuáles fueron sus cambios y ver por qué el CC ha aumentado. Desafortunadamente, nuestros umbrales son bastante bajos y, a menudo, es difícil reducir el CC fácilmente. – RickL

+0

Sí, ese es el problema que tengo con las reglas fijas. Pueden estar bien para el 80 o el 90 por ciento de los casos, pero eso todavía deja un 10% en el lugar donde chupan. – Treb

1

La complejidad ciclomática es análoga a la temperatura. Ambas son mediciones y, en la mayoría de los casos, carecen de significado sin contexto. Si dije que la temperatura exterior era de 72 grados, eso no significa mucho; pero si agregué el hecho de que estaba en el Polo Norte, el número 72 se vuelve significativo. Si alguien me dijo que un método tiene una complejidad ciclomática de 10, no puedo determinar si eso es bueno o malo sin su contexto.

Cuando reviso el código de una aplicación existente, encuentro que la complejidad ciclomática es una métrica útil de "punto de partida". Lo primero que verifico son métodos con CC> 10. Estos "> 10" métodos no son necesariamente malos. Simplemente me proporcionan un punto de partida para revisar el código.

reglas generales cuando se considera un número de CC:

  • La relación entre CC# y # de pruebas, debe ser CC# < = #tests
  • Refactor para CC# sólo si se aumenta la capacidad de mantenimiento
  • CC por encima de 10 indica a menudo uno o más Code Smells
0

no soy un experto en este tema, pero yo pensé que le daría mis dos c ents. Y tal vez eso es todo lo que vale.

Cyclomatic Complexity parece ser solo un atajo automático en particular para encontrar fragmentos de código potencialmente problemáticos (pero no definitivamente). Pero, ¿no es el problema real para ser resuelto uno de prueba? ¿Cuántos casos de prueba requiere el código? Si CC es más alto, pero el número de casos de prueba es el mismo y el código es más limpio, no se preocupe por CC.

1.) No hay un punto de decisión allí. Hay una y única ruta a través del programa allí, solo un posible resultado con cualquiera de las dos versiones. El primero es más conciso y mejor, se puede condenar la Complejidad Ciclomática.

1 caso de prueba para ambos

2.) En ambos casos, ya sea escribir "wibble" o no se tiene.

2 casos de prueba para ambos

3.) El primero podría resultar en nada, "uno" o "uno" y "uno y dos". 3 caminos. El segundo uno podría resultar en nada, en cualquiera de los dos, o en ambos. 4 caminos.

3 casos de prueba para los primeros 4 casos de prueba para la segunda

Cuestiones relacionadas