You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
몇 가지 원칙을 이론적으로 설명해야 하는데 이렇게 할 수 밖에 없는 이유는 아직 경험 자료가 많이 부족하기 때문이다.
문제는 프로그래밍 언어를 설계할 때 심리학적 요인을 고려해야 함을 인정하지 않거나 또는 그렇게 인정하더라도 언어 설계자와 주변 몇 명만을 연구하는 것으로 충분하다고 생각한다는 점이다.
일관성
일반 심리학 연구 결과에 따르면 어떤 목록을 얼마나 잘 기억할 수 있는가는 그 목록에 담겨 있는 정보의 내용과 밀접한 관련이 있다. 정보의 내용은 목록에 포함되어 있는 것 뿐만 아니라 목록에 없어도 기억해야 하는 사람의 머릿속에 들어 잇는 것도 정보의 내용에 포함되기 때문이다.
이진수 체계를 아는 사람이면 이진수 순서대로 나열된 8개의 숫자 보다 몇 개가 빠져 있는 6개가 더 외우기 어려울 수 있는데, 빠진 것이 무엇인지 알고 기억해야 하기 때문이다.
만약 이진수 체계를 모른다면 갯수가 적은 쪽을 더 잘 외울 수 있다.
프로그래밍에서도 같은 현상이 발생하는데 FORTRAN의 배열 첨자 규칙이 예이다. 산술 표현식 체계를 모르는 프로그래머에게는 FORTRAN이 더 외우기 쉬운데, 첨자로 사용할 수 있는 표현식 개수가 PL/1이나 APL에 비해 적기 때문이다. 문제는 산술 표현식을 모르는 프로그래머가 없기 때문에 첨자로 사용될 수 있다는 규칙만 알면 되는 걸 FORTRAN의 경우는 7가지 형식의 표현만 첨자로 사용할 수 있다는 걸 외워야 한다.
일관성의 원칙이 무엇인가를 명료한 문장 하나로 단정하지 않은 것은 수학적이라기 보다 심리학적이기 때문이다. 그래도 프로그래밍 언어의 일관성을 굳이 한 문장으로 정의하자면 이렇다.
"동일한 표현은 그 위치와 상관없이 동일하게 동작한다."
프로그래밍 언어가 이 원칙에서 멀어질수록 배우기가 어렵고 프로그래머가 오류를 범할 가능성도 커진다.
일관성의 중요성을 확인하기 위해 같은 프로그램을 두 언어로 작성하는 비교 실험을 했다.
OS/360용 Pl/1과 DOS/360용 PL/1인데, DOS용 PL/1은 OS용 PL/1의 부분 집합이다.
DOS용 PL/1을 사용한 프로그래머들은 DOS용에도 있는 기능인데도 사용하지 않은 경우가 많았는데, 그 기능을 쓸 수 있는지 확신이 서지 않았다는 대답이었다.
표 12-1 한 프로그래밍 언어와 그 부분 집합인 언어의 비교
평균 실행 횟수
평균 실행 시간
평균 코드 줄 수
원래의 언어
32
1
243
부분 집합인 언어
41
1.2
319
사람들은 금기가 많을수록 은연 중에 또 다른 금기가 있을 것이라 예상한다. 언어에 존재하는 제약 사항은 그것이 적용되는 영역 밖에서도 영향력을 발휘한다. 그래서 일관성의 원칙을 이렇게도 정의할 수 있다.
"어떤 프로그래머가 '이런 표현도 쓸 수 있을까?' 라고 물을 때 답은 반드시 '쓸 수 있다'여야 한다"
일관성의 원칙은 문법적으로 동일한 구문은 문맥이 달라도 동일한 의미를 지녀야 한다는 뜻이기도 하다. 일관적이지 못한 문법은 프로그래머가 여러 가지 의미론적인 시도를 하는 데 장애물이 된다. 프로그래머가 자신이 사용하는 프로그래밍 언어에 혼란을 느끼면 일을 제대로 할 수 없을 것이다.
불명확함에 두 가지 종류가 있는데 물리적인 불명확성이고, 다른 하나는 심리적인 불명확성이다. 물론 컴파일러에는 불명확성이 없다. 그러나 컴파일러 구현마다 해석이 다를 수 있기 때문에 모든 구현이 필요 이상으로 차이를 보이지 않도록 언어 자체에서 이런 종류의 불명확성을 제거하는 일은 중요하다. 그러나 물리적 불명확성을 제거한다고 해서 심리적 불명확성까지 사라지는 것은 아니다.
언젠가는 프로그래밍 언어 설계자들이 불명확성에 이렇게 두 가지 종류가 있음을 인지하고 대처할 날이 올 것이다. PL/1의 WHILE처럼 불명확한 사례가 드물게 발생하는 경우에는 이 방법이 유용할 것이다. 불명확성을 없애고 싶다면 프로그래머가 WHILE이라는 이름의 배열을 사용할 때만 적용되는 감춰진 규칙을 언어에 심어 놓는 것이다. 그러면 이름이 WHILE인 배열이 나타날 때 컴파일러가 프로그래머에게 변경하라고 알려주면 된다. 지금도 컴파일러가 그런 상황에 대해 알려주기는 하지만 경고 메시지 보다는 키워드를 변수 이름으로 사용하려는 멍청한 프로그래머만 오류 메시지로 보여주는게 좋을 것이다.
일관성의 마지막 측면으로 언어 설계자가 모든 비난을 받는 건 온당치 않다. 프로그래머가 지은 죄가 훨신 큰 경우도 있다. 변수 이름으로 키워드를 사용하기는 그 프로그램을 읽는 사람을 혼란스럽게 만든다. 그 밖의 예로 아무 이유 없이 변수의 크기를 매번 다르게 선언하기, 약어와 완전한 단어를 번갈아가며 쓰기, 코드 들여쓰기와 빈칸 넣기를 마음대로 하기, 주석을 과하게 추가하거나 어려워 보이는 코드에는 주석을 달지 않는 경우가 있을 것이다.
프로그래머가 일관성을 해치는 대표적인 경우는 변수 이름으로 쓸 의미 있는 단어를 잘못 고르는 것이다. OLDX에 X의 예전 값이 할당되어 있지 않고, SUMAB가 A와 B의 합이 아니며, BIGGEST에 실제로 가장 큰 값이 들어있지 않은 경우가 그렇다. 하지만 이 교훈을 아무리 얘기해도 이런 잘못된 생각은 사라지지 않을 것이다. 언어 자체가 일관성이 결여된 것과 마찬가지로, 이런 습관은 우리가 진실이 아닌 부분을 믿도록 만들기 때문에 우리 자신에게 해가 된다.
디버깅 관점에서는 일관성이 아예 없는 경우보다 일관적이고 매우 드물게 예외가 있는 상황이 더 안좋은 상황이다. 예외가 적다면 방심하기 쉽기 때문이다.
간결성
누구에게나 긴 프로그램보다는 짧은 프로그램이 더 이해하기 쉽다고 할 수 있다. 그러나 프로그램이 얼마나 간결한지를 단순히 그 소스에 얼마나 많은 글자가 들어 있는가로 판단할 수는 없다. 표현식 A + B 보다 BIG + SMALL 이해하기가 더 쉬운데 사고 과정에서 글자 하나를 쓰기 보다는 단어를 사용하는 습관이 있기 때문에 그렇다. 사고 과정에서 BIG 같은 단어는 A 같은 단어와 동일하게 취급된다.
심리학에서 여러 작은 단위를 조합해서 커다란 단위 하나로 묶고 그렇게 만들어진 큰 단위도 각각을 구성한 하위 단위와 마찬가지로 쉽게 다루는 능력을 의미덩이 만들기(chunking)라 부른다. 이건 의식적인 노력 없이 수행하는 자연스러운 인지 과정이다. 그러나 의미덩이를 만들려면 먼저 그 의미덩이를 경험을 통해 학습해야 한다. 2진수를 몰랐을 때는 서로 별개인 두 글자로 기억해야 할텐데 이진수를 8진수나 16진수의 의미덩이로 변환하는 방법을 알게 되면 예전보다 이진수가 더 짧아 보이게 된다.
자연어 연구를 통해 나온 지프(Zipf)의 법칙이 있는데, 자주 사용하는 단어일수록 길이가 짧은 경향이 있다. 'is', 'the', 'a' 등이 해당되고 'don't'나 'there's' 같은 단어도 지프의 법칙에 의해 압축된 예로 볼 수 있다.
프로그래밍에서는 압축된 표현을 많이 볼 수 있다. PROCEDURE 대신에 PROC로 사용하기 시작하는 경우가 있다. 순차적으로 나열하는 항목을 DO 구문을 쓰거나 SUM 함수를 사용해서 코드를 작성하는 경우처럼 한 기능을 더 강력한 기능으로 대체하는 과정에서도 일종의 압축이 발생한다.
또 다른 압축 형태로 데이터의 구조화가 있다. 반복이나 함수 보다 훨씬 더 강력하다고 볼 수 있다.
적절한 데이터의 구조화를 통해 표현을 압축하는 방법으로 연산의 차원을 높이는 것도 있다. 문자열 데이터 구조가 그 예인데 문자열 데이터도 일련의 비트이지만 어떤 문자열의 값을 바꿀 때에는 각 비트를 하나씩 수정하는 것이 아니라 다른 문자열 값을 대입하는 연산 하나로 끝낸다.
표현의 압축은 생략을 통해서도 이뤄진다. 특정한 경우에 대한 표현을 완전히 생략하는 것인데 PL/1 에서 SKIP(1) 대신 SKIP을 사용해도 되는 건 SKIP(1)이 가장 자주 사용되기 때문이다. 변수 선언시에도 속성을 생략할 수도 있다.
DECLARE X;
DELCARE X FLOAT DECIMAL(6) REAL AUTOMATIC INTERNAL;
두 코드가 선언한 변수는 동일하다. 그리고 선언문을 생략해도 변수 X가 암시적으로 또는 문맥적으로 선언되는 경우가 많다. 글을 쓸 때는 정보를 중복함으로써 얻어지는 부담이 더 큰 편이기 때문에, 프로그래밍 언어에서 잘 만들어진 디폴트 체계는 충분한 가치가 있다.
중복 정보를 적절한 방식으로 제거한다면 지루함을 덜고 실수도 줄일 수 있다. 그러나 존재할 가능성이 있는 중복 정보가 모조리 제거된 언어에서는 프로그램을 문법 검사하기가 불가능한데, 존재할 수 있는 문자열은 모두 그 언어에서 문법적으로 올바를 수도 있기 때문이다. 기계어 프로그래밍이 어려울 때가 있는데 그 원인이 중복 정보가 너무 과도하게 제거되어 있기 때문이라고 볼 수 있는가? 에 대한 대답은 심리적인 측면에서 쓸모 있는 중복 정보와 쓸모 없는 중복 정보를 명확히 구별해야 한다.
FORTRAN에서 A(1+I)를 금지하는 규칙은 프로그래머의 심리적 편안함이 아니라 최적화된 실행 코드로 컴파일하기가 쉽도록 만들기 위한 규칙이다. 이 표현식이 잘못이라는 것은 사실이지만 이 잘못은 우리에게 문제가 있기 때문이 아니다. 오직 FORTRAN의 제한 때문에 생긴 것이다. 어떤 의미에서, 잘못하고 있는 쪽은 프로그래머가 아니라 언어다.
근접성과 순차성
잘 설계된 프로그래밍 언어는 좋은 기억력과 마찬가지 방식으로 관련 정보를 쉽게 찾을 수 있는 곳에 담아 둬서 프로그래머를 도와준다.
관심을 가져야 할 기억력의 종류는 공감각적(synesthetic) 기억력과 순차적(sequential) 기억력이다.
공감각적 기억력은 특정 세부 사항에 의지하지 않고 얼굴이나 이웃, 책 한 페이지의 편집 배치 등을 알아볼 수 잇게 해주는 능력이다. 사물을 전체적인 하나의 심상으로 기억하는 것이다.
순차적 기억력은 청각을 통해 들은 정보와 더 밀접하게 관련되어 있다. 순차적 기억은 차례로 이어진 사슬처럼 구성되어 있어서 차례로 떠오르면서 고리마다 바로 다음에 오는 고리를 상기시키는 구조이다.
프로그램에서 근접성의 개념은 공감각 기억에 순차성의 개념은 순차적 기억에 대응한다. 근접성은 프로그램에서 서로 관련 있는 부분이 모두 한 장소에 나타나는 성질을 의미한다. 프로그래밍 언어에서 근접성을 높이는 방법 가운데 하나는 압축이다.
리터럴은 근접성을 높이는 데 도움이 되는데, 한 리터럴에 관련된 모든 정보가 그 리터럴의 내용에 모두 들어 있기 때문이다. 변수 이름만 봐도 알 필요가 있는 게 연상되도록 변수 이름을 잘 지어도 이와 같은 효과가 있다.
모든 선언을 지정된 장소에서 해야 하는 언어를 사용할 때도 어느 정도 근접성을 얻을 수 있다. 맨 앞 페이지를 떼서 옆에 두고 참조하면 되기 때문이다. 그래서 어디서나 선언을 할 수 있는 PL/1과 같은 언어에 대해 불평하는 사람도 있다.
어떤 프로그래밍 언어를 쓰더라도 디버깅할 때는 반드시 비근접성으로 인해 어떤 문제가 나타날 수 있는지를 염두에 둬야 한다.
언어가 지는 한 특징이 근접성을 저해시킨다고 해도 보통 그 특징이 언어가 잘못 설계되어서 생긴 것은 아니다. 설계가 잘못된 것이라면 그 특징을 제거하면 될 것이고, 그게 제거됐는지 아무도 관심을 가지지 않을 것이다.
프로그래밍과 비슷한 상황에서 문제를 해결하는 과정을 실험해 보면 일련의 선택들을 완전히 순차적으로만 배열하는 편이 분기나 반복이 포함된 경우보다 일반적으로 더 다루기 쉽다. 프로그래밍도 마찬가지로 GO TO 구문이나 분기문이 많은 프로그램일수록 이해하거나 디버깅하기에 더 어렵다. 이런 어려움 중 일부는 단순히 비근접성 때문이기도 하다.
고수준의 언어들은 컴퓨터의 비순차성을 보완하는 여러 장치를 제공한다.
전통과 혁신
실수할 가능성은 최소로 줄이면서 쉽게 표현할 수 있으려면, 프로그래밍 언어가 자연스러워지는 것이 가장 필요하다. 그건 일관성을 통해 얻을 수 있지만 이미 그 언어에 익숙한 프로그래머들에게만 효과가 있다.
프로그래밍 언어를 프로그래머가 알고 있을 법한 다른 언어와 비슷하게 만든다면, 새 언어로 진입하는 장벽을 낮출 수 있을 것이다.
자연어에서 프로그래밍 언어가 차용한 개념으로는 의미 있는 빈 칸을 들 수 있다. 'orate'는 'or ate'와 동일하지 않다. 빈 칸이 빠져 있는 경우는 교정이 가능한데 중복 정보나 문법적으로 혹은 의미론적으로 어느 정도 잘못되어 보이므로 교정할 수 있다.
프로그래밍 언어의 규칙이 이런 자연어의 빈 칸 규칙에 부합하지 않으면 배우기 어렵거나 최소한 디버깅하기가 더 어려울 수 있다. FORTRAN에는 다음 문장으로 대표되는 고전적은 버그 패턴이 있다.
DO33 I =1 . 20
쉼표 대신 마침표로 쓰면 이 문장은 다음과 같이 해석된다.
D033I=1.20
이건 FORTRAN에서 쓰는 빈 칸 규칙에 따라 DO33I 라는 하나의 변수 이름이 된다.
프로그래밍 언어가 자연어와 비슷해질 수 있는 영역으로는 철자법도 있다. 자연어는 철자가 틀려서 말이 안되는 다른 단어로 섞이는 경우도 그 사실을 의식하지 못한다. 반면에 프로그래밍 언어에는 대부분 의도가 무엇인지 뻔한 경우까지도 오류로 감지할 정도로 철자법에 대해서 엄격하게 대처한다.
COBOL의 경우는 군더더기 단어(noise word) 덕분에 프로그래머가 영어와 좀 더 비슷하게 느낄 수 있다.
PL/1에서도 문장 내에 있는 일부 구성 요소의 순서를 자유롭게 할 수 있는 경우가 몇 가지 있다.
DO I = 1 TO N BY K;
or
DO I = 1 BY K TO N;
DELCARE A FIXED BINARY;
or
DECLARE A BINARY FIXED;
PUT SKIP LIST(A);
or
PUT LIST(A) SKIP;
두 가지를 모두 허용하므로 사용자마다 자연스럽게 느끼는 문법을 쓸 수 있으므로 그 언어를 배우기가 쉽다. 하지만 사용자는 그 중 하나를 선택했다는 사실을 의식하지 못할 수도 있다. 배울 때 하나만 배웠다면 다른 형식을 모를 수 있고 여러 형식 사이에 의미론적으로 차이가 있을 거라고 생각해서 하나를 알게 된 다음에는 다른 것을 사용하기 꺼려할 수도 있다.
그리고 의미론적으로 차이가 있는 경우도 있다. 사실 PL/1에서 다음 두 문장의 의미는 완전히 동일하지는 않다.
DO I = 1 TO N BY K;
DO I = 1 BY K TO N;
(A=2)&(B=3)
(B=3)&(A=2)
뒤에 숨어 있는 성능의 차이 때문에 프로그래머는 느슨함을 활용하지 않게 될 수도 있다.
새로운 프로그래밍 언어를 널리 쓰이는 기존 언어와 비슷하게 설계한다면 학습 초기 단계의 속도를 높일 수 있는 건 분명하다. 그러나 초기 학습이 빠른 만큼 훗날에 치러야 할 대가도 쌓이게 된다. 두 프로그래밍 언어가 서로 완전히 똑같은 경우는 없기 때문이다.
두 언어에 차이가 있다면 억제(inhibition)라는 심리적 현상이 일어난다. 순향 억제의 경우는 먼저 학습한 내용과 나중에 학습한 내용이 비슷해서 나중의 학습이 방해를 받는 현상을 뜻한다. FORTAN과 PL/1을 쓰는 프로그래머는 두 언어의 출력 설정이나 형식을 배울 때 억제 현상이 드러난다.
비슷하지만 완전히 동일하지는 않은 두 언어를 만들면 우리는 억제라는 비용을 지불해야 한다. 따라서 완전히 동일하게 만들 수 없다면 서로 분명하게 다른 언어로 만드는 게 억제 비용을 낮추는 데 더 나을 수 있다.
프로그래머는 모두 똑같지 않은 성향을 가졌으므로 프로그래머가 이미 아는 개념이나 구조에 새로운 언어를 부합하도록 만드는 데는 분명한 한계가 있다. 언어를 느슨하게 만든다면 개인 성향에 좀 더 맞춰줄 수 있으므로 어떤 의미에서는 느슨한 언어는 프로그래머 개인의 선호에 대한 적응성이 뛰어나다고 볼 수 있다.
느슨함 외에 적응성을 높이는 방법에는 여러 가지가 있다. 함수 또는 하위 루틴을 정의할 수 있는 기능이 대표적인 예이다. 새로운 데이터 타입 정의도 그렇고 기존 연산자를 재정의하거나 새로운 연산자를 정의하는 걸 허용해주는 언어도 있다. 마지막으로 정교한 메타언어를 써서 언어의 전체 모습을 바꿔버릴 수 있는 언어도 있다.
이런 기능들을 이용해 언어에 적응하면 언어 설계자들이 일일이 파악하기 힘든 프로그래머 개개인의 개성과 어느 정도 조화를 이룰 수도 있다. 그러나 자신만의 생각과 표현 방식에 가까워지면 다른 사람의 방식과는 멀어질 수 있다. 다른 사람도 나의 프로그램을 읽고 이해할 필요가 있으므로 그런 기능들을 너무 과도하게 사용하면 안된다. 그러면 내 프로그램을 마치 정신분열증 환자의 비밀 일기처럼 볼 수도 있다.
조직의 업무 성격에 따라서는 언어의 적응력을 어느 정도 활용하는 편이 좋다. 만약 지금 쓰는 언어가 조직의 요구에 너무 벗어나 있으면 변경을 시작하기에 앞서 그 요구에 좀 더 맞는 다른 언어를 찾아보는 편이 나을 수 있다.
특수 목적 언어, 범용 언어, 장난감 언어
만약 특정 응용 분야를 대상으로 특수 목적 언어를 설계한다면, 대화 주제가 한정되므로 심리적 이익을 처음부터 누릴 수 있다.
통계용 언어는 복소수 연산 기능이 필요 없음
문자열 처리 언어는 복잡한 산술 연산이 필요 없음
기계 제어 언어는 기하학 기능이 더 필요함
언어의 기능을 제한하는 건 목적한 분야의 문제들이 일정 정도 커지지 않을 것이라는 가정인 경우도 가끔 있다.
예로 보조 기억 장치가 필요 없을 것이라는 걸 가정한다면 그 언어로는 시뮬레이션 할 수 없는 특정 문제가 있을 수 있다.
특수 목적 언어를 설계할 때는 대화의 주제를 좁히는 작업이 중요하므로 처음 부터 이 작업을 해야 하고 생각도 신중하게 해야 한다. APL의 경우가 다룰 수 있는 주제를 한정하는 작업을 잘 했기 때문에 성공할 수 있었다.
반면 APL이 설정한 범위를 넘어선 문제를 해결하려면 프로그래머들은 APL의 한계를 느낄 수 있었다. 하지만 APL에 열광하는 사람들은 그런 한계를 인식조차 하지 못한다. 그 한계가 명확하고 그로 인해 자신들이 APL에 열광했는데도 그렇다.
특수 목적 언어를 사용하는 사람이 사용하지 않는 사람 보다 이런 한계를 잘 인식하지 못하는 것은 언어가 사용하는 사람의 사고방식을 좌지우지하기 때문이다. 이건 억제 효과라기 보다는 프로그래머가 프로그램과 데이터를 조직화 하는 방식 자체를 언어가 결정한다는 뜻이다.
대부분 프로그래머는 자신의 기술 수준이 올라갔을 때 자기 충족적인 만족감을 느끼지만, 특수 목적의 프로그래밍 언어를 사용할 때는 그와 상관없이 만족감을 느끼게 되기도 한다. 언어에 의해 사고 방식이 굳어져 언어와 자신이 그 언어에 대해 알고 있는 범위 내로 문제를 제한해 파악할 수 있기 때문이다.
그런데 특수 목적 언어가 프로그래머에게 해를 끼친 경우는 문제의 범위를 넘어서는 경우인데 COBOL의 사례가 특히 교훈적이다.
COBOL은 비전문가를 많이 배려한 언어인데, 프로그래머가 아닌 사람도 읽을 수 있도록 고려해 설계를 했고 그 노력은 어느 정도 결실을 맺었다. 그런데 세월이 흐르고 빠른 응답시간이 요구되는 온라인 시스템을 개발해야 하는 요구사항에 대해 COBOL로 개발하기가 어려운데, COBOL이 강요하는 정렬 심리 때문에 임의접근 파일을 사용해 효율성을 높일 수 있는 걸 개발하기가 쉽지 않다.
어떤 프로그래밍 언어가 그것이 목적한 특수한 일을 잘 처리하면 할수록 그 사용자의 사고는 더 좁아지는 결과가 된다. 이 모순에서 벗어날 방법은 없어 보인다. 하지만 진정한 전문 프로그래머는 하나의 언어에 잘 적응한다고 해서 다른 언어에 적응을 못하게 되는 함정에 빠져 있을 여유가 없다.
특수 목적 언어는 해당 분야에 적합한 데이터 구조를 제공하고, 더 간결한 프로그램이 가능하며 사용자의 기존 지식에 잘 부합해야 성공할 가능성이 높다. 실제 적합한 데이터 구조를 제공한 언어는 성공했고, 그렇지 못한 언어는 실패했다.
특수한 데이터 구조를 제공하면 그 구조와 관련된 연산 기능도 함께 제공하게 된다. 연산에 쓰이는 함수와 구조의 이름은 그 분야에서 쓰이는 용어를 참고해서 사용자들이 친숙하게 느끼도록 짓는다.
일반적인 사람들을 대상으로 설정한 특수 목적 언어는 사용자의 기존 지식과 유사한 모습을 띠도록 설계된다. 불행하게도 지금까지 고안된(도저히 개발되었다고 표현하기 어려운) 특수 목적 언어를 보면 기존 지식과 일치하는 부분들만 제공하는 수준에 그친다. 초기 학습 시간은 크게 아낄 수 있지만, 결국 사용자가 원하는 진짜 문제는 해결할 수 없고 비슷한 장난감 문제만 풀 수 있다는 걸 알게 된다. 그러면 사용자는 금방 그 언어에 대한 비판자로 돌변하는데, 충분히 그럴만한 사안이라서 그렇다.
특수 목적 언어가 세상에 태어나는 방식은 대부분 프로그래밍 언어 설계 산업의 망신거리다. 나쁜 프로그래밍 언어로부터 스스로 보호할 능력이 없는 사람들에 대한 사회적 책임을 우리가 져야 한다.
따라서 건전한 행동주의적 원칙에 입각해서 설계와 실험을 수행할 수 있는 환경에서 언어를 개발해야 한다. 프로그래밍에만 전문가가 되지 말고 설계에도 전문가가 되어야 한다.
요약
진 사멧(Jean Sammet)은 < Programming Language: History and Fundamentals(프로그래밍 언어: 역사와 원칙) > 의 책 표지에 바벨탑을 연상시키는 그림을 실었고 프로그래밍 언어 117개가 탑을 장식하고 있다.
사멧이 열거한 언어들은 대략 1952년에서 1967까지 15년 동안에 탄생한 것인데 새로운 언어가 평균 1년에 8개 정도 나왔다고 볼 수 있다. 여기에서도 첫 10년간 연평균 2~3개 였고 나머지 5년 동안 연평균 20개이고 이건 매년 증가 추세를 보인다.
이제는 눈을 높이 들어 장차 언어의 설계자가 될 사람에게 더 많은 걸 요구해야 한다. 그 언어가 심리적으로도 유용함을 증명해야 한다. 그리고 언어 설계자만 비난할 일도 아닌 것이 프로그래밍 언어 이론가들도 심리적 측면을 너무 오랫동안 무시해 왔다. 프로그래밍은 수학의 한 갈래가 아니고 사람과 기계가 의사소통하는 형식이다. 하지만 이 의사소통 형식은 사람은 적극적인데 비해 기계는 소극적일 때가 많다. 이런 소통의 일방성이 프로그래밍 언어와 관련된 문제들의 근본 원인일지도 모른다. 이론가들은 프로그래밍 언어의 대화적 성격으로 눈을 돌려야 한다. 그래야 자신들이 연구하는 것은 기호 조작이 아니라 인간 행위임을 깨닫게 될 것이다.
질문
관리자에게
회사에서 어떤 프로그래밍 언어를 사용하고 있나? 당신은 프로그램을 얼마나 자주 읽는가? 프로그래밍 언어를 관리 업무를 위한 보조 수단으로 보는가, 아니면 프로그래머들이 자기들끼리 속닥거리기 위한 비밀 수단으로 보는가?
회사에서 주로 사용하는 프로그래밍 언어는 C#이다. 프로그램을 매일 수십번을 읽고 있다.
이건 보조 수단이 아니라 같은 프로그래머이기도 하므로 보조수단이나 비밀 수단 수준이 아니라
같이 업무를 하기 위한 약속된 언어이다.
새로운 프로그래밍 언어를 회사에 도입하기로 결정할 때 어떤 심리적 요소들을 고려하는가? 어떤 종류의 실험을 해보는가?
기존 언어와의 적응성을 고려할 것인데
더 우선되어야 하는 건 회사가 달성하려는 비즈니스 목표와 서비스에 부합하는 언어인지 검증해볼 것이다.
그래서 기존에 회사에서 운영하고 있던 서비스와 프로그램 대비
어떤 면에서 더 좋은지에 대한 보고서를 작성하고 판단한 후에 채택할 것 같다.
프로그래머에게
자신이 가장 잘 아는 프로그래밍 언어에 대해 다음의 성격들이 드러나는 사례를 제시하고 토의해 보라.
일관성
비일관성
금기 사항
C# 언어의 경우 Roslyn compiler platform을 사용하고 있기 때문에
일관성이나 비일관성의 규칙에 대해 실시간 체크가 가능하고
컴파일 언어이고 type strong 언어이다 보니 비일관성의 경우는 거의 찾아보기 어렵다.
(있어도 바로 roslyn compiler에 의해 에러 메시지가 뜬다)
거의 일관적인 프로그래밍이 가능하며
객체지향적 프로그래밍과 함수형 호출 방식을 통해 그 일관성을 지켜주는 쪽에 가깝다.
C#은 오래되기도 했지만 계속 발전하는 언어여서
금기사항의 경우는 버전이 올라가면서 해결이 되는 경우가 많다.
아직 C#이 가지고 있는 금기 사항은 mixin traits 정도의 표현일 것 같다.
당신이 알고 있는 언어 중에서 간결성이 가장 뛰어난 것은 무엇인가? 그 언어가 그렇게 간결한 원인은 무엇인가? 혹시 그 언어를 사용해서 해결할 수 있는 문제의 범위가 제한되어 있기 때문에 그런 것은 아닌가?
잠시의 망설임 없이 Python 이라고 볼 수 있다.
이건 언어 설계자가 철학을 가지고 설계한 부분이 크다고 볼 수 있다.
Python이 해결할 수 있는 문제의 범위는 거의 제한되어 있지 않다.
제한되는 부분은 인터프리터 언어이다 보니 성능적인 측면에서의 제약이 있을 뿐
문제를 해결할 수 없는 범위의 제한은 없다고 보는 것이 맞다.
당신이 가장 잘 아는 언어에서 비근접성을 낳을 수 있는 방법을 모두 나열해 보라. 그렇게 발생한 비근접성이 디버깅할 때 어떤 결과를 초래하는가? 비근접성으로 인해 발생한 버그의 예를 들고, 어떻게 결국 그 버그를 찾아낼 수 있었는지 말해 보라.
자바스크립트에서 모듈화가 되지 않은 그냥 스크립트 코드를 작성한다면 엄청난 비근접성을 경험하게 될 수도 있다.
특히 글로벌 변수나 객체 사용이 가능한 var 타입의 코드는 스크립트 코드를 파일 단위로 나눈다고 해도
비근접성을 낳게 될 것이고 디버깅하기가 어려울 것으로 예상된다.
다른 사람이 작성한 여러 프로그램을 길이가 비슷한 것끼리 분류하고, 또 각 분류 내에서도 이해하기 쉬운 정도에 따라 순서를 매겨 보라. 각 프로그램에서 사용된 분기의 횟수를 세어 보고, 프로그램의 명확성과 분기의 횟수 사이에 어떤 연관이 있는지 확인하라. 또, 분기 하나에 포함된 코드의 평균 길이를 계산해서 이 역시 프로그램의 명확성과 어떤 연관이 있는지 보라.
이해하기 쉬운 코드는 순차적으로 실행되는 코드로 읽는데에 문제가 없는 수준으로 확인할 수 있다.
분기의 횟수가 많아질수록 기억해야 하는 횟수가 증가하게 될 것이고
이는 코드 명확성에 해를 끼치게 될 가능성이 높다.
하나의 분기에 포함된 코드 길이가 50 라인이 되는 경우도 있는데,
이 정도 길이는 분기 처리시 발생하는 명확성에 크게 좌우되지 않는다고 볼 수도 있다.
가장 최근에 배운 언어로 프로그래밍할 때 이전 프로그래밍 언어에서 쓰던 방식의 영향을 받은 예를 몇 가지 들어 보라. 또, 당신이 공부한 프로그래밍 언어들이 프로그래밍이 아닌 다른 분야의 사고 과정에 영향을 끼친 예도 몇 가지 들어 보라.
Flutter의 dart 언어를 쓸 일이 있는데, C#에서 쓰는 delegate, event, async/await을 쓰는 방식이 매우 유사했다.
프로그래밍 언어가 다른 분야의 사고 과정에 영향을 끼친 걸 생각해 보진 않았는데
아마 실생활에서도 조건 판단이나 반복의 경우도 유사할 것이라고 생각한다.
특수 목적 언어를 안다면, 그 언어가 다음 항목의 이점을 어떻게 활용하는지 설명해 보라.
대화 주제의 제한
해당 분야에 적합한 데이터 구조
해당 분야에 적합한 처리 함수
해당 분야에 대한 기존 지식에 부합되는 용어
검색해 보니 마크업(HTML, CSS), 질의(SQL), 모델링(UML) 언어들이 여기에 속한다고 한다.
하나씩 설명해 보면 좋을 것 같다.
- 대화 주제의 제한
HTML, CSS는 웹 브라우저상에 무엇을 어떻게 표현할지를 정하는 방법이므로
웹 페이지 제작에 한정되서 제한이 있을 수 있다.
SQL 역시 관계형 데이터베이스에서 데이터를 다루는 언어이므로
데이터를 어떻게 다룰지에 대한 주제로 한정지어서 쓸 수 있다.
UML도 특정 도메인에 한정 지어서 모델링을 하게 될 때 표현할 수 있는 도구로 적합할 수 있다.
- 해당 분야에 적합한 데이터 구조
HTML, CSS는 레이아웃별 그리고 태그별 데이터가 정해져 있는데 데이터 구조가 딱히 정의되어 있지는 않다.
SQL의 경우는 관계형 데이터베이스 테이블 데이터 구조라면 적합하다.
UML의 경우 한정된 도메인 모델일 때 그 도메인에 맞는 유비쿼터스 언어를 사용한다면 데이터 구조를 설계할 수 있다.
- 해당 분야에 적합한 처리 함수
HTML, CSS는 마크업이므로 처리 함수를 사용하려면 반드시 javascript를 사용할 수 밖에 없고
javascript를 사용한다면 일반적인 함수 및 사용자 정의 함수 등 다양하게 호출하거나 만들어서 사용할 수 있다.
SQL의 경우도 내장 함수들이 제공되어 있고 프로시저라는 정의 함수로 만들 수도 있다.
UML은 모델링 언어이므로 처리 함수라는게 있지는 않다.
- 해당 분야에 대한 기존 지식에 부합되는 용어
HTML, CSS는 프로그래밍 쪽 보다는 표현 언어에 가까우므로 기존 지식에 매우 부합하여 언어를 작성하고 결과를 볼 수 있다.
SQL의 경우 키워드 구조는 자연어와 유사하므로 기존 지식을 활용하고자 한다면 자연스러운 문맥으로 사용해볼 수 있다.
UML의 경우 객체지향 지식에 대해 어느 정도 알고 있다면 부합하는 용어가 상당히 많다.
참고문헌
Raymond J. Rubey < Guide to PL/1 Vol. 1: Comparative Evaluation > Detroit, American Data Processing, 1969년
F. P Brooks < Guide to PL/1 Vo. 2: Experiences with PL/1 > Detroit, American Data Processing, 1969년
새로운 프로그래밍 언어인 PL/1의 가치를 평가하는 두 가지 방식을 보여준다.
1권에서 프로그래밍 언어를 행동주의적으로 연구하는 방식을 취했는데 개인간 편차를 제거하고자 한 프로그래머가 서로 다룬 두 언어로 동일한 문제를 풀도록 한 것이다. COBOL과 PL/1, FORTRAN과 PL/1, JOVIAL과 PL/1 등의 여러 조합을 시도했다.
저자가 행동주의 과학자가 아니라 프로그래머임에도 연구 방법은 꽤 정교하다.
Jean E. Sammet < Programming Languages: History and Fundamentals > Englewood Cliffs, N.J, Prentice-Hall, 1969년
특수 목적 언어가 어떻게 설계되는지 추측할 수 있다.
N. Wirth < PL 360, A Programming Language for the 360 Computers > Communications of the ACM, 15, No. 1 (1968년 1월), 37-74 쪽.
생성되는 기계어 코드에 대한 제어권은 완벽하게 유지하면서 블록 구조의 장점을 취한 어셈블리어를 생각해 냈다.
이는 시스템 프로그래밍의 미래를 논한 최근 10년 사이에 나온 논문 가운데 가장 중요한 축에 속한다.
G. M. Weinberg < PL/1 Programming: A Manual of Style > New York McGraw-Hill, 1970년
Pl/1을 배경으로 프로그래밍 언어의 원칙들을 상세하게 논했다.
M, Klerer, J. May < A User-Oriented Programming Language > Computer Journal, 8, No. 2(1965년 7월), 103-109쪽
언어를 설계하는 관점에서 볼 때, 클래러와 메이가 제시한 시스템의 가장 흥미로운 특징은 모호성을 수용했다는 점이다.
그 다음 흥미로운 특징으로 겸손함의 극치인지 자부심의 극치인지 알 수 없지만 자신들이 만든 언어에 이름을 붙이지 않은 점이다.
C. J. Shaw < Decision Tables-An Annotated Bibliography > Santa Monica, System Development Corp. (1965년 4월)
Paul Dixon < Decision Tables and Their Application > Computers and Automation 13, (1964년 4월), 14-19쪽
결정 표 운동Dicision Table Movement은 60년대 초반 반짝 융성한 후 거의 잊히는 듯 하다가 근래에 다시 살아나고 있다.
불행히도 형식적인 문제들 또 잘못 쓰인 교과서들에 문제가 집중되어 있다.
아직까지 어떤 심리학적 의미에서든 결정 표의 가치를 증명할 경험적인 근거가 나와 있지 않다. 이는 결정표가 절차 기반 언어보다 더 자연스러운 프로그래밍 방식이라고 주장하는 측에서는 유감스러운 일이다.
G. M. Weinberg < Experiments in Problem Solving (Doctoral Thesis) > Ann Arbor, University Microfilms, 1965년
피실험자에게 여러 사고방식 중 하나를 선택할 자유가 있을 때 보이는 행테에 대한 연구로,
프로그래밍 언어가 어떤 종류의 구조를 갖춰야 가장 바람직할지 암시해 준다.
Benjamin Lee Whorf < Language, Thought, and Reality > Cambridge, Mass., M.I.T. Press, 1965년
인류학자 또는 인류언어학자인 워프(Whorf)는 표준 미국-유럽 언어가 아닌 언어를 연구하며, 금기의 영향력 등 언어가 생각에 미치는 영향을 밝혀냈다.
이 책에 실린 글이 읽기 어렵게 느껴지면 설명하고 있는 생각의 방식이 낯설어서이다.
비유럽 언어에 대한 연구가 유용할지도 모른다. 여태까지 유럽 언어만 컴퓨터 프로그래밍에 유용한 모델이 들어 있다고 믿고 있었을지도 모르기 때문이다. 이 책을 읽은 후에는 생각이 바뀔 것이다.
G. K. Zipf < Human Behavior and the Principle of Least Effort > Cambridge, Mass., Addison-Wesley, 1949년
지프는 워프와 마찬가지로 동시대 지적 유행과 거리가 먼 인물이었고, 업적이 인정받기 까지 오랜 시간이 걸렸다.
이 책은 언어 변화의 원칙에 대한 연구 결과를 담고 있다.
프로그래밍 언어의 방언 또는 중복 정보가 없는 프로그래밍에 대해 관심이 있는 사람이라면 읽어봐야 한다.
C. E. Shannon < Prediction and Entropy in Printed English > Bell System Technical Journal, Vol. 30 (1951년), 50-64쪽
N. G. Burton, J. C. R. Licklider < Long-Range Constraints in the Statistical Structure of Printed English > American Journal of Psychology, Vol. 68 (1955년), 650-653쪽.
이 두 글은 영어로 출판된 책에 얼마나 많은 중복 정보가 들어 있는지를 측정하려는 시도로 볼 수 있다.
프로그램 또는 프로그래밍 언어에 대한 측정 방법도 제안하고 있다.
George A. Miller < The Magical Number Seven, Plus-or-minus Two: Some Limits on Our Capacity for Processing Information > Psychological Review, 63, No. 2 (1956년 3월), 81-97쪽
밀러는 이 논문에서 인간의 정신이 소유한 정보 처리 능력이 어떻게 제한되는지 그리고
그런 제한을 극복하고자 인간의 정신은 어떤 전략을 사용하는가를 설명한다.
밀러가 열거한 전략은 프로그래머들이 사용하는 전략과 크게 다르지 않아 보인다.
B. Smith < Memory > London, Allen and Unwin, Ltd., 1966년
F. A. Yates < The Art of Memory > Chicago, The University of Chicago Press, 1966년
M. Minsky < Semantic Information Processing > Cambridge, Mass., M.I.T. Press, 1968년.
세 권의 공통점은 프로그래밍 언어를 설계할 때 고려해야 하는 기억과 여러 정신 과정을 논의한 점이다.
크게 다른 점은 프로그래밍에 굉장히 중요한 정신 과정에 대해 기억과 같은 높은 수준의 과정에 대해 너무나도 이견이 많다는 점이다.
12장에 보태는 글: 프로그래밍 언어 설계에 필요한 원칙
인터뷰 질문에서 "컴퓨터 과학에 자신이 무엇을 가장 크게 공헌했다고 생각하십니까?" 라는 질문에
"프로그래밍 언어를 하나도 만들지 않은 것이 컴퓨터 분야에 대한 나의 가장 큰 공헌입니다" 라고 했다.
사실 가장 먼저 떠오른 대답은 "저는 컴퓨터 과학에 아무것도 공헌하지 않았습니다" 이다.
돌이켜 생각해 보면 매우 비겁한 책임 회피성 발언이었다.
이 책을 다시 검토해 보면서 당시 내가 욕을 먹지 않기 위해 몸을 사렸다는 걸 깨달았다.
새로운 프로그래밍 언어를 만들지 않은 건 사실이지만, 설계 원칙들을 만들어 냈기 때문에 프로그래밍 언어 설계의 설계자였다.
설계 원칙을 만들었을 뿐이었으므로 책임은 지지 않은 채로 멀리서 훈수만 둔 셈이다.
고백하자면, 어셈블리, FORTRAN, APL, COBOL, PL/1, Simula, IBM System/360 가계어와 작업 제어 언어, Pascal, 프로그래밍 언어의 형식적 기술을 위한 비엔나 정의 언어(Vienna Definition Language, VDL)에도 훈수를 둔 사람 가운데 한 명이었다.
FORTRAN의 오브젝트 코드를 비판하고 결코 오래가지 못할 언어라고 잘못 예견했다.
APL, MetaCOBOL, Pascal 등에도 영향을 끼쳤고 Algol, C, Smalltalk의 초기 버전에도 영향을 끼쳤다.
게다가 태어나지 못하도록 일조를 했을지도 모르는 수십 개 언어들도 있다.
모든 프로그래머는 메타언어 전문가다.
이것이 프로그래밍 언어 설계에 필요한 원칙이란 제목이 붙은 글에 내가 덧붙일 수 있는 유일한 내용이다.
The text was updated successfully, but these errors were encountered:
논의 주제)
책에서 언급한 설계 원칙에 대해서는 현대 프로그래밍 언어에서는 어느 정도 해소가 되었거나
더 좋은 컴파일러와 그 도구들(lint나 실시간 컴파일러)을 통해 실현된 것도 있는 것 같습니다.
즉, 일관성은 문법으로
간결성은 컴파일러 기능&성능으로
근접성과 순차성은 GOTO문 같은 문법은 사라진지 오래입니다.
여기서
자신이 주력으로 사용하는 프로그래밍 언어에 대해서
다른 언어에서 설계된 특징 중 가져와서 쓰면 좋을 것 같은 것이 있는지 얘기해 보면 좋겠습니다.
저는 C# 언어를 주력으로 쓰는데 java와 마찬가지로 다중 상속을 허용하지 않습니다.
하지만 mixin 개념을 사용하면 다중 상속을 구현하는 것 같으면서도 다중 상속이 아닌 구현을 재사용할 수 있는 장점이 있습니다.
이미 python, swift, dart, kotlin, golang 등 다양한 현대 언어들은 이미 mixin을 지원을 하고 있기 때문에
C#에도 mixin이 생기면 어떨까 하는 생각이 듭니다.
물론 C# 8.0에서 default interface implementation이 지원되긴 하지만 상속 계층 구조를 따라간다는 점에서는 반쪽짜리 문법을 지원하고 있습니다.
12장 프로그래밍 언어 설계에 필요한 원칙
몇 가지 원칙을 이론적으로 설명해야 하는데 이렇게 할 수 밖에 없는 이유는 아직 경험 자료가 많이 부족하기 때문이다.
문제는 프로그래밍 언어를 설계할 때 심리학적 요인을 고려해야 함을 인정하지 않거나 또는 그렇게 인정하더라도 언어 설계자와 주변 몇 명만을 연구하는 것으로 충분하다고 생각한다는 점이다.
일관성
일반 심리학 연구 결과에 따르면 어떤 목록을 얼마나 잘 기억할 수 있는가는 그 목록에 담겨 있는 정보의 내용과 밀접한 관련이 있다. 정보의 내용은 목록에 포함되어 있는 것 뿐만 아니라 목록에 없어도 기억해야 하는 사람의 머릿속에 들어 잇는 것도 정보의 내용에 포함되기 때문이다.
이진수 체계를 아는 사람이면 이진수 순서대로 나열된 8개의 숫자 보다 몇 개가 빠져 있는 6개가 더 외우기 어려울 수 있는데, 빠진 것이 무엇인지 알고 기억해야 하기 때문이다.
만약 이진수 체계를 모른다면 갯수가 적은 쪽을 더 잘 외울 수 있다.
프로그래밍에서도 같은 현상이 발생하는데 FORTRAN의 배열 첨자 규칙이 예이다. 산술 표현식 체계를 모르는 프로그래머에게는 FORTRAN이 더 외우기 쉬운데, 첨자로 사용할 수 있는 표현식 개수가 PL/1이나 APL에 비해 적기 때문이다. 문제는 산술 표현식을 모르는 프로그래머가 없기 때문에 첨자로 사용될 수 있다는 규칙만 알면 되는 걸 FORTRAN의 경우는 7가지 형식의 표현만 첨자로 사용할 수 있다는 걸 외워야 한다.
일관성의 원칙이 무엇인가를 명료한 문장 하나로 단정하지 않은 것은 수학적이라기 보다 심리학적이기 때문이다. 그래도 프로그래밍 언어의 일관성을 굳이 한 문장으로 정의하자면 이렇다.
프로그래밍 언어가 이 원칙에서 멀어질수록 배우기가 어렵고 프로그래머가 오류를 범할 가능성도 커진다.
일관성의 중요성을 확인하기 위해 같은 프로그램을 두 언어로 작성하는 비교 실험을 했다.
OS/360용 Pl/1과 DOS/360용 PL/1인데, DOS용 PL/1은 OS용 PL/1의 부분 집합이다.
DOS용 PL/1을 사용한 프로그래머들은 DOS용에도 있는 기능인데도 사용하지 않은 경우가 많았는데, 그 기능을 쓸 수 있는지 확신이 서지 않았다는 대답이었다.
표 12-1 한 프로그래밍 언어와 그 부분 집합인 언어의 비교
사람들은 금기가 많을수록 은연 중에 또 다른 금기가 있을 것이라 예상한다. 언어에 존재하는 제약 사항은 그것이 적용되는 영역 밖에서도 영향력을 발휘한다. 그래서 일관성의 원칙을 이렇게도 정의할 수 있다.
일관성의 원칙은 문법적으로 동일한 구문은 문맥이 달라도 동일한 의미를 지녀야 한다는 뜻이기도 하다. 일관적이지 못한 문법은 프로그래머가 여러 가지 의미론적인 시도를 하는 데 장애물이 된다. 프로그래머가 자신이 사용하는 프로그래밍 언어에 혼란을 느끼면 일을 제대로 할 수 없을 것이다.
불명확함에 두 가지 종류가 있는데 물리적인 불명확성이고, 다른 하나는 심리적인 불명확성이다. 물론 컴파일러에는 불명확성이 없다. 그러나 컴파일러 구현마다 해석이 다를 수 있기 때문에 모든 구현이 필요 이상으로 차이를 보이지 않도록 언어 자체에서 이런 종류의 불명확성을 제거하는 일은 중요하다. 그러나 물리적 불명확성을 제거한다고 해서 심리적 불명확성까지 사라지는 것은 아니다.
언젠가는 프로그래밍 언어 설계자들이 불명확성에 이렇게 두 가지 종류가 있음을 인지하고 대처할 날이 올 것이다. PL/1의 WHILE처럼 불명확한 사례가 드물게 발생하는 경우에는 이 방법이 유용할 것이다. 불명확성을 없애고 싶다면 프로그래머가 WHILE이라는 이름의 배열을 사용할 때만 적용되는 감춰진 규칙을 언어에 심어 놓는 것이다. 그러면 이름이 WHILE인 배열이 나타날 때 컴파일러가 프로그래머에게 변경하라고 알려주면 된다. 지금도 컴파일러가 그런 상황에 대해 알려주기는 하지만 경고 메시지 보다는 키워드를 변수 이름으로 사용하려는 멍청한 프로그래머만 오류 메시지로 보여주는게 좋을 것이다.
일관성의 마지막 측면으로 언어 설계자가 모든 비난을 받는 건 온당치 않다. 프로그래머가 지은 죄가 훨신 큰 경우도 있다. 변수 이름으로 키워드를 사용하기는 그 프로그램을 읽는 사람을 혼란스럽게 만든다. 그 밖의 예로 아무 이유 없이 변수의 크기를 매번 다르게 선언하기, 약어와 완전한 단어를 번갈아가며 쓰기, 코드 들여쓰기와 빈칸 넣기를 마음대로 하기, 주석을 과하게 추가하거나 어려워 보이는 코드에는 주석을 달지 않는 경우가 있을 것이다.
프로그래머가 일관성을 해치는 대표적인 경우는 변수 이름으로 쓸 의미 있는 단어를 잘못 고르는 것이다. OLDX에 X의 예전 값이 할당되어 있지 않고, SUMAB가 A와 B의 합이 아니며, BIGGEST에 실제로 가장 큰 값이 들어있지 않은 경우가 그렇다. 하지만 이 교훈을 아무리 얘기해도 이런 잘못된 생각은 사라지지 않을 것이다. 언어 자체가 일관성이 결여된 것과 마찬가지로, 이런 습관은 우리가 진실이 아닌 부분을 믿도록 만들기 때문에 우리 자신에게 해가 된다.
디버깅 관점에서는 일관성이 아예 없는 경우보다 일관적이고 매우 드물게 예외가 있는 상황이 더 안좋은 상황이다. 예외가 적다면 방심하기 쉽기 때문이다.
간결성
누구에게나 긴 프로그램보다는 짧은 프로그램이 더 이해하기 쉽다고 할 수 있다. 그러나 프로그램이 얼마나 간결한지를 단순히 그 소스에 얼마나 많은 글자가 들어 있는가로 판단할 수는 없다. 표현식 A + B 보다 BIG + SMALL 이해하기가 더 쉬운데 사고 과정에서 글자 하나를 쓰기 보다는 단어를 사용하는 습관이 있기 때문에 그렇다. 사고 과정에서 BIG 같은 단어는 A 같은 단어와 동일하게 취급된다.
심리학에서 여러 작은 단위를 조합해서 커다란 단위 하나로 묶고 그렇게 만들어진 큰 단위도 각각을 구성한 하위 단위와 마찬가지로 쉽게 다루는 능력을 의미덩이 만들기(chunking)라 부른다. 이건 의식적인 노력 없이 수행하는 자연스러운 인지 과정이다. 그러나 의미덩이를 만들려면 먼저 그 의미덩이를 경험을 통해 학습해야 한다. 2진수를 몰랐을 때는 서로 별개인 두 글자로 기억해야 할텐데 이진수를 8진수나 16진수의 의미덩이로 변환하는 방법을 알게 되면 예전보다 이진수가 더 짧아 보이게 된다.
자연어 연구를 통해 나온 지프(Zipf)의 법칙이 있는데, 자주 사용하는 단어일수록 길이가 짧은 경향이 있다. 'is', 'the', 'a' 등이 해당되고 'don't'나 'there's' 같은 단어도 지프의 법칙에 의해 압축된 예로 볼 수 있다.
프로그래밍에서는 압축된 표현을 많이 볼 수 있다. PROCEDURE 대신에 PROC로 사용하기 시작하는 경우가 있다. 순차적으로 나열하는 항목을 DO 구문을 쓰거나 SUM 함수를 사용해서 코드를 작성하는 경우처럼 한 기능을 더 강력한 기능으로 대체하는 과정에서도 일종의 압축이 발생한다.
또 다른 압축 형태로 데이터의 구조화가 있다. 반복이나 함수 보다 훨씬 더 강력하다고 볼 수 있다.
적절한 데이터의 구조화를 통해 표현을 압축하는 방법으로 연산의 차원을 높이는 것도 있다. 문자열 데이터 구조가 그 예인데 문자열 데이터도 일련의 비트이지만 어떤 문자열의 값을 바꿀 때에는 각 비트를 하나씩 수정하는 것이 아니라 다른 문자열 값을 대입하는 연산 하나로 끝낸다.
표현의 압축은 생략을 통해서도 이뤄진다. 특정한 경우에 대한 표현을 완전히 생략하는 것인데 PL/1 에서 SKIP(1) 대신 SKIP을 사용해도 되는 건 SKIP(1)이 가장 자주 사용되기 때문이다. 변수 선언시에도 속성을 생략할 수도 있다.
두 코드가 선언한 변수는 동일하다. 그리고 선언문을 생략해도 변수 X가 암시적으로 또는 문맥적으로 선언되는 경우가 많다. 글을 쓸 때는 정보를 중복함으로써 얻어지는 부담이 더 큰 편이기 때문에, 프로그래밍 언어에서 잘 만들어진 디폴트 체계는 충분한 가치가 있다.
중복 정보를 적절한 방식으로 제거한다면 지루함을 덜고 실수도 줄일 수 있다. 그러나 존재할 가능성이 있는 중복 정보가 모조리 제거된 언어에서는 프로그램을 문법 검사하기가 불가능한데, 존재할 수 있는 문자열은 모두 그 언어에서 문법적으로 올바를 수도 있기 때문이다. 기계어 프로그래밍이 어려울 때가 있는데 그 원인이 중복 정보가 너무 과도하게 제거되어 있기 때문이라고 볼 수 있는가? 에 대한 대답은 심리적인 측면에서 쓸모 있는 중복 정보와 쓸모 없는 중복 정보를 명확히 구별해야 한다.
FORTRAN에서 A(1+I)를 금지하는 규칙은 프로그래머의 심리적 편안함이 아니라 최적화된 실행 코드로 컴파일하기가 쉽도록 만들기 위한 규칙이다. 이 표현식이 잘못이라는 것은 사실이지만 이 잘못은 우리에게 문제가 있기 때문이 아니다. 오직 FORTRAN의 제한 때문에 생긴 것이다. 어떤 의미에서, 잘못하고 있는 쪽은 프로그래머가 아니라 언어다.
근접성과 순차성
잘 설계된 프로그래밍 언어는 좋은 기억력과 마찬가지 방식으로 관련 정보를 쉽게 찾을 수 있는 곳에 담아 둬서 프로그래머를 도와준다.
관심을 가져야 할 기억력의 종류는 공감각적(synesthetic) 기억력과 순차적(sequential) 기억력이다.
공감각적 기억력은 특정 세부 사항에 의지하지 않고 얼굴이나 이웃, 책 한 페이지의 편집 배치 등을 알아볼 수 잇게 해주는 능력이다. 사물을 전체적인 하나의 심상으로 기억하는 것이다.
순차적 기억력은 청각을 통해 들은 정보와 더 밀접하게 관련되어 있다. 순차적 기억은 차례로 이어진 사슬처럼 구성되어 있어서 차례로 떠오르면서 고리마다 바로 다음에 오는 고리를 상기시키는 구조이다.
프로그램에서 근접성의 개념은 공감각 기억에 순차성의 개념은 순차적 기억에 대응한다. 근접성은 프로그램에서 서로 관련 있는 부분이 모두 한 장소에 나타나는 성질을 의미한다. 프로그래밍 언어에서 근접성을 높이는 방법 가운데 하나는 압축이다.
리터럴은 근접성을 높이는 데 도움이 되는데, 한 리터럴에 관련된 모든 정보가 그 리터럴의 내용에 모두 들어 있기 때문이다. 변수 이름만 봐도 알 필요가 있는 게 연상되도록 변수 이름을 잘 지어도 이와 같은 효과가 있다.
모든 선언을 지정된 장소에서 해야 하는 언어를 사용할 때도 어느 정도 근접성을 얻을 수 있다. 맨 앞 페이지를 떼서 옆에 두고 참조하면 되기 때문이다. 그래서 어디서나 선언을 할 수 있는 PL/1과 같은 언어에 대해 불평하는 사람도 있다.
어떤 프로그래밍 언어를 쓰더라도 디버깅할 때는 반드시 비근접성으로 인해 어떤 문제가 나타날 수 있는지를 염두에 둬야 한다.
언어가 지는 한 특징이 근접성을 저해시킨다고 해도 보통 그 특징이 언어가 잘못 설계되어서 생긴 것은 아니다. 설계가 잘못된 것이라면 그 특징을 제거하면 될 것이고, 그게 제거됐는지 아무도 관심을 가지지 않을 것이다.
프로그래밍과 비슷한 상황에서 문제를 해결하는 과정을 실험해 보면 일련의 선택들을 완전히 순차적으로만 배열하는 편이 분기나 반복이 포함된 경우보다 일반적으로 더 다루기 쉽다. 프로그래밍도 마찬가지로 GO TO 구문이나 분기문이 많은 프로그램일수록 이해하거나 디버깅하기에 더 어렵다. 이런 어려움 중 일부는 단순히 비근접성 때문이기도 하다.
고수준의 언어들은 컴퓨터의 비순차성을 보완하는 여러 장치를 제공한다.
전통과 혁신
실수할 가능성은 최소로 줄이면서 쉽게 표현할 수 있으려면, 프로그래밍 언어가 자연스러워지는 것이 가장 필요하다. 그건 일관성을 통해 얻을 수 있지만 이미 그 언어에 익숙한 프로그래머들에게만 효과가 있다.
프로그래밍 언어를 프로그래머가 알고 있을 법한 다른 언어와 비슷하게 만든다면, 새 언어로 진입하는 장벽을 낮출 수 있을 것이다.
자연어에서 프로그래밍 언어가 차용한 개념으로는 의미 있는 빈 칸을 들 수 있다. 'orate'는 'or ate'와 동일하지 않다. 빈 칸이 빠져 있는 경우는 교정이 가능한데 중복 정보나 문법적으로 혹은 의미론적으로 어느 정도 잘못되어 보이므로 교정할 수 있다.
프로그래밍 언어의 규칙이 이런 자연어의 빈 칸 규칙에 부합하지 않으면 배우기 어렵거나 최소한 디버깅하기가 더 어려울 수 있다. FORTRAN에는 다음 문장으로 대표되는 고전적은 버그 패턴이 있다.
쉼표 대신 마침표로 쓰면 이 문장은 다음과 같이 해석된다.
이건 FORTRAN에서 쓰는 빈 칸 규칙에 따라 DO33I 라는 하나의 변수 이름이 된다.
프로그래밍 언어가 자연어와 비슷해질 수 있는 영역으로는 철자법도 있다. 자연어는 철자가 틀려서 말이 안되는 다른 단어로 섞이는 경우도 그 사실을 의식하지 못한다. 반면에 프로그래밍 언어에는 대부분 의도가 무엇인지 뻔한 경우까지도 오류로 감지할 정도로 철자법에 대해서 엄격하게 대처한다.
COBOL의 경우는 군더더기 단어(noise word) 덕분에 프로그래머가 영어와 좀 더 비슷하게 느낄 수 있다.
PL/1에서도 문장 내에 있는 일부 구성 요소의 순서를 자유롭게 할 수 있는 경우가 몇 가지 있다.
두 가지를 모두 허용하므로 사용자마다 자연스럽게 느끼는 문법을 쓸 수 있으므로 그 언어를 배우기가 쉽다. 하지만 사용자는 그 중 하나를 선택했다는 사실을 의식하지 못할 수도 있다. 배울 때 하나만 배웠다면 다른 형식을 모를 수 있고 여러 형식 사이에 의미론적으로 차이가 있을 거라고 생각해서 하나를 알게 된 다음에는 다른 것을 사용하기 꺼려할 수도 있다.
그리고 의미론적으로 차이가 있는 경우도 있다. 사실 PL/1에서 다음 두 문장의 의미는 완전히 동일하지는 않다.
뒤에 숨어 있는 성능의 차이 때문에 프로그래머는 느슨함을 활용하지 않게 될 수도 있다.
새로운 프로그래밍 언어를 널리 쓰이는 기존 언어와 비슷하게 설계한다면 학습 초기 단계의 속도를 높일 수 있는 건 분명하다. 그러나 초기 학습이 빠른 만큼 훗날에 치러야 할 대가도 쌓이게 된다. 두 프로그래밍 언어가 서로 완전히 똑같은 경우는 없기 때문이다.
두 언어에 차이가 있다면 억제(inhibition)라는 심리적 현상이 일어난다. 순향 억제의 경우는 먼저 학습한 내용과 나중에 학습한 내용이 비슷해서 나중의 학습이 방해를 받는 현상을 뜻한다. FORTAN과 PL/1을 쓰는 프로그래머는 두 언어의 출력 설정이나 형식을 배울 때 억제 현상이 드러난다.
비슷하지만 완전히 동일하지는 않은 두 언어를 만들면 우리는 억제라는 비용을 지불해야 한다. 따라서 완전히 동일하게 만들 수 없다면 서로 분명하게 다른 언어로 만드는 게 억제 비용을 낮추는 데 더 나을 수 있다.
프로그래머는 모두 똑같지 않은 성향을 가졌으므로 프로그래머가 이미 아는 개념이나 구조에 새로운 언어를 부합하도록 만드는 데는 분명한 한계가 있다. 언어를 느슨하게 만든다면 개인 성향에 좀 더 맞춰줄 수 있으므로 어떤 의미에서는 느슨한 언어는 프로그래머 개인의 선호에 대한 적응성이 뛰어나다고 볼 수 있다.
느슨함 외에 적응성을 높이는 방법에는 여러 가지가 있다. 함수 또는 하위 루틴을 정의할 수 있는 기능이 대표적인 예이다. 새로운 데이터 타입 정의도 그렇고 기존 연산자를 재정의하거나 새로운 연산자를 정의하는 걸 허용해주는 언어도 있다. 마지막으로 정교한 메타언어를 써서 언어의 전체 모습을 바꿔버릴 수 있는 언어도 있다.
이런 기능들을 이용해 언어에 적응하면 언어 설계자들이 일일이 파악하기 힘든 프로그래머 개개인의 개성과 어느 정도 조화를 이룰 수도 있다. 그러나 자신만의 생각과 표현 방식에 가까워지면 다른 사람의 방식과는 멀어질 수 있다. 다른 사람도 나의 프로그램을 읽고 이해할 필요가 있으므로 그런 기능들을 너무 과도하게 사용하면 안된다. 그러면 내 프로그램을 마치 정신분열증 환자의 비밀 일기처럼 볼 수도 있다.
조직의 업무 성격에 따라서는 언어의 적응력을 어느 정도 활용하는 편이 좋다. 만약 지금 쓰는 언어가 조직의 요구에 너무 벗어나 있으면 변경을 시작하기에 앞서 그 요구에 좀 더 맞는 다른 언어를 찾아보는 편이 나을 수 있다.
특수 목적 언어, 범용 언어, 장난감 언어
만약 특정 응용 분야를 대상으로 특수 목적 언어를 설계한다면, 대화 주제가 한정되므로 심리적 이익을 처음부터 누릴 수 있다.
언어의 기능을 제한하는 건 목적한 분야의 문제들이 일정 정도 커지지 않을 것이라는 가정인 경우도 가끔 있다.
예로 보조 기억 장치가 필요 없을 것이라는 걸 가정한다면 그 언어로는 시뮬레이션 할 수 없는 특정 문제가 있을 수 있다.
특수 목적 언어를 설계할 때는 대화의 주제를 좁히는 작업이 중요하므로 처음 부터 이 작업을 해야 하고 생각도 신중하게 해야 한다. APL의 경우가 다룰 수 있는 주제를 한정하는 작업을 잘 했기 때문에 성공할 수 있었다.
반면 APL이 설정한 범위를 넘어선 문제를 해결하려면 프로그래머들은 APL의 한계를 느낄 수 있었다. 하지만 APL에 열광하는 사람들은 그런 한계를 인식조차 하지 못한다. 그 한계가 명확하고 그로 인해 자신들이 APL에 열광했는데도 그렇다.
특수 목적 언어를 사용하는 사람이 사용하지 않는 사람 보다 이런 한계를 잘 인식하지 못하는 것은 언어가 사용하는 사람의 사고방식을 좌지우지하기 때문이다. 이건 억제 효과라기 보다는 프로그래머가 프로그램과 데이터를 조직화 하는 방식 자체를 언어가 결정한다는 뜻이다.
대부분 프로그래머는 자신의 기술 수준이 올라갔을 때 자기 충족적인 만족감을 느끼지만, 특수 목적의 프로그래밍 언어를 사용할 때는 그와 상관없이 만족감을 느끼게 되기도 한다. 언어에 의해 사고 방식이 굳어져 언어와 자신이 그 언어에 대해 알고 있는 범위 내로 문제를 제한해 파악할 수 있기 때문이다.
그런데 특수 목적 언어가 프로그래머에게 해를 끼친 경우는 문제의 범위를 넘어서는 경우인데 COBOL의 사례가 특히 교훈적이다.
COBOL은 비전문가를 많이 배려한 언어인데, 프로그래머가 아닌 사람도 읽을 수 있도록 고려해 설계를 했고 그 노력은 어느 정도 결실을 맺었다. 그런데 세월이 흐르고 빠른 응답시간이 요구되는 온라인 시스템을 개발해야 하는 요구사항에 대해 COBOL로 개발하기가 어려운데, COBOL이 강요하는 정렬 심리 때문에 임의접근 파일을 사용해 효율성을 높일 수 있는 걸 개발하기가 쉽지 않다.
어떤 프로그래밍 언어가 그것이 목적한 특수한 일을 잘 처리하면 할수록 그 사용자의 사고는 더 좁아지는 결과가 된다. 이 모순에서 벗어날 방법은 없어 보인다. 하지만 진정한 전문 프로그래머는 하나의 언어에 잘 적응한다고 해서 다른 언어에 적응을 못하게 되는 함정에 빠져 있을 여유가 없다.
특수 목적 언어는 해당 분야에 적합한 데이터 구조를 제공하고, 더 간결한 프로그램이 가능하며 사용자의 기존 지식에 잘 부합해야 성공할 가능성이 높다. 실제 적합한 데이터 구조를 제공한 언어는 성공했고, 그렇지 못한 언어는 실패했다.
특수한 데이터 구조를 제공하면 그 구조와 관련된 연산 기능도 함께 제공하게 된다. 연산에 쓰이는 함수와 구조의 이름은 그 분야에서 쓰이는 용어를 참고해서 사용자들이 친숙하게 느끼도록 짓는다.
일반적인 사람들을 대상으로 설정한 특수 목적 언어는 사용자의 기존 지식과 유사한 모습을 띠도록 설계된다. 불행하게도 지금까지 고안된(도저히 개발되었다고 표현하기 어려운) 특수 목적 언어를 보면 기존 지식과 일치하는 부분들만 제공하는 수준에 그친다. 초기 학습 시간은 크게 아낄 수 있지만, 결국 사용자가 원하는 진짜 문제는 해결할 수 없고 비슷한 장난감 문제만 풀 수 있다는 걸 알게 된다. 그러면 사용자는 금방 그 언어에 대한 비판자로 돌변하는데, 충분히 그럴만한 사안이라서 그렇다.
특수 목적 언어가 세상에 태어나는 방식은 대부분 프로그래밍 언어 설계 산업의 망신거리다. 나쁜 프로그래밍 언어로부터 스스로 보호할 능력이 없는 사람들에 대한 사회적 책임을 우리가 져야 한다.
따라서 건전한 행동주의적 원칙에 입각해서 설계와 실험을 수행할 수 있는 환경에서 언어를 개발해야 한다. 프로그래밍에만 전문가가 되지 말고 설계에도 전문가가 되어야 한다.
요약
진 사멧(Jean Sammet)은 < Programming Language: History and Fundamentals(프로그래밍 언어: 역사와 원칙) > 의 책 표지에 바벨탑을 연상시키는 그림을 실었고 프로그래밍 언어 117개가 탑을 장식하고 있다.
사멧이 열거한 언어들은 대략 1952년에서 1967까지 15년 동안에 탄생한 것인데 새로운 언어가 평균 1년에 8개 정도 나왔다고 볼 수 있다. 여기에서도 첫 10년간 연평균 2~3개 였고 나머지 5년 동안 연평균 20개이고 이건 매년 증가 추세를 보인다.
이제는 눈을 높이 들어 장차 언어의 설계자가 될 사람에게 더 많은 걸 요구해야 한다. 그 언어가 심리적으로도 유용함을 증명해야 한다. 그리고 언어 설계자만 비난할 일도 아닌 것이 프로그래밍 언어 이론가들도 심리적 측면을 너무 오랫동안 무시해 왔다. 프로그래밍은 수학의 한 갈래가 아니고 사람과 기계가 의사소통하는 형식이다. 하지만 이 의사소통 형식은 사람은 적극적인데 비해 기계는 소극적일 때가 많다. 이런 소통의 일방성이 프로그래밍 언어와 관련된 문제들의 근본 원인일지도 모른다. 이론가들은 프로그래밍 언어의 대화적 성격으로 눈을 돌려야 한다. 그래야 자신들이 연구하는 것은 기호 조작이 아니라 인간 행위임을 깨닫게 될 것이다.
질문
관리자에게
프로그래머에게
참고문헌
새로운 프로그래밍 언어인 PL/1의 가치를 평가하는 두 가지 방식을 보여준다.
1권에서 프로그래밍 언어를 행동주의적으로 연구하는 방식을 취했는데 개인간 편차를 제거하고자 한 프로그래머가 서로 다룬 두 언어로 동일한 문제를 풀도록 한 것이다. COBOL과 PL/1, FORTRAN과 PL/1, JOVIAL과 PL/1 등의 여러 조합을 시도했다.
저자가 행동주의 과학자가 아니라 프로그래머임에도 연구 방법은 꽤 정교하다.
특수 목적 언어가 어떻게 설계되는지 추측할 수 있다.
생성되는 기계어 코드에 대한 제어권은 완벽하게 유지하면서 블록 구조의 장점을 취한 어셈블리어를 생각해 냈다.
이는 시스템 프로그래밍의 미래를 논한 최근 10년 사이에 나온 논문 가운데 가장 중요한 축에 속한다.
Pl/1을 배경으로 프로그래밍 언어의 원칙들을 상세하게 논했다.
언어를 설계하는 관점에서 볼 때, 클래러와 메이가 제시한 시스템의 가장 흥미로운 특징은 모호성을 수용했다는 점이다.
그 다음 흥미로운 특징으로 겸손함의 극치인지 자부심의 극치인지 알 수 없지만 자신들이 만든 언어에 이름을 붙이지 않은 점이다.
결정 표 운동Dicision Table Movement은 60년대 초반 반짝 융성한 후 거의 잊히는 듯 하다가 근래에 다시 살아나고 있다.
불행히도 형식적인 문제들 또 잘못 쓰인 교과서들에 문제가 집중되어 있다.
아직까지 어떤 심리학적 의미에서든 결정 표의 가치를 증명할 경험적인 근거가 나와 있지 않다. 이는 결정표가 절차 기반 언어보다 더 자연스러운 프로그래밍 방식이라고 주장하는 측에서는 유감스러운 일이다.
피실험자에게 여러 사고방식 중 하나를 선택할 자유가 있을 때 보이는 행테에 대한 연구로,
프로그래밍 언어가 어떤 종류의 구조를 갖춰야 가장 바람직할지 암시해 준다.
인류학자 또는 인류언어학자인 워프(Whorf)는 표준 미국-유럽 언어가 아닌 언어를 연구하며, 금기의 영향력 등 언어가 생각에 미치는 영향을 밝혀냈다.
이 책에 실린 글이 읽기 어렵게 느껴지면 설명하고 있는 생각의 방식이 낯설어서이다.
비유럽 언어에 대한 연구가 유용할지도 모른다. 여태까지 유럽 언어만 컴퓨터 프로그래밍에 유용한 모델이 들어 있다고 믿고 있었을지도 모르기 때문이다. 이 책을 읽은 후에는 생각이 바뀔 것이다.
지프는 워프와 마찬가지로 동시대 지적 유행과 거리가 먼 인물이었고, 업적이 인정받기 까지 오랜 시간이 걸렸다.
이 책은 언어 변화의 원칙에 대한 연구 결과를 담고 있다.
프로그래밍 언어의 방언 또는 중복 정보가 없는 프로그래밍에 대해 관심이 있는 사람이라면 읽어봐야 한다.
이 두 글은 영어로 출판된 책에 얼마나 많은 중복 정보가 들어 있는지를 측정하려는 시도로 볼 수 있다.
프로그램 또는 프로그래밍 언어에 대한 측정 방법도 제안하고 있다.
밀러는 이 논문에서 인간의 정신이 소유한 정보 처리 능력이 어떻게 제한되는지 그리고
그런 제한을 극복하고자 인간의 정신은 어떤 전략을 사용하는가를 설명한다.
밀러가 열거한 전략은 프로그래머들이 사용하는 전략과 크게 다르지 않아 보인다.
세 권의 공통점은 프로그래밍 언어를 설계할 때 고려해야 하는 기억과 여러 정신 과정을 논의한 점이다.
크게 다른 점은 프로그래밍에 굉장히 중요한 정신 과정에 대해 기억과 같은 높은 수준의 과정에 대해 너무나도 이견이 많다는 점이다.
12장에 보태는 글: 프로그래밍 언어 설계에 필요한 원칙
인터뷰 질문에서 "컴퓨터 과학에 자신이 무엇을 가장 크게 공헌했다고 생각하십니까?" 라는 질문에
"프로그래밍 언어를 하나도 만들지 않은 것이 컴퓨터 분야에 대한 나의 가장 큰 공헌입니다" 라고 했다.
사실 가장 먼저 떠오른 대답은 "저는 컴퓨터 과학에 아무것도 공헌하지 않았습니다" 이다.
돌이켜 생각해 보면 매우 비겁한 책임 회피성 발언이었다.
이 책을 다시 검토해 보면서 당시 내가 욕을 먹지 않기 위해 몸을 사렸다는 걸 깨달았다.
새로운 프로그래밍 언어를 만들지 않은 건 사실이지만, 설계 원칙들을 만들어 냈기 때문에 프로그래밍 언어 설계의 설계자였다.
설계 원칙을 만들었을 뿐이었으므로 책임은 지지 않은 채로 멀리서 훈수만 둔 셈이다.
고백하자면, 어셈블리, FORTRAN, APL, COBOL, PL/1, Simula, IBM System/360 가계어와 작업 제어 언어, Pascal, 프로그래밍 언어의 형식적 기술을 위한 비엔나 정의 언어(Vienna Definition Language, VDL)에도 훈수를 둔 사람 가운데 한 명이었다.
FORTRAN의 오브젝트 코드를 비판하고 결코 오래가지 못할 언어라고 잘못 예견했다.
APL, MetaCOBOL, Pascal 등에도 영향을 끼쳤고 Algol, C, Smalltalk의 초기 버전에도 영향을 끼쳤다.
게다가 태어나지 못하도록 일조를 했을지도 모르는 수십 개 언어들도 있다.
모든 프로그래머는 메타언어 전문가다.
이것이 프로그래밍 언어 설계에 필요한 원칙이란 제목이 붙은 글에 내가 덧붙일 수 있는 유일한 내용이다.
The text was updated successfully, but these errors were encountered: