¿Cuáles son sus consejos para realizar un seguimiento y evitar errores en los bucles?

StackOverflow https://stackoverflow.com/questions/1011712

  •  06-07-2019
  •  | 
  •  

Pregunta

Acabo de encontrar ... OTRA VEZ ... un error de desperdicio en tiempo real como sigue

for (int i = 0; i < length; i++)
{ //...Lots of code 
    for (int j = 0; i < length; j++)
    {
        //...Lots of code 
    }
}

¿Notaste directamente el i interno que DEBE SER j? Yo tampoco. Así que de ahora en adelante voy a usar:

for (int i = 0; i < length; i++)
{
    for (int i1 = 0; i1 < length; i1++)
    {
    }
}

¿Cuáles son sus consejos para interior y exterior mientras y para bucles?

Editar: Gracias por las valiosas respuestas. A continuación un breve resumen de los consejos propuestos:

  • usar nombres de variables significativas para las variables de índice (en su lugar, uso SomeObjCollectionLength)
  • coloque el contenido del bucle interno en un método separado y llame a ese método desde el bucle externo
  • la cantidad no manejable de líneas de código entre el bucle externo y el interno es una señal fuerte de olor a código
  • evite pegar y apresurar copias, escriba los índices vars con cuidado

Es posible que desee consultar el resumen LBushkin para siguiendo

  • use foreach e iteradores siempre que sea posible
  • inicializa las variables justo antes de ingresar los bucles
  • Hacer que cada bucle realice solo una función. Evite mezclar responsabilidades en un solo ciclo
  • Cuando sea posible, haga sus bucles lo suficientemente cortos como para verlos todos a la vez
¿Fue útil?

Solución

No use i & amp; j (o cualquier otra variable de una sola letra) como nombres de índice. Use nombres propios y no se encontrará con este tipo de problemas.

Otros consejos

Una de las soluciones más simples y limpias es colocar el contenido del bucle interno en un método para que se convierta en:

for (int i = 0; i < length; i++)
{
    DoSomething();
}

private void DoSomething(int outerValue)
{
    for (int i = 0; i < length; i++)
    {
        // Do something else
    }

}

Para mí, el 'olor a código' aquí es 'mucho código'.

Si la cantidad de código en los bucles es particularmente grande, la distancia entre los bucles interno y externo significa que no es tan probable que se comparen entre sí para la corrección.

Es cierto que mirar el inicio del bucle interno de forma aislada debería llamar la atención sobre el problema, pero tener la estructura principal en una sección de código tan pequeña como sea posible le da a tu cerebro menos digestión.

Puede ser posible extraer las secciones 'lotes de código' en funciones / métodos separados, para reducir el tamaño de la estructura principal, pero esto puede no ser siempre práctico.

Además, diría que 'i1' no es particularmente una buena elección del nombre de la variable, ya que eso tiende a alentar a 'i2', 'i3', etc., lo que realmente no conduce a un código comprensible. Quizás reemplazar todas las variables de bucle con algo más significativo ayudaría a la claridad del código y reduciría las posibilidades del error original.

Mi consejo principal (sin ningún orden en particular) para escribir un mejor código de bucle (gran parte de esto es del excelente libro Código completo ):

  1. Evite múltiples puntos de salida para bucles.
  2. Use continuar / romper con moderación.
  3. Refactorice bucles anidados en rutinas separadas, cuando sea posible.
  4. Use nombres de variables significativos para hacer legibles los bucles anidados.
  5. Utilice los bucles foreach () cuando sea posible, en lugar de los bucles (i = ...).
  6. Ingrese el bucle desde una ubicación solamente. No te metas en un bucle con goto's. Nunca.
  7. Coloque el código de inicialización inmediatamente antes del ciclo.
  8. Mantenga las declaraciones de inicialización del bucle con el bucle con el que están relacionadas.
  9. Evite reutilizar variables entre bucles no anidados. 10. Limite el alcance de las variables de índice de bucle al propio bucle.
  10. Use while (verdadero) para bucles infinitos, en lugar de para (;;)
  11. En los lenguajes que proporcionan construcciones de bloque (por ejemplo, '{' y '}') úselas en lugar de sangría para encerrar las declaraciones de un bucle. Sí, incluso para bucles de una sola línea.
  12. Evite bucles vacíos.
  13. Evite colocar los quehaceres domésticos en el medio de un bucle, colóquelos al principio y / o al final.
  14. Hacer que cada bucle realice solo una función. Evite mezclar responsabilidades en un solo ciclo.
  15. Hacer obvias las condiciones de terminación del bucle.
  16. No simule con la variable de índice de bucle de un bucle for () para que termine.
  17. Evite el código que depende del valor final del indexador de bucle.
  18. Considere el uso de contadores de seguridad en bucles complejos: se pueden verificar para asegurarse de que el bucle no se ejecute demasiadas o muy pocas veces.
  19. Use declaraciones de interrupción, cuando sea posible, para terminar los bucles while.
  20. Cuando sea posible, haga sus bucles lo suficientemente cortos como para verlos todos a la vez.

Eso es un error de copiar y pegar, evitar copiar y pegar.

En cuanto a su solución, no es mucho mejor. El error aún puede pasar entre toneladas de código. Tiendo a usar nombres significativos incluso para variables temporales de bucle.

aproveche su IDE, en VS, intente usar esto: http://msdn.microsoft.com/en-us/library/z4c5cc9b (VS.80) .aspx

muestra: escriba para , luego presione Tab Tab sucesivamente

Vine aquí para ser inteligente y decir "lo escribo bien la primera vez". Pero luego vi tu ejemplo y, bueno, lo he hecho muchas veces.

Cuando necesita bucles anidados de esa manera, mi única solución es estar alerta y pensar cuando escribe el código.

Donde sea posible, usar iteradores y para cada bucle es bueno.

Además, no puedo ver cómo su solución sugerida será mejor. Y tampoco se ve tan bien.

En primer lugar, reduzca el tamaño del cuerpo del bucle, es decir, mueva cosas para separar las funciones. En general, es una mala idea tener funciones más largas de las que caben en la pantalla, por lo que los bucles deberían ser aún más pequeños.

En segundo lugar, use nombres de variables significativos en casos como este. Solo usaría i y j en bucles simples con algunas líneas de código. Por ejemplo, si está pasando por una matriz bidimensional, " col " y "fila" tendría mucho más sentido, haría que el código fuera más fácil de leer (" cuál era cuál? ") y más fácil detectar errores como este.

Solo tienes que tener mucho cuidado con estos problemas, no hay una bala mágica contra esto. Incluso con "mejor nombre" propone que de vez en cuando perderá la noción de si este es el enésimo o (N + M) nivel de bucle anidado y cometerá un error.

Si es necesario un bucle anidado, escríbalo con cuidado. Si se puede evitar extrayendo el cuerpo del bucle externo en una función que sería una buena protección contra el uso indebido de los índices.

Utilizo 'ii' y 'jj' para los contadores de bucles transitorios si realmente los necesito; son más fáciles de buscar que 'i' y 'j' y también más fáciles de detectar en ejemplos como el anterior. Para ir mejor, puedes usar un nombre de variable real. Si está recorriendo una cadena, puede llamarla characterIndex o algo así. Es más mecanografía, pero se documenta y ahorra tiempo en la depuración de problemas oscuros más adelante.

Mejor aún sería evitar contadores numéricos y usar iteradores con nombre sobre una colección. En mi opinión, aclaran la intención.

Finalmente, si es posible, es bueno eliminar el ciclo por completo: Boost :: Foreach es una forma de hacerlo en C ++, aunque generalmente prefiero usar lenguajes como Python que permiten de forma nativa la iteración directa sobre el contenido de un contenedor sin necesidad de incrementar un valor de índice o iterador.

Intente utilizar más construcciones de bucle declarativas. Por ejemplo, si realmente no necesita índices (esos i sy j s) y su entorno de programación lo permite, puede usar un foreach construir para iterar sobre la colección.

Al igual que en muchas otras cosas, hay algunos consejos excelentes en Código completo de Steve McConnell. Valdría la pena leer lo que tiene que decir sobre la creación de un buen código de bucle. No tengo mi copia del libro a mano aquí, pero todo el libro merece su tiempo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top