Estou programando em Java há vários anos, mas acabei de voltar à escola para obter um diploma formal. Fiquei bastante surpreso ao saber que, na minha última tarefa, perdi pontos por usar um loop como o abaixo.
do{
//get some input.
//if the input meets my conditions, break;
//Otherwise ask again.
} while(true)
Agora, para o meu teste, estou apenas procurando por alguma entrada do console, mas me disseram que esse tipo de loop é desencorajado porque o uso break
é semelhante goto
, simplesmente não fazemos isso.
Entendo completamente as armadilhas de goto
seu primo Java break:label
e tenho o bom senso de não usá-las. Sei também que um programa mais completo forneceria outros meios de fuga, por exemplo, para encerrar o programa, mas não foi por isso que meu professor citou, então ...
O que há de errado do-while(true)
?
java
while-loop
do-while
JHarnach
fonte
fonte
break
provavelmente é bem-intencionada, mas realmente mal compreendida. Talvez você possa educar seu professor sobre isso;) Na minha experiência, os professores não sabem muito sobre o ofício da programação.do {} while (true)
é equivalentewhile(true) {}
e o último é, de longe, a forma mais convencional e muito mais clara.break
, deve tentar programar em uma linguagem sem ela. Não são necessários muitos loops antes que você deseje!Respostas:
Eu não diria que é ruim - mas igualmente eu normalmente procuraria pelo menos uma alternativa.
Nas situações em que é a primeira coisa que escrevo, quase sempre tento refatorá-lo para algo mais claro. Às vezes, isso não pode ser ajudado (ou a alternativa é ter uma
bool
variável que não faz nada significativo, exceto indicar o fim do loop, menos claramente que umabreak
declaração), mas vale a pena tentar pelo menos.Como um exemplo de onde é mais claro o uso
break
de uma bandeira, considere:Agora vamos forçá-lo a usar uma bandeira:
Eu vejo o último como mais complicado de ler: ele tem um
else
bloco extra , oactOnInput
é mais recuado e, se você está tentando descobrir o que acontece quandotestCondition
retornatrue
, precisa examinar cuidadosamente o resto do bloco para verificar se existe não é algo após oelse
bloco que ocorrerá, serunning
foi definidofalse
ou não.A
break
declaração comunica a intenção de forma mais clara e permite que o restante do bloco continue com o que precisa fazer sem se preocupar com as condições anteriores.Observe que esse é exatamente o mesmo tipo de argumento que as pessoas têm sobre várias instruções de retorno em um método. Por exemplo, se eu conseguir calcular o resultado de um método dentro das primeiras linhas (por exemplo, porque alguma entrada é nula, vazia ou nula), acho mais claro retornar essa resposta diretamente do que ter uma variável para armazenar o resultado , em seguida, um bloco inteiro de outro código e, finalmente, uma
return
declaração.fonte
while (true)
AFAIK nada, realmente. Os professores são alérgicos
goto
, porque ouviram em algum lugar que é muito ruim. Caso contrário, você apenas escreveria:O que é quase a mesma coisa.
Talvez isso seja mais limpo (porque todas as informações de loop estão contidas na parte superior do bloco):
fonte
Douglas Crockford fez uma observação sobre como ele desejava que o JavaScript contivesse uma
loop
estrutura:E eu não acho que Java seria pior por ter uma
loop
estrutura também.Não há nada de intrinsecamente errado com
while(true)
loops, mas não é uma tendência para os professores a desencorajá-los. Do ponto de vista do ensino, é muito fácil fazer com que os alunos criem loops sem fim e não entendam por que o loop nunca é escapado.Mas o que eles raramente mencionam é que todos os mecanismos de loop podem ser replicados com
while(true)
loops.é o mesmo que
e
é o mesmo que:
e
é o mesmo que:
Contanto que você possa configurar seus loops de uma maneira que funcione, a construção que você escolher usar não é importante. Se acontecer de caber em um
for
loop, use umfor
loop.Uma última parte: mantenha seus loops simples. Se houver muita funcionalidade em todas as iterações, coloque-a em uma função. Você sempre pode otimizá-lo depois de fazê-lo funcionar.
fonte
for
loops quandocontinue
há declarações envolvidas, mas elas não são uma grande extensão.for (;;) {
? (Pronunciado "para sempre"). Isso costumava ser muito popular.Em 1967, Edgar Dijkstra escreveu um artigo em uma revista especializada sobre por que o goto deve ser eliminado das linguagens de alto nível para melhorar a qualidade do código. Um paradigma inteiro de programação chamado "programação estruturada" surgiu disso, embora certamente nem todos concordam que ir automaticamente significa código incorreto.
O ponto crucial da programação estruturada é essencialmente que a estrutura do código deve determinar seu fluxo em vez de ter gotos ou quebras ou continuar a determinar o fluxo, sempre que possível. Da mesma forma, ter vários pontos de entrada e saída em um loop ou função também é desencorajado nesse paradigma.
Obviamente, esse não é o único paradigma de programação, mas geralmente pode ser facilmente aplicado a outros paradigmas, como a programação orientada a objetos (ala Java).
Seus professores provavelmente foram ensinados e estão tentando ensinar à sua turma que é melhor evitar o "código de espaguete", garantindo que nosso código seja estruturado e seguindo as regras implícitas da programação estruturada.
Embora não haja nada inerentemente "errado" em uma implementação que use break, alguns consideram significativamente mais fácil ler código onde a condição para o loop é explicitamente especificada na condição while () e elimina algumas possibilidades de ser excessivamente complicada. Definitivamente, existem armadilhas no uso de uma condição while (true) que parece surgir com frequência no código por programadores iniciantes, como o risco de criar acidentalmente um loop infinito ou tornar o código difícil de ler ou desnecessariamente confuso.
Ironicamente, o tratamento de exceções é uma área em que certamente ocorrerá um desvio da programação estruturada e será esperado à medida que você avança na programação em Java.
Também é possível que seu instrutor tenha esperado que você demonstrasse sua capacidade de usar uma estrutura ou sintaxe específica de loop ensinada nesse capítulo ou lição do seu texto e, embora o código que você escreveu seja funcionalmente equivalente, você pode não estar demonstrando o habilidade específica que você deveria aprender nessa lição.
fonte
A convenção Java usual para leitura de entrada é:
E a convenção C ++ usual para leitura de entrada é:
E em C, é
ou se estiver convencido de que sabe quanto tempo dura a linha de texto mais longa no seu arquivo, você pode
Se você estiver testando para ver se o usuário digitou um
quit
comando, é fácil estender qualquer uma dessas três estruturas de loop. Vou fazer isso em Java para você:Portanto, embora certamente haja casos em que
break
ougoto
justificado, se você estiver lendo um arquivo ou o console linha por linha, não será necessário umwhile (true)
loop para realizá-lo - sua linguagem de programação já lhe forneceu com um idioma apropriado para usar o comando de entrada como condição de loop.fonte
while (true)
loop em vez de um desses loops de entrada convencionais, pode estar esquecendo de verificar o final do arquivo.while
condicional. Na condição final do Java, ele já está ficando bastante pesado e, se você tiver que fazer uma manipulação extensiva para decidir se continua ou não, pode demorar um pouco. Você pode dividi-lo em uma função separada, e isso pode ser melhor. Mas se você o desejar em uma função e houver um trabalho não trivial antes de decidir continuar,while(true)
pode ser melhor.gets()
não é uma convenção comum. É altamente propício ao buffer overflow.fgets(buffer, BUFFER_SIZE, file)
é muito mais parecido com a prática padrão.fgets
.Não é uma coisa tão terrível, mas você precisa levar em consideração outros desenvolvedores ao codificar. Mesmo na escola.
Seus colegas desenvolvedores devem poder ver a cláusula de saída do seu loop, na declaração do loop. Você não fez isso. Você ocultou a cláusula de saída no meio do loop, dando mais trabalho a alguém que aparece e tenta entender seu código. Esta é a mesma razão pela qual coisas como "pausa" são evitadas.
Dito isto, você ainda verá coisas assim em MUITO código no mundo real.
fonte
while (true)
, é bastante óbvio que haverá umbreak
oureturn
dentro dele, ou que ele funcionará para sempre. Ser direto é importante, maswhile(true)
não é especialmente ruim, por si só. Variáveis que possuem invariantes complexos em iterações de loop seriam um exemplo de algo que causa muito mais angústia.É sua arma, sua bala e seu pé ...
É ruim porque você está pedindo problemas. Não será você ou qualquer um dos outros pôsteres nesta página que tenha exemplos de loops curtos / simples enquanto.
O problema começará em um momento muito aleatório no futuro. Pode ser causado por outro programador. Pode ser a pessoa que está instalando o software. Pode ser o usuário final.
Por quê? Eu tive que descobrir por que um aplicativo LOC de 700K começaria a queimar gradualmente 100% do tempo da CPU até que toda CPU estivesse saturada. Foi um incrível loop enquanto (verdadeiro). Era grande e desagradável, mas resumia-se a:
Não havia ramo final. Se o valor não corresponder a uma condição if, o loop continuará em execução até o final do tempo.
Obviamente, o programador culpou os usuários finais por não escolherem um valor que o programador esperava. (Eliminei todas as instâncias de while (true) no código.)
IMHO, não é uma boa programação defensiva usar construções como while (true). Voltará para assombrá-lo.
(Mas lembro-me de professores com notas baixas, se não comentássemos todas as linhas, mesmo para i ++;)
fonte
É ruim no sentido de que as construções de programação estruturada são preferidas às declarações (um tanto não estruturadas) de interrupção e continuação. Eles são, por comparação, preferidos a "ir" de acordo com esse princípio.
Eu sempre recomendo tornar seu código o mais estruturado possível ... embora, como Jon Skeet ressalte, não o torne mais estruturado do que isso!
fonte
De acordo com minha experiência, na maioria dos casos, os loops têm a condição "principal" de continuar. Essa é a condição que deve ser gravada no próprio operador while (). Todas as outras condições que podem interromper o loop são secundárias, não tão importantes etc. Elas podem ser escritas como
if() {break}
instruções adicionais .while(true)
geralmente é confuso e é menos legível.Penso que estas regras não cobrem 100% dos casos, mas provavelmente apenas 98% deles.
fonte
Embora não seja necessariamente uma resposta sobre o porquê de não usar
while (true)
, sempre achei essa declaração cômica e do autor que o acompanha uma explicação sucinta sobre o porquê de fazer enquanto em vez de fazer enquanto.Com relação à sua pergunta: Não há nenhum problema inerente ao
... se você souber o que está fazendo e se certificar de que
exit_time
em algum momento será avaliadotrue
.Os professores o desencorajam a usar,
while(true)
porque até e a menos que você saiba exatamente o que está fazendo, é uma maneira fácil de cometer um erro crítico.fonte
exit_time = false; while(!exit_time) { execute_stuff(); }
edo { execute_stuff(); } while(! exit_time );
ambos são muito mais claros do que ter umif( condition ) { break; }
no final de um loop com umwhile(true)
. Quebras são curtos-circuitos para loops - perfeitamente bem quando usadas como um curto-circuito no meio de um loop, mas você deve apenas avaliar uma condição na instrução while versus fazer uma pausa no final de um loop.Você pode apenas usar um sinalizador booleano para indicar quando terminar o loop while.
Break
ego to
havia razões para que o software fosse difícil de manter - a crise do software (tm) - e deveria ser evitado e facilmente pode ser.É uma pergunta se você é pragmático ou não. Codificadores pragmáticos podem apenas usar quebra nessa situação simples.
Mas é bom obter o hábito de não usá-los; caso contrário, você pode usá-los em situações inadequadas, como em loops aninhados complicados em que a legibilidade e a manutenção do seu código se tornam mais difíceis de usar
break
.fonte
if (running)
dentro do loop, recuando todo o resto do código quando tudo o que eu quero é sair do loop é definitivamente menos claro para mim do que uma declaração de interrupção simples que afirma exatamente o que eu quero fazer. Você parece estar pensando em usar o intervalo como um mau hábito axiomaticamente - não penso nisso como tal.Talvez eu seja azarado. Ou talvez apenas me falte uma experiência. Mas cada vez que eu lembro de lidar com
while(true)
terbreak
dentro, foi possível melhorar o código da aplicação Extract Method para enquanto bloco , que manteve awhile(true)
mas (por coincidência?) Transformou todas asbreak
s emreturn
s.Na minha experiência,
while(true)
sem pausas (isto é, com retornos ou arremessos) são bastante confortáveis e fáceis de entender.fonte
Eu acho que sim, é muito ruim ... ou pelo menos para muitos desenvolvedores. É sintomático de desenvolvedores que não pensam em suas condições de loop. Consequentemente, há propensão a erros.
fonte
Não há nenhum grande problema com
while(true)
combreak
declarações, no entanto alguns podem pensar sua reduz ligeiramente a legibilidade do código. Tente dar nomes significativos às variáveis, avalie as expressões no local apropriado.Para o seu exemplo, parece muito mais claro fazer algo como:
Isso é especialmente verdadeiro se o loop do while for longo - você sabe exatamente onde está a verificação para verificar se está ocorrendo uma iteração extra. Todas as variáveis / funções têm nomes apropriados no nível de abstração. o
while(true)
afirmação é dizer que o processamento não está no lugar que você pensou.Talvez você queira uma saída diferente na segunda vez no loop. Algo como
parece mais legível para mim, então
Novamente, com um exemplo trivial, ambos são bastante legíveis; mas se o loop ficar muito grande ou profundamente aninhado (o que significa que você provavelmente já deve ter refatorado), o primeiro estilo pode ser um pouco mais claro.
fonte
Uso algo semelhante, mas com lógica oposta, em muitas das minhas funções.
fonte
É mais uma questão estética, muito mais fácil de ler código, onde você sabe explicitamente por que o loop irá parar na declaração do loop.
fonte
Eu diria que, geralmente, a razão pela qual não é considerada uma boa ideia é que você não está usando o construto em seu potencial máximo. Além disso, costumo pensar que muitos instrutores de programação não gostam quando seus alunos chegam com "bagagem". Com isso, quero dizer que eles gostam de ser a principal influência no estilo de programação de seus alunos. Então, talvez seja apenas uma irritação do instrutor.
fonte
Para mim, o problema é legibilidade.
Uma declaração while com uma condição verdadeira não diz nada sobre o loop. Isso torna o trabalho de entendê-lo muito mais difícil.
O que seria mais fácil de entender desses dois trechos?
fonte
Eu acho que usar o intervalo para o seu professor é como quebrar um galho de árvore para obter o fruto, use alguns outros truques (incline o galho) para que você obtenha o fruto e o galho ainda esteja vivo. :)
fonte
1) Nada está errado com um
do -while(true)
2) Seu professor está errado.
NSFS !!:
3) A maioria dos professores são professores e não programadores.
fonte
Pode ser ruim se o loop for executado em um encadeamento em segundo plano; portanto, quando você fechar o aplicativo encerrando um encadeamento da interface do usuário, esse trecho de código continuará sendo executado. Como já foi dito, você sempre deve usar algum tipo de verificação para fornecer uma forma de cancelamento.
fonte