programing

while(true) 루프가 그렇게 나쁜가요?

javaba 2022. 8. 1. 23:42
반응형

while(true) 루프가 그렇게 나쁜가요?

저는 자바에서 몇 년 동안 프로그래밍을 하고 있지만, 얼마 전에 정식 학위를 따기 위해 학교로 돌아왔습니다.지난번 과제에서 아래와 같은 루프 사용으로 감점이 된 것을 알고 매우 놀랐습니다.

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

이러한 것이 좋다고 은, 「콘솔 입력」을 사용하고 있기 때문입니다.break is to 에 가깝다goto그냥 안 해요

는 는는의 한다.goto 그 자바 사촌인 바 and and and and and and and andbreak: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 더 움푹 패여있기 어떻게 알아내기 요.testConditiontrue, 블록의 나머지 부분을 주의 깊게 살펴보고, 그 후에 아무것도 없는지 확인해야 합니다.else" " " " " " 가 할 수 running 설정되었습니다.false그렇지 않으면.

break스테이트먼트는 의도를 보다 명확하게 전달하고 블록의 나머지 부분이 이전 조건에 대해 걱정하지 않고 필요한 작업을 수행할 수 있도록 합니다.

이것은 메서드의 여러 반환문에 대해 사람들이 가지고 있는 것과 정확히 같은 종류의 인수입니다.예를 들어 첫 번째 몇 줄 내의 메서드의 결과를 계산할 수 있다면(예를 들어 일부 입력이 null이거나 비어 있거나 0이기 때문에), 결과를 저장하는 변수를 갖는 것보다 답변을 직접 반환하는 것이 더 명확하다는 것을 알게 되고, 그 후 다른 코드의 전체 블록, 그리고 마지막으로,return★★★★★★ 。

AFAIK af af af 。은 단지 뿐이다.goto쓸 수 .그렇지 않으면 다음과 같이 쓸 수 있습니다.

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

거의 비슷해요.

(모든 루핑 정보가 블록의 맨 위에 포함되어 있기 때문에) 이것이 더 깔끔할 수 있습니다.

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

}

더글라스 크록포드는 JavaScript가 어떻게 포함되었으면 좋겠다고 말했다.loop★★★★

loop
{
  ...code...
}

그리고 자바가 더 나쁠 것 같진 않아loop구조도 마찬가지입니다.

while(true)루프는 있지만, 선생님들은 그들을 단념시키는 경향이 있다.교육의 관점에서 보면, 학생들이 끝없는 루프를 만들고 왜 루프가 빠져나가지 않는지 이해하지 못하게 하는 것은 매우 쉽습니다.

그러나 거의 언급하지 않은 것은 모든 루프 메커니즘이 다음 방법으로 복제될 수 있다는 입니다.while(true)displaces.displaces

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 ""를하다, ""를 사용합니다.forloopsyslog.syslog..syslog.

마지막 부분: 루프를 단순하게 유지합니다.반복할 때마다 많은 기능이 필요한 경우 함수에 넣습니다.작동한 후에는 언제든지 최적화할 수 있습니다.

1967년에 Edgar Dijkstra는 왜 코드 품질을 향상시키기 위해 고급 언어에서 goto를 제거해야 하는지에 대한 기사를 무역 잡지에 썼다."구조화된 프로그래밍"이라는 전체 프로그래밍 패러다임이 여기에서 비롯되었지만, 확실히 모두가 goto가 자동적으로 나쁜 코드를 의미한다는 것에 동의하지는 않는다.

구조화 프로그래밍의 핵심은 본질적으로 코드 구조가 흐름의 결정권을 가지며 가능한 한 흐름을 결정하도록 하는 것입니다.마찬가지로 이 패러다임에서는 루프 또는 함수에 대해 여러 개의 진입점과 출구점을 갖는 것도 권장되지 않습니다.

분명히 이것이 유일한 프로그래밍 패러다임은 아니지만 종종 객체 지향 프로그래밍(일명 자바)과 같은 다른 패러다임에 쉽게 적용될 수 있습니다.

여러분의 선생님들은 아마 이미 배웠고, 우리의 코드가 구조화되어 있는지 확인하고 구조화된 프로그래밍의 암묵적인 규칙을 따름으로써 우리가 "스파게티 코드"를 피하는 것이 최선이라고 가르치려 하고 있을 것입니다.

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
}

가 a your음 a quit명령어를 사용하면 이 3개의 루프 구조 중 하나를 쉽게 확장할 수 있습니다.바어자

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, so, so, sobreak ★★★★★★★★★★★★★★★★★」goto에서 한while (true)loop을 실행한다--프로그래밍 언어는 이미 input 명령어를 루프 조건으로 사용하기 위한 적절한 idi를 제공하고 있습니다.

그렇게 나쁜 것은 아니지만 코딩할 때 다른 개발자를 고려해야 합니다.심지어 학교에서도.

동료 개발자는 루프 선언 시 루프의 exit 절을 볼 수 있어야 합니다.네가 한 짓이거짓말이야.루프 중간에 exit 절을 숨겨서 코드를 이해하려고 하는 다른 사람을 위해 더 많은 작업을 수행했습니다.이것은 "브레이크"와 같은 것을 피하는 것과 같은 이유입니다.

하지만 실제 세계에서는 여전히 많은 코드에서 이런 것들을 볼 수 있습니다.

네 총, 네 총알, 네 발이야

당신이 화를 자초해서 안 좋아요.이 페이지의 다른 포스터에는 짧은 루프/단순한 루프 예가 없습니다.

그 문제는 장차 어느 아주 무작위적인 시간에 시작될 것이다.다른 프로그래머가 원인일 수 있습니다.소프트웨어를 설치하는 사람일 수 있습니다.최종 사용자일 수 있습니다.

왜일까요? 70K LOC 앱이 CPU가 포화 상태가 될 때까지 CPU 시간의 100%를 소비하기 시작하는 이유를 알아내야 했습니다.그것은 놀라운 루프가 되었다.크고 지저분했지만 결국 다음과 같이 요약된다.

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

다른 최종적인 지점은 없었다.값이 if 조건과 일치하지 않으면 루프는 종료될 때까지 계속 실행됩니다.

물론 프로그래머는 프로그래머가 기대하는 값을 선택하지 않은 것에 대해 최종 사용자를 비난했습니다.(그 후 코드의 while(true) 인스턴스를 모두 삭제했습니다.)

IMHO while(true)과 같은 구문을 사용하는 것은 좋은 방어 프로그래밍이 아닙니다.그것은 다시 당신을 괴롭힐 것이다.

(하지만 i++에 대해서도 모든 줄에 코멘트를 하지 않으면 교수님이 점수를 매긴 것을 기억합니다.)

구조화된 프로그래밍 구조가 (어느 정도 구조화되지 않은) 문장을 중단하고 계속하는 것보다 선호된다는 점에서 좋지 않습니다.그에 비해, 그들은 이 원칙에 따라 "고토"보다 선호된다.

항상 가능한 한 구조화된 코드를 만들 것을 권합니다.하지만 Jon Sket이 지적한 바와 같이 더 이상 구조화하지 마십시오.

내 경험에 따르면 대부분의 경우 루프는 계속하기 위한 "주요" 조건을 가지고 있습니다.와중()을 사용하다루프를 끊을 가능성이 있는 다른 모든 조건은 세컨더리이며 그다지 중요하지 않습니다.으로 쓸 수 .if() {break}★★★★★★★★★★★★★★★★★★.

while(true)가 혼동되어 읽기 어려운 경우가 많습니다.

나는 이 규칙들이 100%가 아닌 98%의 사례만을 대상으로 한다고 생각한다.

할 수 없지만, 왜 「」를 사용하지 는 대답할 수 없습니다.while (true), 나는 항상희극과 함께 나오는 작가의 진술이 왜 do-while 대신 do-while을 해야 하는지에 대한 간결한 설명이라는 것을 발견해 왔다.

문의하신 내용에 대해서:에는 본질적인 문제는 없습니다.

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

...당신이 뭘 하고 있는지 알고 있고, 확실히 한다면exit_time true

이 사용하는 것을 하지 않습니다.while(true)왜냐하면 당신이 정확히 무엇을 하고 있는지 알 수 있는 지경에 이르기 전까지는, 그리고 그렇지 않다면, 그것은 결정적인 실수를 저지르는 쉬운 방법이기 때문이다.

부울 플래그를 사용하여 while 루프를 종료할 타이밍을 지정할 수 있습니다. Break ★★★★★★★★★★★★★★★★★」go to소프트웨어가 유지보수가 어려운 이유, 즉 소프트웨어 관리(tm)는 피해야 하며, 피해야 하며, 쉽게 그럴 수도 있습니다.

그것은 당신이 실용적인지 아닌지에 대한 질문이다.실용적인 코드 작성자는 그 간단한 상황에서 휴식 시간을 사용할 수 있습니다.

않으면 복잡한 및 등 할 수 .그렇지 않으면 코드 가독성과 유지보수가 어려워지는 복잡한 중첩 루프 등 부적절한 상황에서 Habbit에서 사용할 수 있습니다.break.

네, 꽤 안 좋은 것 같아요.적어도 많은 개발자들에게는요.루프 상태에 대해 생각하지 않는 개발자의 징후입니다.따라서 오류가 발생하기 쉽습니다.

while(true)break그러나 일부에서는 코드 가독성을 약간 떨어뜨린다고 생각할 수 있습니다.변수에 의미 있는 이름을 지정하고 적절한 위치에서 식을 평가합니다.

예를 들어 다음과 같은 작업을 수행하는 것이 훨씬 명확해 보입니다.

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

하는 동안에 하다추가 반복이 발생하고 있는지 확인하기 위한 체크 위치를 정확히 알 수 있습니다.모든 변수/함수는 추상화 수준에서 적절한 이름을 가집니다.while(true)스테이트먼트는 처리가 생각대로 되지 않는다는 것을 나타냅니다.

두 번째 루프에서 다른 출력이 필요할 수 있습니다.뭐랄까

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

그때가 더 가독성이 있는 것 같다.

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

다시 말씀드리지만, 둘 다 읽기 쉽지만, 루프가 매우 커졌거나 깊이 중첩된 경우(즉, 이미 리팩터링을 했어야 한다는 의미) 첫 번째 스타일은 조금 더 명확할 수 있습니다.

나는 운이 없는 것 같아.아니면 그냥 경험이 부족해서 그런 거든지요.하지만 매번 생각날 때마다while(true) 있다break내부에서는 추출 방법why-block적용하는 코드를 개선할 수 있었습니다.while(true)가 모든 것을 시켰다.break는 에 s s sreturns.

경험으로는 ★★★★★★★★★★★★★★★★★★★★★★.while(true)휴식 없이(리바운드 또는 던지기 포함) 꽤 편안하고 이해하기 쉽습니다.


  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);
      }
  }

저는 비슷한 것을 사용하지만, 반대 논리를 가진 많은 기능에서 사용합니다.

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 */
}

심미적인 것에 가깝고, 루프가 루프 선언에서 멈추는 이유를 명확하게 알 있는 코드를 읽는 것이 훨씬 쉽습니다.

일반적으로 그것이 좋은 아이디어로 여겨지지 않는 이유는 당신이 그 구조를 최대한의 잠재력을 발휘하기 위해 사용하지 않기 때문이라고 말하고 싶습니다.또, 많은 프로그래밍 강사들이 학생들이 "가방"을 들고 들어오는 것을 좋아하지 않는다고 생각하는 경향이 있습니다.내 말은 그들이 학생들의 프로그래밍 스타일에 가장 큰 영향을 주는 것을 좋아한다는 것이다.그래서 아마도 그것은 단지 교관의 짜증일 것이다.

문제는 가독성입니다.

true 조건의 while 스테이트먼트는 루프에 대해 아무것도 알 수 없습니다.그것은 그것을 이해하는 일을 훨씬 더 어렵게 만든다.

이 두 부분 중 어떤 부분이 더 이해하기 쉬울까요?

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

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

선생님에게 휴식을 취하는 것은 열매를 얻기 위해 나뭇가지를 부러뜨리는 것과 같기도 하고, 다른 속임수를 써서 열매를 얻고 그 가지는 아직 살아있도록 하는 것과 같기도 하군요.:)

1) 1 1 1do -while(true)

2) 선생님이 틀렸어요.

NSFS!!:

3) 대부분의 교사는 프로그래머가 아닌 교사입니다.

루프가 백그라운드 스레드에서 실행되면 좋지 않을 수 있으므로 UI 스레드를 종료하여 응용 프로그램을 닫으면 해당 코드 조각이 계속 실행됩니다.다른 사람들이 이미 말한 것처럼, 당신은 항상 어떤 종류의 수표를 사용해서 취소 방법을 제공해야 합니다.

언급URL : https://stackoverflow.com/questions/6850380/are-whiletrue-loops-so-bad

반응형