¿Anidamiento máximo para bucles y condicionales? [duplicar]

14

He escrito un código que tiene algunos nidos bastante profundos (una vez, escribí algo que era un control condicional dentro de un forloop dentro de un control condicional dentro de un forloop dentro de un forloop).

¿Existe una guía general sobre los límites del número de anidados para bucles / condicionales que tiene?

    
pregunta Josh Brown 09.10.2013 - 19:50

6 respuestas

14

Está tocando una de las métricas de código clásicas: complejidad ciclomática . No mide los niveles anidados, sino más bien los bucles y condicionales (que normalmente encierran niveles anidados).

PMD (una herramienta de análisis estático de Java) tiene la complejidad como una de sus medidas y tiene esto es lo que hay que decir al respecto :

  

La complejidad está determinada por el número de puntos de decisión en un método más uno para la entrada del método. Los puntos de decisión son "si", "mientras", "para" y "etiquetas de casos". Generalmente, 1-4 es de baja complejidad, 5-7 indica complejidad moderada, 8-10 es de alta complejidad y 11+ es de muy alta complejidad.

Vea también Experimentos que correlacionan las métricas de código con la densidad de errores de P.SE que profundiza en las medidas reales.

    
respondido por el user40980 09.10.2013 - 20:30
9

El lenguaje C permite hasta 127 niveles de bloques anidados; como 640 KB de RAM, eso es todo lo que cualquier persona debería necesitar.

En la práctica, si se encuentra anidando a más de 4 o 5 niveles de profundidad, piense en factorizar algunos de esos niveles internos a sus propias funciones (o replantee su algoritmo). Si nada más, el código será más fácil de escanear.

    
respondido por el John Bode 09.10.2013 - 20:20
9

Le recomiendo encarecidamente que lea "Código limpio" de Robert Martin, un extracto del cual dice acerca de las estructuras anidadas:

  

Bloques y sangrado

     

... los bloques dentro de las declaraciones if , las declaraciones else , while   declaraciones, y así sucesivamente debe ser una línea larga. Probablemente esa linea   debe ser una llamada de función. Esto no solo mantiene el envolvente   Función pequeña, pero también agrega valor documental porque la   La función llamada dentro del bloque puede tener un nombre descriptivo.

     

Esto también implica que las funciones no deben ser lo suficientemente grandes como para mantenerlas   estructuras anidadas . Por lo tanto, el nivel de sangría de una función   No debe ser mayor que uno o dos . Esto, por supuesto, hace que el   Funciones más fáciles de leer y entender.

Por lo tanto, la recomendación de Bob Martin es que el departamento de estructura anidada debería ser dos como máximo .

Estoy de acuerdo con eso y, aunque no siempre lo cumplo, al menos lo intento.

Además, de acuerdo con la configuración predeterminada del PDM de la herramienta de análisis estático, la complejidad ciclomática de una función no debe exceder de 11, lo que se puede alcanzar fácilmente si se supera un departamento de dos.

    
respondido por el Tulains Córdova 09.10.2013 - 22:29
5

Como ocurre con la mayoría de las preguntas sobre los estándares de codificación, la respuesta es: Lo que haga que tu código sea más legible.

Yo diría que eso es generalmente bastante cerca de cero capas de lógica incrustadas. Pero a veces no lo es, y atenerse con vehemencia a las reglas contra el sentido común es más perjudicial que seguir la simple política de leer su propio código, o hacer que otra persona lo haga.

Cualquier cosa que lo haga más legible, hazlo.

    
respondido por el pdr 09.10.2013 - 20:23
2

Yo personalmente trato de evitar más de cuatro o cinco niveles de profundidad en una sola función. Más que eso sería un mal "olor de código". Le sugeriría que intente evitarlo ajustando la estructura del programa o reformulando su problema.

    
respondido por el clwen 09.10.2013 - 20:10
1

Una desventaja de los bucles anidados no se menciona aún: si cada bucle se repite en un conjunto de datos de gran tamaño, su algoritmo tendrá clases de alta complejidad. Por ejemplo,

foreach(foo in foos) {
  foreach(bar in bars) {
    foreach(baz in bazzes) {
      foreach(buzz in buzzes) {
        do_a_thing(foo, bar, baz, buzz);
      }
    }
  }
}

Se ejecutará en aproximadamente el tiempo O(n^4) si foos , bars , bazzes y buzzes tienen el mismo tamaño.

Esto no es un problema si las colecciones siempre van a ser pequeñas. Entonces, el consejo de todos los demás se aplica. Sin embargo, si sus colecciones tienen una probabilidad decente de tener miles de objetos grandes o grandes, valdría la pena buscar un algoritmo más rápido si es posible.

    
respondido por el Kevin 10.10.2013 - 01:58

Lea otras preguntas en las etiquetas