Estoy usando SonarLint para Eclipse desde hace poco, y me ayudó mucho. Sin embargo, me planteó una pregunta sobre la complejidad ciclomática.
SonarLint considera aceptable un CC de 10, y hay algunos casos en los que estoy más allá, alrededor de 5 o 6 unidades. Esas partes están relacionadas con los mapeadores donde los valores se basan en diferentes variables, por ejemplo:
- El campo A se basa en la cadena sA;
- El campo B se basa en String sB;
- El campo C se basa en String sC;
- etc ...
No tengo otra opción que poner un if
para cada campo. Esta no es mi elección (afortunadamente) sino un sistema ya existente y complejo que no puedo cambiar por mí mismo.
El núcleo de mi pregunta es: ¿por qué es tan importante no tener un CC demasiado alto en un solo método ? Si mueve algunas de sus condiciones en uno o más submétodos para reducir la complejidad, no reduce el costo de su función general, solo está moviendo el problema a otra parte, supongo.
(Perdón por pequeños errores, si los hay).
EDITAR
Mi pregunta no se refiere a la complejidad ciclomática global, sino solo a la complejidad del método único y la división de métodos (me cuesta explicar lo que quiero decir exactamente, lo siento). Me pregunto por qué es permisible dividir sus condiciones en métodos más pequeños si todavía pertenece a un 'súper método', que solo ejecutará cada submétodo, agregando así complejidad al algoritmo.
Sin embargo, el segundo enlace ( sobre el antipatrón ) es de gran ayuda.
fuente
Respuestas:
Lo central aquí: "capacidad cerebral".
Verá, una de las principales funciones del código es ... ser leída . Y el código puede ser fácil de leer y entender; o duro
Y tener un CC alto simplemente implica muchos "niveles" dentro de un método. Y eso implica: usted, como lector humano, tendrá dificultades para comprender ese método.
Cuando lees el código fuente, tu cerebro automáticamente intenta poner las cosas en perspectiva: en otras palabras, intenta crear alguna forma de "contexto".
Y cuando tiene un método pequeño (con un buen nombre) que solo consta de unas pocas líneas y un CC muy bajo; entonces su cerebro puede aceptar fácilmente este "bloque". Lo lees, lo entiendes; HECHO.
Por otro lado, si su código tiene un CC alto, su cerebro gastará muchos "ciclos" más para deducir lo que está sucediendo.
Otra forma de decir eso: siempre debe inclinarse hacia la preferencia de una red compleja de cosas simples sobre una red simple de cosas complejas. Porque tu cerebro es mejor para entender cosas pequeñas.
fuente
CC, como todas las demás reglas generales para los olores de código, es una heurística . No es un criterio a prueba de fallas que te diga una verdad absoluta. Si lo fuera, lo razonable sería simplemente hacer que tales métodos sean ilegales en el idioma y obligar a las personas a lograr sus fines de otra manera.
Pero esa no es la forma en que funcionan los indicadores. La mayoría de las veces su función es alertar a las personas de cosas de las que no eran conscientes. En su caso, sabe que la lógica es complicada y las soluciones alternativas la harían aún más complicada. Por lo tanto, no tiene sentido tratar de satisfacer la regla general primitiva, cuando su propósito principal es emitir advertencias a las personas que no son conscientes de que hay un problema.
fuente
En resumen: se trata de la legibilidad y, por lo tanto, de la mantenibilidad de su código.
Si tiene un método largo y complejo con muchos (anidados)
if
, se hace difícil saber qué hace realmente. Si extrae algunos métodos privados y los nombra de manera significativa, es mucho más fácil.fuente
La complejidad ciclomática de un método está relacionada con el número de casos de prueba requeridos para un método. Específicamente, una complejidad ciclomática de 10 significa que 10 es el límite superior para que los casos de prueba tengan una cobertura de ramificación total para su método. También está relacionado con la cantidad de rutas que se deben probar, menos las rutas imposibles.
Más allá de eso, estoy de acuerdo con las otras respuestas para otras consideraciones: la capacidad mental de un desarrollador o un indicador de posibles problemas o refactorización o una medida de legibilidad y facilidad de mantenimiento del código .
fuente
CC es solo una heurística, y cuán "malo" es un puntaje particular depende de muchas cosas.
Dicho esto, siempre debe ver un CC alto como algo que resalta el código que podría / debería ser refactorizado. Dices que mover la
if
declaración a otro método está ocultando el problema, pero ¿hay un patrón allí que puedas abstraer en lugar de copiar pegando n veces? Si es unaif-else
cadena larga , ¿puede convertirla en una declaración de cambio, o tal vez usar polimorfismo u otra cosa? Si hay una anidación profunda, ¿se pueden unir algunas de sus cláusulas condicionales o indica responsabilidades separadas que deberían dividirse en diferentes clases?fuente
Veo la complejidad ciclomática como una advertencia. Si puede leer el código y no es demasiado complejo de entender, entonces no me preocuparía demasiado, probablemente haya cosas más importantes de las que preocuparse, siempre las hay.
Una forma de reducir el tipo de CC que menciona es usar polimorfismo, ya que ha etiquetado su pregunta con la etiqueta Java. Entonces, en lugar de que las rutas de código se escriban en cadena , puede usar clases bien nombradas. Esto puede ayudar, pero a veces es excesivo y puede hacer que su código sea aún más difícil de entender.
Sin embargo, puede ser una señal de código que será difícil de mantener. Al leer el método, ¿es fácil ver qué ruta de código va a seguir para cada caso? ¿Podría saltarse este método si no conoce bien la base del código y está buscando algo relacionado pero más adelante en el código? Sé que algunas personas abogan por dividir los métodos en muchos métodos de 1/2 línea con nombres descriptivos, pero a veces creo que es aún más difícil de leer que el código que debía reemplazar.
En última instancia, la mantenibilidad es un problema difícil y depende de usted decidir cuál cree que será más fácil de leer. El hecho de que esté pensando en esto significa que está en el camino correcto. Solo recuerde, el responsable de mantenimiento que tiene que intentar descifrar este código en años podría ser usted. Así que hazlo lo más fácil posible para ellos.
fuente
Se trata de cuánto tiempo se pasa mirando (ciclos cerebrales) el código y comprendiendo lo que está haciendo el código.
También los métodos más grandes son más difíciles de probar y más difíciles de predecir qué tipo de comportamiento podría ocurrir.
La complejidad ciclomática es una medida. En este caso, los valores más altos son indicadores de posibles problemas. El código complejo tarda más en comprender y probablemente no se pruebe tan a fondo como los métodos menos complejos. Por lo tanto, es importante tener en cuenta qué áreas del código son complejas con esta medida para fines de refactorización y mantenimiento.
Otra cosa a considerar es actualizar el código complejo. Al hacer el análisis, un desarrollador podría informar que cambiar el código es más o menos arriesgado al observar su complejidad.
Por lo tanto, existe un gran valor para medir la complejidad que se puede aprovechar y utilizar para la toma de decisiones.
fuente