태그 보관물: coding-style

coding-style

이것이 goto 진술을 정당화합니까? = false;

나는 두 번째 전에이 질문을 보았고 거기에서 몇 가지 자료를 가져 왔습니다 . ‘break n’구문의 이름이 있습니까?

이것은 사람들이 프로그램을 이중 중첩 for 루프에서 벗어나도록 지시 해야하는 복잡한 방법으로 보입니다.

for (i = 0; i < 10; i++) {
    bool broken = false;
    for (j = 10; j > 0; j--) {
        if (j == i) {
            broken = true;
            break;
        }
    }
    if (broken)
        break;
}

나는 goto 선언이 악마라고 말하는 교과서들을 알고 있으며, 나는 그것들을 전혀 좋아하지 않지만 규칙에 대한 예외를 정당화합니까?

n-nested for 루프를 다루는 답변을 찾고 있습니다.

참고 : 예, 아니요 또는 그 사이의 어딘가에 상관없이 완전히 가까운 대답은 환영 하지 않습니다 . 특히 대답이 ‘아니요’인 경우 왜 합법적 인 이유를 제시해야합니까 (어쨌든 Stack Exchange 규정에서 너무 멀지 않음).



답변

루프에 대해 열악한 조건식을 선택 하면 go-to 문이 분명히 필요합니다 .

외부 루프를 최대한 길게 유지 i < 10하고 가장 안쪽 루프를 계속 유지하고 싶다고 설명합니다 j > 0.

그러나 실제로는 그것이 원하는 것이 아닙니다. 루프에 평가하려는 실제 조건을 루프에 알려주지 않고 break 또는 goto를 사용하여 해결하려고합니다.

루프에서로 시작하려는 진정한 의도를 말하면 중단하거나 갈 필요가 없습니다.

bool alsoThis = true;
for (i = 0; i < 10 && alsoThis; i++)
{
    for (j = 10; j > 0 && alsoThis; j--)
    {
        if (j == i)
        {
            alsoThis = false;
        }
    }
}


답변

이 경우 코드를 별도의 루틴으로 리팩터링 한 다음 return내부 루프에서 리팩터링 할 수 있습니다. 그것은 외부 루프에서 벗어날 필요성을 무효화합니다.

bool isBroken() {
    for (i = 0; i < 10; i++)
        for (j = 10; j > 0; j--)
            if (j == i) return true;

    return false;
}


답변

아니요, goto필요 하다고 생각하지 않습니다 . 다음과 같이 작성하면

bool broken = false;
saved_i = 0;
for (i = 0; i < 10 && !broken; i++)
{
    broken = false;
    for (j = 10; j > 0 && !broken; j--)
    {
        if (j == i)
        {
            broken = true;
            saved_i = i;
        }
    }
}

&&!broken두 루프에 모두 있으면 두 루프에서 벗어날 수 있습니다 i==j.

나 에게이 접근 방식이 바람직합니다. 루프 조건은 매우 명확 i<10 && !broken합니다.

작업 버전은 여기에서 볼 수 있습니다 : http://rextester.com/KFMH48414

암호:

public static void main(String args[])
{
    int i=0;
    int j=0;
    boolean broken = false;
    for (i = 0; i < 10 && !broken; i++)
    {
        broken = false;
        for (j = 10; j > 0 && !broken; j--)
        {
            if (j == i)
            {
                broken = true;
                System.out.println("loop breaks when i==j=="+i);
            }
        }
    }
    System.out.println(i);
    System.out.println(j);
}

산출:

i == j == 1 일 때 루프 중단
2
0


답변

짧은 대답은 “그것은 달려있다”입니다. 코드의 가독성과 이해 가능성에 대해 선택하는 것을 옹호합니다. 이동 경로는 조건을 조정하는 것보다 더 읽기 쉬울 수 있습니다. 또한 상점 / 프로젝트에서 사용되는 지침과 코드베이스의 일관성을 최소한의 놀라움의 원칙으로 고려할 수도 있습니다. 예를 들어 스위치를 나가거나 오류 처리를하는 것은 Linux 커널 코드 기반의 일반적인 관행입니다. 또한 일부 프로그래머는 코드를 읽는 데 문제가 있거나 ( “goto is evil”만트라로 제기되거나 교사가 그렇게 생각하기 때문에 배우지 못했을 수 있음) 일부 사용자는 “심판”할 수도 있습니다.

일반적으로 말하면, 특히 점프가 너무 길지 않은 경우 같은 기능으로 더 나아가는 것이 허용됩니다. 중첩 루프를 떠나는 유스 케이스는 “나쁘지 않은”goto의 알려진 예 중 하나입니다.


답변

귀하의 경우 goto는 유혹적으로 보일 정도로 개선되었지만 코드베이스에서 규칙을 사용하는 것에 대한 규칙을 어길 가치가있는 것은 아닙니다.

미래의 검토 자에 대해 생각해보십시오. “그 사람은 나쁜 코더입니까, 아니면 실제로 고토가 가치가있는 경우입니까?”라고 생각해야합니다. 인터넷.” goto를 완전히 사용할 수 없을 때 왜 미래의 코더에게 그렇게 할 것입니까?

일반적으로이 사고 방식은 모든 “나쁜”코드에 적용되며 심지어 정의하기까지합니다. 지금 작동하고이 경우에는 좋지만이 코드가 올바른지 확인하기 위해 노력합니다. 해.

즉, 당신은 약간 더 가시적 인 사례 중 하나를 생산했습니다. 당신은 할 수있다:

  • 부울 플래그와 같이 더 복잡한 제어 구조를 사용하여 두 루프를 모두 분리하십시오.
  • 내부 루프를 자체 루틴에 넣으십시오 (아마 이상적)
  • 두 루프를 루틴에 넣고 깨지 않고 반환

이중 루프가 너무 응집력이 없어서 자체 루틴이되어서는 안되는 경우를 만드는 것은 매우 어렵습니다.

그건 그렇고, 내가 본 이것에 대한 가장 좋은 토론은 Steve McConnell의 Code Complete 입니다. 이 문제들을 비판적으로 생각하는 것을 좋아한다면, 그 책의 내용은 엄청나지만 책을 읽거나 읽을 것을 강력히 권합니다.


답변

TLD; DR : 구체적으로 아니오, 일반적으로 예

당신이 사용한 특정 예에서 나는 다른 많은 사람들이 지적한 것과 같은 이유로 no라고 말할 것입니다. 코드를 동등하게 좋은 형식으로 쉽게 리팩터링 할 수 있으므로 goto.

일반적으로 금지 규정 goto은 이해의 본질 goto과 사용 비용에 근거한 일반성 입니다. 소프트웨어 엔지니어링의 일부는 구현 결정을 내립니다. 이러한 결정에 대한 정당화는 비용과 이점을 비교함으로써, 그리고 이점이 비용을 능가 할 때마다 구현이 정당화됩니다. 비용과 이익 모두 다른 평가로 인해 논란이 일어납니다.

요점은 a goto가 정당화 되는 경우 항상 예외가 있지만 다른 평가로 인해 일부에만 적용 된다는 것 입니다. 안타깝게도 많은 엔지니어들은 이유를 이해하기 위해 시간을 내기보다는 인터넷에서 기술을 읽기 때문에 의도적으로 무지한 기술을 배제합니다.


답변

나는이 경우가 다음과 같이 쓰여질 수 있기 때문에 예외를 정당화한다고 생각하지 않는다.

def outerLoop(){
    for (i = 0; i < 10; i++) {
        if( broken?(i) )
          return; // broken
    }
}

def broken?(i){
   for (j = 10; j > 0; j--) {
        if (j == i) {
            return true; // broken
        }
   }
   return false; // not broken
}