GOTO문, 발전의 흔적

in #kr7 years ago

최근 스팀잇을 시작해서 서툴긴 하지만 이전에 썼던 글을 옮겨봅니다.
아무래도 소스코드가 있는 글은 마크다운이 편한데 다행이네요
피드도 붙힐 수 있음 좋겠네요

GOTO문, 발전의 흔적

목차

  1. GOTO문
  2. 옛 선인들의 이야기
  3. 역사를 계승하고 발전한 고급언어

Go to Statement Considered Harmful

당신은 GOTO문을 아는가?
이제는 우리의 기억 속에 잊혔던 굴욕적인 이름.
가끔씩 지식인들은 이를 들쳐내고는 하는 말이 있다.

"쉿, 이 구문은 절대 사용해서는 안돼"

Edsger Wybe Dijkstra

그렇다면 도대체 GOTO문이란 무엇인가?
자기가 원하는 코드로 언제든지 옮겨 다닐 수 있는 마법의 키워드
그것이 바로 GOTO이다.

그런 것이 어딨냐고?
그렇다면 당신은 구조화 프로그래밍에 익숙해진 것이다.

꿈을 갖고 배우며, 변화를 도모하기에 너무 늦은 때란 없다
Theodore Isaac Rubin

어셈블리어에서는 jump라는 명령어가 있었다.
프로그램은 기본적으로 위에서 아래로 왼쪽에서 오른쪽으로 명령어를 시행해간다.
그런데 jump를 사용하면 원하는 어디든 갈 수 있다.
마치, 하이퍼링크처럼 소스와 소스를 이어준다.

아직 plan calcul이 일어나기 전에는
많은 이들이 이것을 가지고 프로그램을 제어하고 반복시키며 문명을 만들어 갔다.

고급언어가 만들어지고, if문과 for문이 확립되면서
많은 것들이 변했지만 아직까지 jump명령어의 필요성이 존재하였고
GOTO명령어는 컴파일단에서 jump명령어로 변경되는 유일한 행위로 자리잡게 된다.

내 삶이 구닥다리가 되고
옛 추억이 되어 버려서
더 이상 현재를 만들 수 없을 때
어느덧 나는 늙어버렸다
-별 그리운 시

많은 날이 지나가고
어느 날이 되었을 때

GOTO문은 더 이상 프로그래밍에 사용되지 않은 구닥다리 트렌드였다

많은 지식인들이 해롭다며 울부짖었다.
일부의 선인들은 진지하게 왜 해로운지에 대해서 토의하기 시작했다.

무조건 goto문은 나쁘다?

그렇게 오래되지 않았던 토의가 벌써 10년이란 세월을 맞았다.
이 토의의 결론을 요약하자면

GOTO문이 사용되어야 하는 부분은 존재한다.
1, 다중 루프를 빠져나올 때
2, 예외 처리를 해야 할 때
이 두 가지는 모든 프로그램 로직에서 필요로 하다
그렇기에 GOTO문은 이런 부분에서는 사용되어야 한다.

최근의 언어는 이러한 부분을 지원한다.
아래는 대표적인 코드이다

for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
        for(int k=0;k<10;k++){
            //루프 break;
        }
    }
}

다중루프를 빠져나오는 문제
여기서는 다중루프를 빠져나올 수 없다

breakPoint :
for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
        for(int k=0;k<10;k++){
            break breakPoint;
        }
    }
}

자바에서의 다중루프 빠져나오기
breakPoint 레이블을 사용하여 빠져나온다

int sock_create_lite(int family, int type, int protocol, struct socket **res)
{

        err = security_socket_create(family, type, protocol, 1);
    if (err)
        goto out;

    sock = sock_alloc();
    if (!sock) {
        err = -ENOMEM;
        goto out;
    }

    sock->type = type;
    err = security_socket_post_create(sock, family, type, protocol, 1);
    if (err)
        goto out_release;
out:
    *res = sock;
    return err;
out_release:
    sock_release(sock);
    sock = NULL;
    goto out;
}

/*소켓 인터페이스 구현(linux/net/socket.c:1027-1054) 중 발췌.
(GPL 라이센스 및 커밋 3c435c) */

예외처리를 해야 할 때

int sockCreateLite(int family, int type, int protocol, Socket socket)
{
   int resultCode=0;
   try{
        security_socket_create(family, type, protocol, 1);
        sock = sock_alloc();
        sock.type = type;
        security_socket_post_create(sock, family, type, protocol, 1);
        return resultCode;
    }catch( SocketCreateException sce){
        resultCode = SCE;
        return resultCode;
    }catch( SocketAllocException sae){
        resultCode= -ENOMEM;
        return resultCode;
    }catch( SocketPostCreateException spce ){
        sock_release(sock);
        sock = null;
        resultCode = SPCE;
        return resultCode;
    }finally{
        res = sock;
    }
}

자바에서의 예외처리 해결

1, 사용자 정의 EXCEPTION클래스는 사전에 정의 됨.
2, 아래 소스는 위의 소스를 java형식으로 변형했습니다.

///

lable break와 try-catch-finally문을 이용한 해결책에는 두 가지 방법으로 goto문을 숨겼다.

1, lable break는 goto문의 기능을 제약시킴으로써 구조화를 이끌어냈다.
2, try-catch-finally문은 예외를 통일시키는 형식을 사용함으로써 구조화를 이끌어냈다.

현재, GOTO문은 뜨거운 감자가 아니다.
어쩌면 기억하고 있는 사람도 몇 없을지 모른다.

참고문헌

https://ko.wikipedia.org/wiki/Goto_%EB%AC%B8
https://namu.wiki/w/GOTO#fn-2
https://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java
https://kldp.org/node/40440
Go To Statement Considered Harmful - 논문
Structured Programming with goto Statements - 논문