¿Por qué es una buena idea evitar bloques nesteds en una función? (PHP)

Instalé una versión beta de Netbeans 7.4, y hay una nueva sugerencia que dice “Demasiados bloques nesteds en la statement de funciones; es una buena práctica introducir nuevas funciones …”.

Trato de evitar bloques nesteds dentro de una función para una mejor legibilidad, pero ¿hay alguna otra razón por la cual esta sería una mejor “idea”, específicamente para PHP, si eso es importante?

El nombre formal para esto es Cyclomatic Complexity .

Esta es una medida de cuán compleja es una función, basada en el número de “puntos de decisión” en la función. Cuanto mayor es el número, más compleja es la función.

La complejidad está determinada por la cantidad de puntos de decisión en un método más uno para la entrada del método. Los puntos de decisión son ‘if’, ‘while’, ‘for’ y ‘case labels’. En general, 1-4 es de baja complejidad, 5-7 indica complejidad moderada, 8-10 es de alta complejidad y 11+ es de muy alta complejidad.

(tomado de http://phpmd.org/rules/codesize.html )

La razón por la que se considera malo tener sus valores de complejidad demasiado altos es porque dificulta la prueba de la función.

Para probar una función en todo su potencial, necesita tener una prueba separada para cada ruta de código posible. La cantidad de rutas de código aumenta de forma exponencial con cada nuevo punto de decisión, lo que significa que cuando obtiene más de un puñado de decisiones en una sola función, comienza a necesitar cientos de pruebas para asegurarse de haber cubierto el toda la gama de funcionalidad que podría realizar.

Cientos de pruebas para una sola función son claramente demasiadas, por lo que la mejor opción es reducir la cantidad de puntos de decisión por función dividiéndola en varias funciones más pequeñas con menos decisiones cada una.

También necesita hacer que las funciones sean discretas para que no se fundan entre sí. Esto les permite probarse de forma aislada el uno del otro. (de lo contrario, todavía tiene el problema original de demasiadas decisiones en una sola llamada)

Luego puede probar cada una de esas funciones con solo un puñado de las pruebas que originalmente habría requerido.

El proceso de pruebas de funciones de forma aislada entre sí se denomina Prueba de unidad . Este es un tema muy extenso en sí mismo, pero vale la pena investigarlo si quiere saber más sobre buenas prácticas de desarrollo de software.

Como ha etiquetado esta pregunta PHP, le indicaré algunas herramientas que le ayudarán a:

  • Unidad de PHP : este es el paquete de prueba de unidad estándar de facto para PHP.
  • PHPMD – “PHP Mess Detector”; una herramienta para analizar su código para buscar cosas como la complejidad excesiva.
  • pDepender – Otra herramienta similar.

Hay muchas otras herramientas disponibles, pero eso es probablemente suficiente para comenzar; llegar a conocer esos primero. Te encontrarás con otros naturalmente mientras investigas el tema.

En general, las funciones / métodos están bien escritos si hacen una sola cosa pero lo hacen bien.

Cuando un método comienza a exhibir el anidamiento más allá de 1 o 2 niveles, es una señal segura de que está tratando de hacer más de una cosa a la vez.

Cuando hay muchas anidaciones y condicionales en una función, también hace que su lógica sea más intrincada y difícil de seguir, así como también más difícil de probar con solidez.

Finalmente, si hay funcionalidad enterrada profundamente en un nido en otro método, no podrá reutilizarla fácilmente. Deberás cortarlo y pegarlo donde quieras usarlo (lo que siempre conduce a una pesadilla de mantenimiento) o agregar un interruptor adicional y otro condicional al método de alojamiento (lo que simplemente agrava el problema). Si refactoriza esa funcionalidad en su propio método, reutilizarla es trivial.

Un buen beneficio es reducir el scope. Al reducir el locking a un método separado, le está dejando claro a los futuros lectores que este fragmento de código solo depende de los parámetros proporcionados.

En pseudo código

$some_variable = "something"; $some_other_variable = "something else"; if(x < y) { ... lots of code ... some_method($some_variable); ... more code ... } 

Al extraer el condicional a un método separado, queda claro que la lógica dentro de esa twig NO depende de $some_other_variable .

Si tiene métodos grandes con muchas ramificaciones y muchas variables, se hace más difícil mantener el método y es más probable que rompa algo inadvertidamente.

El código de fantasía causa pesadillas de mantenimiento … Al menos en el modelo de KISS, mantenlo simple, y tu depuración será muy fácil.

Esta respuesta se mantiene en el modelo KISS, es una respuesta simple