He estado programando en Java durante varios años, pero recientemente regresé a la escuela para obtener un título formal. Me sorprendió bastante saber que, en mi última tarea, perdí puntos por usar un bucle como el siguiente.
do{
//get some input.
//if the input meets my conditions, break;
//Otherwise ask again.
} while(true)
Ahora, para mi prueba, solo estoy buscando información de la consola, pero me dijeron que se desaconseja este tipo de bucle porque el uso break
es similar goto
, simplemente no lo hacemos.
Entiendo completamente las trampas goto
y su primo de Java break:label
, y tengo el buen sentido de no usarlas. También me doy cuenta de que un programa más completo proporcionaría otros medios de escape, por ejemplo, para terminar el programa, pero esa no fue una razón por la que mi profesor lo citó, así que ...
¿Qué tiene de malo do-while(true)
?
fuente
break
es probablemente bien intencionada, pero en realidad mal entendida. Quizás pueda educar a su profesor sobre esto;) En mi experiencia, los profesores no saben mucho sobre el oficio de la programación.do {} while (true)
es equivalentewhile(true) {}
y este último es, con mucho, la forma más convencional y mucho más clara.break
, debería intentar programar en un lenguaje sin él. ¡No toma muchos bucles antes de que lo desee!Respuestas:
No diría que es malo , pero igualmente al menos normalmente buscaría una alternativa.
En situaciones donde es lo primero que escribo, casi siempre trato de refactorizarlo para que sea más claro. A veces no se puede evitar (o la alternativa es tener una
bool
variable que no haga nada significativo excepto indicar el final del ciclo, con menos claridad que unabreak
declaración), pero al menos vale la pena intentarlo.Como un ejemplo de dónde es más fácil de usar
break
que una bandera, considere:Ahora forcémoslo a usar una bandera:
Veo este último como más complicado de leer: tiene un
else
bloque adicional ,actOnInput
está más sangrado, y si estás tratando de averiguar qué sucede cuandotestCondition
regresatrue
, debes mirar cuidadosamente el resto del bloque para verificar que haya no es algo después delelse
bloque que ocurriría sirunning
se ha establecidofalse
o no.La
break
declaración comunica la intención con mayor claridad y permite que el resto del bloque continúe con lo que necesita hacer sin preocuparse por las condiciones anteriores.Tenga en cuenta que este es exactamente el mismo tipo de argumento que las personas tienen sobre múltiples declaraciones de retorno en un método. Por ejemplo, si puedo calcular el resultado de un método dentro de las primeras líneas (por ejemplo, porque alguna entrada es nula, vacía o cero), me resulta más claro devolver esa respuesta directamente que tener una variable para almacenar el resultado , luego un bloque completo de otro código, y finalmente una
return
declaración.fuente
while (true)
AFAIK nada, de verdad. Los maestros simplemente son alérgicos
goto
, porque escucharon en algún lugar que es realmente malo. De lo contrario, simplemente escribirías:Que es casi lo mismo.
Tal vez esto sea más limpio (porque toda la información de bucle está contenida en la parte superior del bloque):
fuente
Douglas Crockford hizo un comentario sobre cómo deseaba JavaScript contuviera una
loop
estructura:Y tampoco creo que Java sea peor por tener una
loop
estructura.No hay nada inherentemente malo con
while(true)
bucles, pero no es una tendencia a que los maestros para desalentar ellos. Desde la perspectiva de la enseñanza, es muy fácil hacer que los estudiantes creen bucles interminables y no entiendan por qué nunca se escapa el bucle.Pero lo que rara vez mencionan es que todos los mecanismos de bucle se pueden replicar con
while(true)
bucles.es lo mismo que
y
es lo mismo que:
y
es lo mismo que:
Siempre que pueda configurar sus bucles de una manera que funcione, la construcción que elija usar no es importante. Si resulta que encaja en un
for
bucle, use unfor
bucle.Una última parte: mantenga sus bucles simples. Si hay mucha funcionalidad que debe suceder en cada iteración, póngala en una función. Siempre puede optimizarlo una vez que lo tiene funcionando.
fuente
for
bucles cuando lascontinue
declaraciones están involucradas, pero no son una extensión importante.for (;;) {
más? (Pronunciado "para siempre"). Esto solía ser muy popular.En 1967, Edgar Dijkstra escribió un artículo en una revista comercial sobre por qué debería eliminarse el goto de los lenguajes de alto nivel para mejorar la calidad del código. Todo esto surgió de un paradigma de programación llamado "programación estructurada", aunque ciertamente no todos están de acuerdo en que goto significa automáticamente código incorrecto.
El quid de la programación estructurada es esencialmente que la estructura del código debe determinar su flujo en lugar de tener problemas o interrupciones o continuar determinando el flujo, siempre que sea posible. De manera similar, tener múltiples puntos de entrada y salida a un bucle o función también se desaconseja en ese paradigma.
Obviamente, este no es el único paradigma de programación, pero a menudo se puede aplicar fácilmente a otros paradigmas como la programación orientada a objetos (ala Java).
Probablemente a sus maestros se les haya enseñado, y está tratando de enseñarle a su clase que es mejor que evitemos el "código de espagueti" asegurándose de que nuestro código esté estructurado y siguiendo las reglas implícitas de programación estructurada.
Si bien no hay nada intrínsecamente "incorrecto" con una implementación que usa break, algunos consideran que es mucho más fácil leer el código donde la condición para el bucle se especifica explícitamente dentro de la condición while (), y elimina algunas posibilidades de ser demasiado complicado. Definitivamente, existen dificultades para usar una condición while (verdadera) que parece aparecer con frecuencia en el código por parte de programadores novatos, como el riesgo de crear accidentalmente un bucle infinito o hacer que el código sea difícil de leer o innecesariamente confuso.
Irónicamente, el manejo de excepciones es un área donde la desviación de la programación estructurada ciertamente surgirá y se esperará a medida que avance en la programación en Java.
También es posible que su instructor haya esperado que demuestre su capacidad para usar una estructura de bucle o sintaxis particular que se enseña en ese capítulo o lección de su texto, y aunque el código que escribió es funcionalmente equivalente, es posible que no haya demostrado habilidad particular que se suponía que estabas aprendiendo en esa lección.
fuente
La convención habitual de Java para leer entradas es:
Y la convención habitual de C ++ para leer entradas es:
Y en C, es
o si está convencido de saber cuánto dura la línea de texto más larga en su archivo, puede hacerlo
Si está probando para ver si su usuario ingresó un
quit
comando, es fácil extender cualquiera de estas 3 estructuras de bucle. Lo haré en Java por ti:Entonces, aunque ciertamente hay casos en los que
break
ogoto
está justificado, si todo lo que está haciendo es leer un archivo o la consola línea por línea, entonces no debería necesitar unwhile (true)
bucle para lograrlo: su lenguaje de programación ya le ha proporcionado con un lenguaje apropiado para usar el comando de entrada como condición de bucle.fuente
while (true)
bucle en lugar de uno de estos bucles de entrada convencionales, es posible que se olvide de verificar el final del archivo.while
condicional. En la condición final de Java ya se está volviendo bastante fuerte, y si tuvo que hacer una manipulación extensa para decidir si continuar o no, puede ser bastante largo. Podría dividirlo en una función separada, y eso podría ser lo mejor. Pero si lo desea en una función, y hay trabajo no trivial que hacer antes de decidir si continuar,while(true)
puede ser lo mejor.gets()
no es una convención común. Es altamente propicio para desbordamientos de búfer.fgets(buffer, BUFFER_SIZE, file)
es mucho más como la práctica estándar.fgets
.No es algo tan terrible, pero debe tener en cuenta a otros desarrolladores al codificar. Incluso en la escuela.
Sus compañeros desarrolladores deberían poder ver la cláusula de salida para su ciclo, en la declaración del ciclo. No hiciste eso. Ocultaste la cláusula de salida en el medio del bucle, haciendo más trabajo para alguien que viene y trata de entender tu código. Esta es la misma razón por la que se evitan cosas como "descanso".
Dicho esto, todavía verás cosas como esta en MUCHO código en el mundo real.
fuente
while (true)
, es bastante obvio que habrá unbreak
oreturn
dentro de él, o que se ejecutará para siempre. Ser directo es importante, perowhile(true)
no es especialmente malo, en sí mismo. Las variables que tienen invariantes complejos a través de iteraciones de bucle serían un ejemplo de algo que causa mucha más angustia.Es tu arma, tu bala y tu pie ...
Es malo porque estás pidiendo problemas. No serán usted ni ninguno de los otros pósters de esta página los que tengan ejemplos de bucles while cortos / simples.
El problema comenzará en un momento muy aleatorio en el futuro. Puede ser causado por otro programador. Puede ser la persona que instala el software. Puede ser el usuario final.
¿Por qué? Tenía que averiguar por qué una aplicación de 700K LOC comenzaría a quemar gradualmente el 100% del tiempo de CPU hasta que cada CPU estuviera saturada. Fue un ciclo increíble (cierto). Era grande y desagradable, pero se reducía a:
No había otra rama final. Si el valor no coincide con una condición if, el bucle siguió ejecutándose hasta el final de los tiempos.
Por supuesto, el programador culpó a los usuarios finales por no elegir un valor que el programador esperaba. (Luego eliminé todas las instancias de while (verdadero) en el código).
En mi humilde opinión, no es una buena programación defensiva utilizar construcciones como while (verdadero). Volverá para atormentarte.
(Pero sí recuerdo a los profesores que se gradúan si no comentamos cada línea, incluso para i ++;)
fuente
Es malo en el sentido de que se prefieren las construcciones de programación estructurada a las declaraciones (algo no estructuradas) de romper y continuar. En comparación, se prefieren "ir a" según este principio.
Siempre recomendaría hacer su código lo más estructurado posible ... aunque, como señala Jon Skeet, ¡no lo haga más estructurado que eso!
fuente
Según mi experiencia en la mayoría de los casos, los bucles tienen la condición "principal" para continuar. Esta es la condición en la que debería escribirse el operador while (). Todas las demás condiciones que pueden romper el ciclo son secundarias, no tan importantes, etc. Pueden escribirse como
if() {break}
declaraciones adicionales .while(true)
a menudo es confuso y es menos legible.Creo que estas reglas no cubren el 100% de los casos, pero probablemente solo el 98% de ellos.
fuente
Si bien no es necesariamente una respuesta de por qué no usarlo
while (true)
, siempre he encontrado este cómic y la declaración del autor que lo acompaña una explicación sucinta de por qué hacer el tiempo en lugar de hacerlo.Con respecto a su pregunta: no hay ningún problema inherente con
... si sabes lo que estás haciendo y asegurándote de que
exit_time
en algún momento evaluarástrue
.Los maestros te desalientan de usar
while(true)
porque hasta y a menos que estés en el punto de que sabes exactamente lo que estás haciendo, es una manera fácil de cometer un error crítico.fuente
exit_time = false; while(!exit_time) { execute_stuff(); }
ydo { execute_stuff(); } while(! exit_time );
son mucho más claros que tener unif( condition ) { break; }
al final de un ciclo con unwhile(true)
. Los descansos son cortocircuitos en bucles, perfectamente bien cuando se usan como cortocircuitos en el medio de un bucle, pero solo debe evaluar una condición en la declaración while frente a tener un descanso al final de un bucle.Puede usar una bandera booleana para indicar cuándo finalizar el ciclo while.
Break
ygo to
eran razones para que el software fuera demasiado difícil de mantener, la crisis del software (tm), y debería evitarse, y fácilmente puede serlo también.Es una pregunta si eres pragmático o no. Los codificadores pragmáticos podrían usar el descanso en esa situación simple.
Pero es bueno obtener el hábito de no usarlos, de lo contrario, puede usarlos fuera del hábitat en situaciones inadecuadas, como en complicados bucles anidados donde la legibilidad y la facilidad de mantenimiento de su código se vuelven más difíciles de usar
break
.fuente
if (running)
bucle dentro del bucle, sangrando todo el resto del código cuando todo lo que quiero es salir del bucle definitivamente es menos claro para mí que una simple declaración de interrupción que establece exactamente lo que quiero hacer. Parece que está considerando usar el descanso como un mal hábito axiomáticamente , no lo considero así.Quizás tengo mala suerte. O tal vez solo me falta una experiencia. Pero cada vez que recuerdo tratar con
while(true)
tenerbreak
adentro, era posible mejorar el código aplicando el método de extracción al bloque while , que mantenía elwhile(true)
pero (¿por coincidencia?) Transformaba todos losbreak
mensajes enreturn
s.En mi experiencia,
while(true)
sin pausas (es decir, con devoluciones o lanzamientos) son bastante cómodas y fáciles de entender.fuente
Creo que sí, es bastante malo ... o al menos, para muchos desarrolladores. Es sintomático de los desarrolladores que no piensan en sus condiciones de bucle. En consecuencia, hay errores propensos.
fuente
No hay ningún problema importante
while(true)
con lasbreak
declaraciones, sin embargo, algunos pueden pensar que disminuye ligeramente la legibilidad del código. Trate de dar nombres significativos a las variables, evalúe las expresiones en el lugar apropiado.Para su ejemplo, parece mucho más claro hacer algo como:
Esto es especialmente cierto si el ciclo do while se alarga: usted sabe exactamente dónde se realiza la comprobación para ver si hay una iteración adicional. Todas las variables / funciones tienen nombres apropiados a nivel de abstracción. los
while(true)
declaración dice que el procesamiento no está en el lugar que pensabas.Tal vez desee una salida diferente la segunda vez a través del ciclo. Algo como
me parece más legible entonces
De nuevo, con un ejemplo trivial, ambos son bastante legibles; pero si el bucle se hizo muy grande o profundamente anidado (lo que significa que probablemente ya debería haber refactorizado), el primer estilo puede ser un poco más claro.
fuente
Utilizo algo similar, pero con lógica opuesta, en muchas de mis funciones.
fuente
Es más una cuestión de estética, mucho más fácil de leer código donde sabes explícitamente por qué el bucle se detendrá justo en la declaración del bucle.
fuente
Yo diría que, en general, la razón por la que no se considera una buena idea es que no está utilizando la construcción en todo su potencial. Además, tiendo a pensar que a muchos instructores de programación no les gusta cuando sus estudiantes entran con "equipaje". Con eso quiero decir que creo que les gusta ser la influencia principal en el estilo de programación de sus estudiantes. Entonces, tal vez eso sea solo una manía del instructor.
fuente
Para mí, el problema es la legibilidad.
Una declaración while con una condición verdadera no le dice nada sobre el ciclo. Hace que el trabajo de entenderlo sea mucho más difícil.
¿Qué sería más fácil de entender de estos dos fragmentos?
fuente
Supongo que usar break para tu maestro es como romper una rama de árbol para obtener la fruta, usa otros trucos (inclina la rama) para que obtengas la fruta y la rama siga viva. :)
fuente
1) No hay nada malo con un
do -while(true)
2) Tu maestro está equivocado.
NSFS !!:
3) La mayoría de los maestros son maestros y no programadores.
fuente
Puede ser malo si su bucle se ejecuta en un subproceso en segundo plano, por lo que cuando cierre su aplicación al terminar un subproceso de interfaz de usuario, ese fragmento de código continuará ejecutándose. Como ya han dicho otros, siempre debe usar algún tipo de cheque para proporcionar una forma de cancelación.
fuente