'goto' 검색 결과 1건

  1. 2008.12.11 모드 없는 소스코드 (4)

스터디를 하면서 속으로:
프로그래밍에는 어떻게 적용할 수 있을까? 서비스 기획에는 어떻게 적용할 수 있을까? 조직에는 어떻게 적용할 수 있을까?
등등을 생각하고 있습니다. 알고 있는 지식들을 서로 연결짓는... 일종의 놀이죠. 개인적으로 이 방법에서 많은 도움을 받고 있습니다. 김창준님께 들은 이야기들, 개인위키를 쓰면서 생긴 습관 등이 두루 작용한 것 같아요.


모드(mode)와 변수(variable)

직전 글에서 모드 없는 인터페이스에 대한 요약문을 썼는데요, 프로그래밍에서의 모드란 변수가 아닐까 하는 생각을 해봤습니다.

사용자 인터페이스에서 모드란 아래와 같이 정의됩니다:
사용자의 제스처에 대해 인간-기계 인터페이스가 다음의 두 조건을 만족시킬 때, 그 인터페이스는 모드적이라 할 수 있다. (1) 인터페이스의 현상태가 사용자의 주의 소재가 아니며, (2) 인터페이스가 하나의 제스처에 대해 시스템의 현상태에 따라 달리 반응한다. --p54
프로그래밍에서의 모드란 아래와 같이 정의할 수 있겠습니다:
소스코드가 다음의 두 조건을 만족시킬 때, 그 소스코드는 모드적이라 할 수 있다. (1) 변수의 현재 값이 개발자의 주의 소재가 아니며, (2) 하나의 모듈(문장, 표현식, 함수, 객체, 서브시스템 등)이 변수의 현재 값에 따라 달리 작동한다.
이 정의에 의거하여 "모드 없는 소스코드"를 만들려면 아래와 같은 노력들을 해볼 수 있겠습니다:
  • 함수의 길이가 짧아야 합니다. 함수의 동작에 영향을 주는 요인들(파라메터, 지역변수, 인스턴스 변수, 전역변수 등)의 상태를 머리속으로 추적하는 일이 점점 어려워집니다. 함수의 길이가 짧으면 짧을수록 (1)에 해당하는 상황에 직면한 소지가적어집니다.
  • 함수에서 의존하는 파라메터/지역변수/인스턴스 변수/전역변수가 적을수록 좋습니다. 의존하는 변수의 수가 줄어들면 (2)에 직면할 소지가 줄어들 뿐 아니라, 기억할 변수의 수가 줄어들기 때문에 (1)을 회피하는 일에도 도움을 줍니다.
변수 중에서도 특히나 위험한 변수라면 주의 소재에서 멀어진 변수들이겠죠. 주의 소재에서 멀어질 가능성이 높은 것에서 낮은 순으로 줄을 세워보면 전역변수->클래스변수->인스턴스변수->지역변수 및 파라메터 순이 될 것입니다. 이 관점에서 보더라도 역시 전역 변수는 제거 대상 1순위 입니다.

이 예시에서는 함수라는 단위를 다루고 있지만 의존(dependency)의 자기유사성(self-similarity)에서와 비슷한 방식으로 더 큰 단위나 더 작은 단위에 적용해볼 수 있을 것입니다.

(Jef Raskin이 모드 없는 인터페이스라는 이상을 추구하는 것을 보면서 순수한 함수형 언어가 아련히 떠올랐는데 이에 대해서는 다음 기회에 써볼게요.)


모드와 숨은 변수들

한편, 프로그래밍 언어에서 변수라고 불리는 것들만이 시스템의 상태인 것은 아닙니다. 문법상 변수는 아니지만 변수 역할을 하고 있는 숨은 변수들이 있게 마련이죠. 특히 전역 변수라는 것은 여러 가지 섹시한 옷을 입고 마치 전역 변수가 아닌 척 하면서 개발자를 유혹하곤 합니다.

싱글톤 패턴(singleton pattern)이라는 멋진 이름으로 불리기도 하고, ServletContext, ActionContext 같이 "뭐시기 Context"라는 이름으로 불리기도 합니다. 전역 변수의 둔갑술에 대한 글은 응주님의 글 시대에 따른 전역 변수의 변신을 참고하시기 바랍니다.


모드와 GOTO

마지막으로, 위에서 설명한 숨은 변수들보다 더 깊고 찾기 힘든 숨은 상태(hidden states)를 만들어내는 주범이 있으니, 바로 그 유명한 GOTO 문입니다. 다익스트라는 그 유명한 Goto Statement Considered Harmful에서 이런 말을 합니다:
We should do (as wise programmers aware of our limitations) our utmost to shorten the conceptual gap beween the static program and the dynamic process, to make the correspondence between the program(spread out in text space) and the process(spread out in time) as trivial as possible.

우리는(자신의 한계를 잘 인식하고 있는 현명한 프로그래머로서) 정적인 프로그램과 동적인 프로세스 사이의 개념적 격차를 줄이기 위해 최선을 다해야 한다. 텍스트 공간 상에 펼쳐져 있는 프로그램과 시간 상에 펼쳐져 있는 프로세스 사이의 대응을 최대한 쉽게 하기 위해서다.
프로그래밍을 한다는 것은:
  • 소스 코드를 읽으면서 이 코드의 실행 결과, 즉 프로세스를 그려내거나
  • 원하는 프로세스로부터 소스 코드를 만들어내는
것인데, 소스 코드라는 것은 2차원 평면(종이 혹은 편집기 화면)이라는 공간 상에 펼쳐진 문자열인 반면, 프로세스는 시간 상에 펼쳐진 개념입니다. 따라서 이 둘 사이의 차이가 적을 수록 프로그래밍이 (읽고/쓰기에) 쉬워진다는 것입니다.

소스 코드를 읽으면서 이 코드가 어떻게 실행될지를 상상하는 일, 즉 코드를 통해 프로세스를 유추하는 일을 할 때 우리는 머리 속에 숨은 변수들을 만들어내야 합니다. 예를 들어 제어문(조건문/반복문 등)이 전혀 없는 코드는 위에서 아래로 순서대로 실행되는데, 이러한 코드는 시간과 공간 사이의 대응이 아주 쉽습니다. 머리 속에 기억하고 있어야 할 숨은 변수는 딱 하나, "지금 몇 번째 줄 까지 실행되었나" 입니다. 이 머리 속 변수를 textural index라고 합니다.

하지만 프로시저(procedure) 혹은 함수(function) 같은 개념을 도입하는 순간 변수 하나로는 프로세스를 추적하는 것이 불가능해집니다. 하지만 호출 스택(call stack) 깊이 만큼의 textual index가 있으면 해결 가능하니 큰 문제는 아닙니다.

반복문이 추가되면? 특정 반복 구간(loop나 for 문의 body)을 읽는 중에는 추가적인 변수를 머리 속에 기억하고 있어야 합니다. 바로 "지금 여기 몇 번째 돌았나?" 하는 지표죠. 이를 dynamic index라고 합니다. 물론 모든 반복(repetition)은 재귀(recursion)로 표현 가능하기 때문에 dynamic index 개념은 필요 없을 수도 있습니다만, 지금 논의에서 이게 필요하냐 안하냐는 중요한 문제가 아니므로 넘어갑시다.

지금까지 설명한 index들을 프로그래머 독립 좌표계(programmer independent coordinate system)라고 하는데 이게 바로 숨은 변수(혹은 숨은 상태)들입니다.

함수와 반복문이 있는 코드의 동적 프로세스를 추적하기 위해서는 위에서 설명한 바와 같이 몇 개의 잘 정의된 프로그래머 독립 좌표계들을 기억하고 있으면 됩니다. 그리고 이 좌표계의 값들은 동적 프로세스의 이해를 직접적으로 도와줍니다. 예를 들면 "지금 루프를 다섯번 돌았으니까, x라는 변수의 값은 5 * 2, 즉 10 이겠군" 하는 식의 추론이 가능해집니다.

한편, GOTO가 추가되면? 의미 있는 프로그래머 독립 좌표계가 사라질 수 있습니다. 물론 모종의 index를 만들 수는 있겠죠. 다익스트라는 "프로그램 실행 후 지금까지 수행된 명령어 갯수" 같은 index를 예로 들고 있습니다. 프로그램이 외부 상태에 영향을 받지 않는다면 이 index 하나만으로 프로세스의 임의의 순간을 온전히 기록할 수 있습니다. 하지만 이 index를 가지고 프로세스에 대해 의미있는 추론을 하는 것은 더이상 가능하지 않습니다. ( 어려운 얘기 같은데, 쉽게 말해서 "스파게티 코드"가 된다는 말입니다 --; )

GOTO 문이 있는 상황에서 코드의 동적 프로세스에 대한 의미 있는 추론을 하려면 온갖 index를 임시 방편으로 만들어서 머리 속에 우겨 넣어야 하는데(혹은 종이에 적을 수도 있겠습니다만), 이것들이 바로 모드 오류를 일으키기에 딱 좋은 숨은 변수(혹은 상태)들인거죠.

따라서,드 없는 소스코드라면 최소한 구조적 프로그래밍 정도는 기본으로 해주어야 한다는 얘기입니다. (헥헥 글재주가 없으니 참말 어렵게도 쓰는군요 쩝)

신고
< Newer     Older >

티스토리 툴바