java refactoring instanceof cyclomatic-complexity

java - ¿Cómo puedo reducir la complejidad ciclomática de esto?



refactoring instanceof (5)

Tengo un método que recibe un objeto y hace algo en función del tipo de objeto que detecta:

void receive(Object object) { if (object instanceof ObjectTypeA) { doSomethingA(); } else { if (object instanceof ObjectTypeB) { doSomethingB(); } else { if (object instanceof ObjectTypeC) { doSomethingC(); } else { if (object instanceof ObjectTypeD) { doSomethingD(); } else { // etc... } } } } }

¿Cómo puedo reducir la complejidad ciclomática? Busqué alrededor, pero no pude encontrar nada demasiado útil.


¿No puedes aprovechar un enfoque orientado a objetos para esto? ¿Crear una interfaz que tenga el método doSomething() luego crear subclases que implementen el comportamiento deseado? Entonces, llamar a object.doSomething() ejecutaría el comportamiento apropiado?


¿Por qué la necesidad de reducir la complejidad? Es un patrón lo suficientemente simple como para que cualquier desarrollador competente lo vea como una función trivial.

Probablemente lo escribiría de esta manera

if (object instanceof ObjectTypeA) { doSomethingA(); } else if (object instanceof ObjectTypeB) { doSomethingB(); } else if (object instanceof ObjectTypeC) { doSomethingC(); }

Si es para satisfacer alguna necesidad esotérica de "CC debe ser menor que x", entonces la regla general de que los estándares están ahí para garantizar que el código mantenible significaría que esto es aceptable, sin importar qué tan alto sea el CC.


La complejidad ciclomática es una medida basada en la estructura gráfica del código. Específicamente, se basa en el número de rutas posibles a través del código; Vea here para más detalles. Si bien existe una correlación entre CC y lo que un programador típico vería como complejidad de código, no son lo mismo. Por ejemplo:

  • CC no tiene en cuenta la semántica del código; por ejemplo, qué hace el método que se llama, o las propiedades matemáticas de un algoritmo.

  • CC no tiene en cuenta los patrones de diseño y codificación. Entonces, algo que CC dice que es complejo puede ser simple para alguien que entiende el patrón que se está utilizando.

Se podría decir que la relación entre CC y la complejidad del código real es como la relación entre el coeficiente intelectual y la inteligencia real.

Por lo tanto, la complejidad ciclomática debe tratarse como un indicador de dónde están las partes complejas de su código ... no como una medida verdadera de la complejidad o de la calidad del código. De hecho, el código altamente complejo no es necesariamente de mala calidad. A menudo, la complejidad es inherente, y tratar de deshacerse de ella solo empeora las cosas.

En este ejemplo en particular, la medida de CC alta no corresponde a algo que podría causarle dificultades a un programador típico. La mejor respuesta (IMO) es dejar el método solo. Tácalo como un falso positivo.


Nunca tuve el objetivo de "reducir la complejidad ciclomática", aunque hubo momentos en que me pagó el LOC.

Tu código es "suficientemente bueno". Mis ojos se tropiezan con los brackets, por lo que sacrificaría un poco el rendimiento e hice lo siguiente (proporcionar los tipos A, B, etc., no están en la misma jerarquía):

receive(Object object) { if (object intanceof ObjectTypeA) doSomethingA(); if (object instanceof ObjectTypeB) doSomethingB(); ...

o (si están en la misma jerarquía):

receive(Object object) { if (object intanceof ObjectTypeA) { doSomethingA(); return; } if (object instanceof ObjectTypeB) { doSomethingB(); return; } ...

No sé si reduciría el efecto ciclomático, y no podría importarme menos.


void receive(ObjectTypeA object) { doSomethingA(); } void receive(ObjectTypeB object) { doSomethingB(); } void receive(ObjectTypeC object) { doSomethingC(); } ... // Your final ''else'' method void receive(Object object) { doSomethingZ(); }