Programing

“while (true)”루프가 그렇게 나쁩니 까?

lottogame 2020. 4. 28. 08:17
반응형

“while (true)”루프가 그렇게 나쁩니 까? [닫은]


나는 몇 년 동안 Java로 프로그래밍을 해왔지만 최근에 공식 학위를 받기 위해 학교로 돌아 왔습니다. 마지막 과제에서 아래 루프와 같은 루프를 사용하는 것에 대한 포인트를 잃어 버렸다는 사실에 놀랐습니다.

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

이제 테스트를 위해 콘솔 입력을 스캔하고 있지만 사용 break이 비슷하기 때문에 이런 종류의 루프는 권장하지 않는다는 말을 들었 goto습니다.

나는 함정 goto과 그 자바 사촌을 완전히 이해 하고 있으며 break:label, 그것을 사용하지 않는 것이 좋습니다. 나는 또한 더 완전한 프로그램이 다른 탈출 수단을 제공한다는 것을 알고 있습니다. 예를 들어 프로그램을 끝내는 것과 같습니다. 그러나 이것이 교수님이 인용 한 이유가 아니 었습니다.

무슨 일이야 do-while(true)?


나는 그것이 나쁘지 않다고 말하지 않을 것입니다 -그러나 마찬가지로 나는 적어도 대안을 찾습니다.

그것이 내가 쓰는 첫 번째 상황 인 경우, 나는 거의 항상 그것을보다 명확한 것으로 리팩토링 하려고 노력 합니다. 때로는 도움이되지 않을 수도 있습니다 (또는 대안은 bool루프의 끝을 나타내지 않고 break명령문 보다 덜 명확하게 나타내는 것 외에 의미가없는 변수를 갖는 것입니다). 그러나 적어도 시도해 볼 가치가 있습니다.

break플래그보다 사용하기 쉬운 곳의 예로 다음을 고려하십시오.

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

이제 플래그를 사용하도록하겠습니다 :

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

나는 후자를 읽기가 더 복잡하다고 생각합니다 : 여분의 else블록이 있고, actOnInput들여 쓰기가 더되며 , testCondition반환 할 때 발생하는 일을 해결하려는 경우 true블록의 나머지 부분을주의 깊게 살펴보고 거기에 있는지 확인해야합니다. 일이 아니다 else 여부를 발생할 수있는 블록 running으로 설정되어 false여부.

break진술은 의도를보다 명확하게 전달하고 나머지 블록은 이전 조건에 대해 걱정하지 않고 필요한 작업을 수행하도록합니다.

이것은 사람들이 메소드에서 여러 개의 return 문에 대해 갖는 것과 동일한 종류의 인수입니다. 예를 들어, 처음 몇 줄 내에서 메소드의 결과를 계산할 수있는 경우 (예 : 일부 입력이 null이거나 비어 있거나 0 인 경우) 결과를 저장할 변수를 갖는 것보다 해당 답변을 직접 반환하는 것이 더 명확합니다. 그런 다음 다른 코드의 전체 블록과 마지막 으로 return명령문.


AFAIK 아무것도 아닙니다. 교사는에 대한 알레르기가 있습니다 goto. 왜냐하면 어딘가 나쁜 소식을 들었 기 때문입니다. 그렇지 않으면 다음과 같이 작성합니다.

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

거의 같은 것입니다.

아마도 이것은 더 깨끗합니다 (모든 루핑 정보가 블록의 상단에 포함되어 있기 때문에) :

for (bool endLoop = false; !endLoop;)
{

}

Douglas Crockford는 JavaScriptloop구조가 포함 되기를 원하는 방식에 대해 언급했습니다 .

loop
{
  ...code...
}

그리고 나는 Javaloop구조 를 갖는 데 더 나쁜 것이라고 생각하지 않습니다 .

while(true)루프에는 본질적으로 아무런 문제가 없지만 교사 루프 를 방해하는 경향이 있습니다. 교습의 관점에서 학생들이 무한 루프를 만들고 루프가 탈출하지 않는 이유를 이해하게하는 것은 매우 쉽습니다.

그러나 그들이 거의 언급하지 않는 것은 모든 루핑 메커니즘을 while(true)루프 로 복제 할 수 있다는 것 입니다.

while( a() )
{
  fn();
}

와 같다

loop
{
  if ( !a() ) break;
  fn();
}

do
{
  fn();
} while( a() );

와 같다:

loop
{
  fn();
  if ( !a() ) break;
}

for ( a(); b(); c() )
{
  fn();
}

와 같다:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

사용하도록 선택한 구문이 작동 하는 방식으로 루프를 설정할 수있는 한 중요하지 않습니다. 이 경우 발생 에 맞게 for루프, 용도 for루프를.

마지막 부분 : 루프를 단순하게 유지하십시오. 반복 할 때마다 많은 기능이 필요한 경우 기능에 넣으십시오. 작동 후에는 항상 최적화 할 수 있습니다.


1967 년에 Dijkstra는 무역 잡지에 기사를 작성하여 코드 품질을 향상시키기 위해 고급 언어에서 goto를 제거해야하는 이유를 설명했습니다. "구조적 프로그래밍"이라고하는 전체 프로그래밍 패러다임은 이것에서 나온 것이지만 모든 사람이 자동으로 잘못된 코드를 의미한다고 동의하는 것은 아닙니다. 구조적 프로그래밍의 요점은 본질적으로 코드의 구조가 가능한 한 흐름을 결정하거나 중단하지 않고 흐름을 결정해야한다는 것입니다. 마찬가지로 패러다임에는 루프 나 함수에 대한 여러 개의 진입 점과 출구 점이있는 것이 좋습니다. 분명히 이것이 유일한 프로그래밍 패러다임은 아니지만 종종 객체 지향 프로그래밍 (ala Java)과 같은 다른 패러다임에 쉽게 적용될 수 있습니다. 선생님이 아마 가르쳐 졌을 것입니다. 그리고 코드가 체계화되도록하고 구조화 된 프로그래밍 규칙에 따라 "스파게티 코드"를 피하는 것이 가장 좋습니다. break를 사용하는 구현에는 본질적으로 "틀린"것이 없지만 while () 조건 내에 루프 조건이 명시 적으로 지정되어 지나치게 까다로울 수있는 가능성을 제거하는 코드를 읽는 것이 훨씬 쉽다고 생각하는 사람들도 있습니다. 실수로 무한 루프를 생성하거나 읽기 어렵거나 불필요하게 혼동되는 코드를 만드는 위험과 같은 초보 프로그래머가 코드에 자주 나타나는 것처럼 보이는 while (true) 조건을 사용하는 데에는 분명히 함정이 있습니다. break를 사용하는 구현에는 본질적으로 "틀린"것이 없지만 while () 조건 내에 루프 조건이 명시 적으로 지정되어 지나치게 까다로울 수있는 가능성을 제거하는 코드를 읽는 것이 훨씬 쉽다고 생각하는 사람들도 있습니다. 실수로 무한 루프를 생성하거나 읽기 어렵거나 불필요하게 혼동되는 코드를 만드는 위험과 같은 초보 프로그래머가 코드에 자주 나타나는 것처럼 보이는 while (true) 조건을 사용하는 데에는 분명히 함정이 있습니다. break를 사용하는 구현에는 본질적으로 "틀린"것이 없지만 while () 조건 내에 루프 조건이 명시 적으로 지정되어 지나치게 까다로울 수있는 가능성을 제거하는 코드를 읽는 것이 훨씬 쉽다고 생각하는 사람들도 있습니다. 실수로 무한 루프를 생성하거나 읽기 어렵거나 불필요하게 혼동되는 코드를 만드는 위험과 같은 초보 프로그래머가 코드에 자주 나타나는 것처럼 보이는 while (true) 조건을 사용하는 데에는 분명히 함정이 있습니다.

아이러니하게도 예외 처리는 구조적 프로그래밍과의 편차가 확실하게 발생하고 Java 프로그래밍에 더 나아갈 때 예상되는 영역입니다.

또한 강사는 해당 장 또는 텍스트 레슨에서 가르치는 특정 루프 구조 또는 구문을 사용하는 능력을 보여줄 것으로 예상했을 수도 있으며, 작성한 코드는 기능적으로 동일하지만 시연하지는 않았을 것입니다 그 레슨에서 배웠어야했던 특정 기술.


입력을 읽기위한 일반적인 Java 규칙은 다음과 같습니다.

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}

그리고 입력을 읽는 일반적인 C ++ 규칙은 다음과 같습니다.

#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

그리고 C에서는

#include <stdio.h>
char* buffer = NULL;
size_t buffer_size;
size_t size_read;
while( (size_read = getline(&buffer, &buffer_size, stdin)) != -1 ){
  // do something with the line
}
free(buffer);

또는 파일에서 가장 긴 텍스트 줄이 얼마나 긴지 알고 있다면

#include <stdio.h>
char buffer[BUF_SIZE];
while (fgets(buffer, BUF_SIZE, stdin)) {
  //do something with the line
}

If you're testing to see whether your user entered a quit command, it's easy to extend any of these 3 loop structures. I'll do it in Java for you:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}

So, while there certainly are cases where break or goto is justified, if all you're doing is reading from a file or the console line by line, then you shouldn't need a while (true) loop to accomplish it -- your programming language has already supplied you with an appropriate idiom for using the input command as the loop condition.


It's not such a terrible thing, but you need to take into consideration other developers when coding. Even in school.

Your fellow developers should be able to see the exit clause for your loop, at the loop declaration. You didn't do that. You hid the exit clause in the middle of the loop, making more work for someone else who comes along and tries to understand your code. This is the same reason that things like "break" are avoided.

That being said, you'll still see things like this in a LOT of code out there in the real world.


It's your gun, your bullet and your foot...

It's bad because you are asking for trouble. It won't be you or any of the other posters on this page who have examples of short/simple while loops.

The trouble will start at some very random time in the future. It might be caused by another programmer. It might be the person installing the software. It might be the end user.

Why? I had to find out why a 700K LOC app would gradually start burning 100% of the CPU time until every CPU was saturated. It was an amazing while (true) loop. It was big and nasty but it boiled down to:

x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}

There was no final else branch. If the value did not match an if condition the loop kept running until the end of time.

Of course, the programmer blamed the end users for not picking a value the programmer expected. (I then eliminated all instances of while(true) in the code.)

IMHO it is not good defensive programming to use constructs like while(true). It will come back to haunt you.

(But I do recall professors grading down if we did not comment every line, even for i++;)


According to my experience in most cases loops have the "main" condition to continue. This is the condition that should be written into while() operator itself. All other conditions that may break the loop are secondary, not so important etc. They can be written as additional if() {break} statements.

while(true) is often confusing and is less readable.

I think that these rules do not cover 100% of cases but probably only 98% of them.


It's bad in the sense that structured programming constructs are preferred to (the somewhat unstructured) break and continue statements. They are, by comparison, preferred to "goto" according to this principle.

I'd always recommend making your code as structured as possible... although, as Jon Skeet points out, don't make it more structured than that!


While not necessarily an answer as to why not to use while (true), I've always found this comic and accompanying author's statement a succinct explanation as to why to do while instead of do-while.

With regards to your question: There is no inherent problem with

while(true) {
   do_stuff();
   if(exit_time) {
      break;
   }
}

... if you know what you're doing and making sure that exit_time will at some point evaluate to true.

Teachers discourage you from using while(true) because until and unless you're at the point that you know exactly what you're doing, it's an easy way to make a critical mistake.


You might just use a Boolean flag to indicate when to end the while loop. Break and go to were reasons for software being to hard to maintain - the software-crisis(tm) - and should be avoided, and easily can be too.

It's a question if you are pragmatic or not. Pragmatic coders might just use break in that simple situation.

But it's good to get the habbit of not using them, else you might use them out of habbit in unsuitable situations, like in complicated nested loops where readability and maintainability of your code becomes harder by using break.


I think that yes it is pretty bad... or at least, for many developers. It is symptomatic of developers that don't think about their loop conditions. Consequently there is error prone.


There's no major problem with while(true) with break statements, however some may think its slightly lowers the code readability. Try to give variables meaningful names, evaluate expressions in the proper place.

For your example, it seems much clearer to do something like:

do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)

This is especially true if the do while loop gets long -- you know exactly where the check to see if there's an extra iteration is occurring. All variables/functions have appropriate names at the level of abstraction. The while(true) statement does is tell you that processing isn't in the place you thought.

Maybe you want different output on the second time through the loop. Something like

input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}

seems more readable to me then

do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);

Again, with a trivial example both are quite readable; but if the loop became very large or deeply nested (which means you probably should already have refactored), the first style may be a bit clearer.


Maybe I am unlucky. Or maybe I just lack an experience. But every time I recall dealing with while(true) having break inside, it was possible to improve the code applying Extract Method to while-block, which kept the while(true) but (by coincidence?) transformed all the breaks into returns.

In my experience while(true) without breaks (ie with returns or throws) are quite comfortable and easy to understand.


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }

I use something similar, but with opposite logic, in a lot of my functions.

DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}

It's more of an aesthetics thing, much easier to read code where you explicitly know why the loop will stop right in the declaration of the loop.


I would say that generally the reason it's not considered a good idea is that you are not using the construct to it's full potential. Also, I tend to think that a lot of programming instructors don't like it when their students come in with "baggage". By that I mean I think they like to be the primary influence on their students programming style. So perhaps that's just a pet peeve of the instructor's.


To me, the problem is readability.

A while statement with a true condition tells you nothing about the loop. It makes the job of understanding it much more difficult.

What would be easier to understand out of these two snippets?

do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);

I guess using break to your teacher is like breaking a branch of tree to get the fruit,use some other tricks (bow the branch) so that you get the fruit and the branch is still alive.:)


1) Nothing is wrong with a do -while(true)

2) Your teacher is wrong.

NSFS!!:

3) Most teachers are teachers and not programmers.


It might be bad if your loop runs on a background thread, so when you close your application by terminating a UI thread, that piece of code will continue to execute. As others already said, you should always use some kind of check to provide a way for cancellation.

참고URL : https://stackoverflow.com/questions/6850380/are-whiletrue-loops-so-bad

반응형