language agnostic - ciclomatica - Buscando aclaraciones sobre la estructuración del código para reducir la complejidad ciclomática
complejidad ciclomatica c# (8)
Al igual que todas las métricas de software, CC no es perfecto. Usado en una base de código lo suficientemente grande, puede darle una idea de dónde podría ser una zona problemática.
Hay dos cosas a tener en cuenta aquí:
- Bases de código lo suficientemente grandes: en cualquier proyecto no trivial tendrás funciones que tienen un valor CC realmente alto. 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.
- No te olvides de usar tu 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 un 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 problemas durante su creación . Esto es mucho mejor que tener que esperar hasta que se vuelvan tan grandes que se hagan obvios (ver SPC para algunos detalles).
Recientemente, nuestra empresa ha comenzado a medir semanalmente la complejidad ciclomática (CC) de las funciones de nuestro código e informa qué funciones han mejorado o empeorado. Así que hemos comenzado a prestar mucha más atención al CC de funciones.
He leído que CC puede calcularse informalmente como 1 + el número de puntos de decisión en una función (por ejemplo, enunciado if, 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 el CC es utilizar la refactorización del método de extracción repetidamente ...
Hay algunas cosas de las que no estoy seguro, 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 hacen lo mismo, pero ¿la primera versión tiene un CC más alto debido a la instrucción 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 ¿el CC del primer fragmento es más alto porque tiene 3 puntos de decisión / si?
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 hacen cosas diferentes, pero ¿tienen el mismo 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?
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.
Después de navegar a través de la entrada de la wikipedia y en el documento original 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 pros y contras. Supongo que en un programa lo suficientemente grande, el valor CC podría apuntar a partes posiblemente complejas de tu código. Pero ese CC más alto no significa necesariamente complejo.
Este es el peligro de aplicar cualquier métrica a ciegas. 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 sabia si utilizara la medida CC como una forma de detectar los puntos calientes potenciales en el código que deberían 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.
[Fuera del tema] Si favorece la legibilidad sobre el buen puntaje en las métricas (¿fue J.Spolsky quien dijo, "lo que se mide, lo que se hace"? - lo que significa que las métricas se abusan más de las veces, supongo), a menudo es mejor use un booleano bien nombrado para reemplazar su declaración condicional compleja.
entonces
if (condition1 && condition2 && condition3)
Console.WriteLine("wibble");
volverse
bool/boolean theWeatherIsFine = condition1 && condition2 && condition3;
if (theWeatherIsFine)
Console.WriteLine("wibble");
- 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.
- Sí, tal vez, su primer ejemplo tiene múltiples puntos de decisión y, por lo tanto, un CC más alto. (Consulte a continuación para obtener una explicación).
- Si quizas. 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 (es de esperar que estén usando herramientas para hacerlo). 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 usa herramientas para refactorizar su código para reducir el CC, asegúrese de entender qué están haciendo 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).
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 medida ú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 al considerar un número CC:
- La relación entre CC # y # de pruebas debe ser CC # <= #tests
- Refactor para CC # solo si aumenta la capacidad de mantenimiento
- CC por encima de 10 a menudo indica uno o más olores de código
No soy un experto en este tema, pero pensé que daría mi granito de arena. 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 mayor, 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, escribes "wibble" o no.
2 casos de prueba para ambos
3.) Primero uno 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 el segundo