Posted by 미스란디르
Sat, 29 Mar 2008 00:08:00 GMT
C를 배운지 얼마 안된 사람이 다음과 같은 질문을 했다고 쳐보자.
"값을 반환 했는데 먼가 잘 안돼요."
그래서 소스를 살펴본다.
int sum_and_multiple(int a, int b)
{
int sum = a + b;
int mul = a * b;
return sum, mul;
}
약간 특이하다. 저건 컴파일할때 에러가 아닌데, (적어도 GCC에선) 그렇다고 값을 두개를 반환하는가 하면 그것도 아니다.
C의 함수 구현은 저런 반환값을 허용하지 않는다. 저건 잘못됐다고 살짝 야단을 치면서 혹은 친절하게
지난번에 가르쳐준 call-by-reference를 복습시켜준다.
정답은 물론 다들 아시는 것 처럼 이렇다.
void sum_and_multiple(int a, int b, int *sum, int *mul)
{
*sum = a + b;
*mul = a * b;
}
정말 그걸로 된걸까?
요즘엔 이런 생각이 든다. 이러한 설명 과정에 의해서 자연스러운 사고방식이 또 하나 없어져가는게 아닐까, 라고. 함수가 값을 반환한다고 배웠다면
값을 꼭 하나가 아니라 여러개 반환하는 건 안될까? 라고 생각하는 것은 너무나도 당연한 생각이다.
조금 다르게 struct 형을 반환하거나, struct를 동적할당해서 그 포인터를 반환하는 방법이 있다.
하고싶은 것에 비해 들이는 노력이 너무 많다.
이러한 동작들이 어째서 안되는지를 설명하기 위해서는 C의 구현, 컴퓨터의 동작방식
레지스터와 스택등을 설명하지 않으면 안된다. (이제와서 생각해보건데, 두개가 안될
이유가 별로 없어 보인다. x86이라면 ax나 eax대신 스택으로 반환값을
처리한다거나 하면 되지 않겠는가?)
하지만 그건 어찌보면 좀 가혹한 얘기이고 흥미를 잃을 수도 있다.
여기서 루비나 파이썬 혹은 LISP같은 프로그래밍 언어를 잠깐만 소개해주면 어떨까?
'이건 무조건 안된다.' 'call-by-reference로 하렴' 대신,
가능 한 경우도 있다고 알려준다.
def sum_and_multiple(a, b)
sum = a + b
mul = a * b
return sum, mul
혹은
def sum_and_multiple(a, b)
sum = a + b
mul = a * b
sum, mul
end
혹은
(defun sum_and_multiple (a b) (LIST (+ a b) (* a b)))
딴 얘기지만 python이랑 루비는 지향하는 바가 다르면서도 키워드가 비슷해서 그런지 참 비슷하게 생겼다.
루비에서도 return을 쓸 수 있으니 return sum, mul 하면 end빼고 똑같지 않은가!
이제 처음 프로그래밍을 배우기 시작해서 C를 익히는 사람에게 다른걸 보여줘봐야 무슨 소용이 있나 싶기도 하다.
하지만 무조건 프로그래밍 언어에 자신을 끼워 맞추기 보다는 또 다른 세계가 있다는 것을 알려주는 것이 좀 더
올바른 교습방법이 아닐까 하는 생각이 든다. 물론 가르치는 사람이 몰라서 안가르쳐 주는 경우가 더 많겠지만.
Posted in 프로그래밍 | Tags 뜬금없이 | 2 comments | no trackbacks
Posted by 미스란디르
Sun, 10 Feb 2008 18:33:00 GMT
GtkDrawingArea + Cairo를 이용해서 간단한 걸 만들고 있다.
그림판이랑 비슷한 부분이 아주 조금 있는데, 예를들면 어떤 그림 조각을 움직인다던가,
혹은 선택하고 복사해서 옆에 새걸 만든다던가 하는것.
C-c 로 복사하고 C-p 로 붙여넣고, DEL로 지우고 따위의 행동을 하려면 key-press-event를 사용하는게 좋겠다고 생각하고, gsignalconnect 로 연결해봤다.
그런데 시그널이 전혀 안들어온다. 참고로 button-press-event 라거나 motion-notify-event같은건 잘 받아진다.
그래서 구글에게 신탁을 해 보았는데, GtkDrawingArea 문서를 알려준다.
To receive mouse events on a drawing area, you will need to enable them with gtk_widget_add_events(). To receive keyboard events, you will need to set the GTK_CAN_FOCUS flag on the drawing area, and should probably draw some user-visible indication that the drawing area is focused. Use the GTK_HAS_FOCUS() macro in your expose event handler to decide whether to draw the focus indicator. See gtk_paint_focus() for one way to draw focus.
마우스 이벤트를 받으려면 gtk_widget_add_events() 를 해야하고, 키보드 이벤트를 받으려면 GTK_CAN_FOCUS flag를 세팅해야 한단다. GTK_HAS_FOCUS() 가지고 검사해서 뭔가 표시하라는건 덤이다.
그래서 다음과 같이 했다.
cpp:
widget = glade_xml_get_widget (xml, "drawing_area");
GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
g_signal_connect (widget, "button-press-event", on_button_press_event, NULL);
g_signal_connect (widget, "key-press-event", on_key_press_event, NULL);
.
.
.
gboolean on_button_press_event (GtkWidget *w, GtkEventButton *e, gpointer userdata)
{
gtk_widget_grab_focus (w);
return TRUE;
}
gboolean on_button_press_event (GtkWidget *w, GtkEventKey *e, gpointer userdata)
{
g_printf("%d:%d\n", e->state, e->keyval);
return TRUE;
}
focus를 가질 수 있게 하고, 버튼을 누르면 focus를 가져오게 한다. 그리고 key-press-event를 연결하면 끝. 아 사실 gtk_widget_add_events()로 이벤트 마스크도 더해줘야 하는데, 요건 글레이드 에디터에서 해버렸다.
아무튼 저걸로 잘 된다.
Posted in 프로그래밍 | Tags gtk, gtkdrawingarea | no comments | no trackbacks
Posted by 미스란디르
Fri, 20 Jul 2007 12:35:00 GMT
이 글은 내가 쓴글은 아니다. 재미있는 글을 발견했는데 원문이 일어이고 제대로 번역한 글을 찾을 수가 없어서 번역해 보았다.
소개글은 http://www.hatena.co.kr/267에서,
원문은 노보리씨의 블로그 에서 찾아볼 수 있다.
여기서부터 본문이다
-------- 여기부터 ---------
나는 하루에 최소 3000줄, 많으면 10000줄 이상의 코드를 작성한다. 그 결과 매달 10만줄 정도를 쓴다. 사용하는 언어는 작성하는 소프트웨어의 특성상 주로 C언어를 사용한다.
또한 프로그래밍에는 버그가 항상 따라다니지만, 최근 2~3년간 발생한 버그의 수가 매우 적게 유지하는 것이 가능했다.
매우 크고 복잡하게, OS에 가까운 처리를 하는 프로그램을 짤 경우에, 프로그래밍을 할 경우에도, 사전의 설계는 매우매우 중요하다. 설계를 잘 해두지 않으면 나중에 전면적으로 고쳐야만 한다거나, 성능이 떨어지는 원인이 되기 때문에 개발자의 고통의 원인이 된다.
당연한 얘기지만 여태까지 만들었던 크고 복잡한 소프트웨어의 대부분의 설계도 나 스스로 했다. 어떠한 경우에도 설계는 최초의 한번으로 확정하고, 그 이후 프로그래밍 작업에 들어가면 그 설계를 후회하거나 수정하지 않으면 안되는 경우는 최대한 없도록 하였고, 그 결과 그러한 참사는 발생하지 않았다.
이러한 것은, 내가 대학에 입학해서 현재까지 4년간 쭉 해왔던 일이지만, 동시에 소프트웨어 개발뿐만 아니라, 대학 과목의 이수(대학은 학고 없이 정상적으로 졸업했다), 학술활동(4년간 학회에서 4번의 초대강연, 1회 수상, 5번 정도의 타대학의 초대강연을 했다), 벤쳐기업의 경영등 이런저런 일을 높은 밀도로 해왔다. 동시에 여러가지 일을 해도 능력부족으로 인한 지장은 거의 없었다.
자신의 능력은 위에서 쓴 것정도이지만, 능력이란 것은 이정도가 평균적이라고 생각하고 있고, 내 능력이 특별히 대단하다고 생각하지 않는다. 하지만 어째 여러 프로그래머의 얘기를 들어보고, 기사를 읽어보니 저정도의 일을 해낼 수 있는 사람은 극히 소수에 불과하다는 사실을 최근 깨달았다.
여러가지 알아본 결과에 의하면, 보통 개발자의 작업 능력은 한달에 수백줄 정도, 빠른 사람도 한달에 3000줄 정도인 것 같다. "하루에 수백줄" 이 아니라, "한달에 수백줄" 인 것이다. 물론 직업 프로그래머에 해당하는 것으로, 일 이외에도 매일 대학에 가거나 자신의 회사를 가지고 있는 것이 아니라 프로그래밍에 전념해도 이정도다. 생각했던것과 전혀 달랐다.
그래서 최근 4년간 내 자신의 능력의 근원에 대한 탐구를 하는 것과 동시에 여러가지를 조사하는 동안에 보통 사람들의 생각하는 방식과 내 사고방식에는 커다란 차이점이 있다는 것을 알게 되었다.
딱 여기까지만 쓰게되면, '나는 그런 능력과는 인연이 없어' 라던가 '조금 능력이 뛰어나다고 건방떨지마' 라던가 '우연이다' 라고 생각하는 사람이 있을지도 모르기 때문에 지금부터 생각하는 방식을 조금만 바꾸는 것으로 누구든지 위에서 쓴 것 같은 능력·작업 효율을 가질 수 있다는 것을 전하고 싶다. 그러면 나 혼자만이 아니라 다른 사람들에게도 유익하다고 생각하기 때문이다.
우선 가장 중요한 사전지식이다. 반드시 다음 세가지를 지키도록 한다.
- 노력하지 않을 것
- 논리적으로 사고하지 않을 것
- 머리를 쓰지 않을 것
갑자기 이런걸 읽게 되면 보통 알고 있던것과는 정 반대라서 놀란다거나 의심한다거나 하는 사람이 있다(랄까, 대부분의 사람들이 그럴 것 같은 느낌이 든다). 우리들은 보통 사회 통념으로 1. 노력할것, 2. 논리적으로 사고할 것, 3. 머리를 사용할 것, 을 항상 주입당하고 있다. 그러한 잘못된 '지도'를 초등학교입학~취직~퇴직할 때 까지(즉 평생동안) 받다보니 자신의 능력에 대해 전혀 알아차리지 못한 채 일생을 마치는 사람도 있을 것이다.
특히 컴퓨터 프로그래밍은 논리적인 직업의 극단적인 예인만큼 프로그래밍을 하는 경우의 개발자의 머리속이 논리적으로 생각하고 있다고 보는 것이 보통이며, 위에서 쓴 '2. 논리적으로 생각하지 않을 것' 에 대해 크나큰 위화감을 느끼는 사람이 많을 것이기 때문에, 우선 그 점에 대해 설명하도록 하겠다.
최근 얘기를 해보니 '컴퓨터에 관련된 기술적인 직업(특히 프로그래밍이나 소프트웨어 설계등)은 논리적인 사고를 하는 것이 좋다' 라고 오해하는 사람이 꽤 많은 것을 알게 되었다.
사실 프로그래밍 따위의 것은 컴퓨터에게 프로그래밍 언어를 논리적으로 기술해서 지시를 내리는 작업이므로, 그 작업중에 '논리적인 사고' 를 하면 할수록 능률이 올라간다고 생각하는 것이 자연스러울 것이다.
하지만 실제로는 정 반대인 것이다.
복잡하고 난이도가 높은 작업에 임해서는 설령 컴퓨터 프로그래밍따위의 초논리적 결과를 얻기 위한 작업이라도 '논리적인 사고' 는 거의 필요 없다
여기서 '논리적인 사고' 의 정의를 하지는 않겠다. 사실 자세하게 정의하는 것 자체가 '논리적인 사고' 인 것이다(논리적으로, 엄밀하게 정의하지 않았으므로 당신의 머리속에 '논리적인 사고'에 대한 이미지를 자유롭게 떠올리면 된다)
나는 뇌과학에 대해서는 잘 모르기(오늘 밤에 공부를 시작해보려 한다) 때문에, 아래에 쓴 내용들은 논리적· (기존의)과학적으로는 맞지 않을 수도 있다. 그렇지만 논리적인 사고를 하지 않았으면 하는 의지를 설명하고자 쓴 것이기 때문에 논리적으로 틀린점에 대해서는 적당히 넘어가 줬으면 좋겠다.
프로그래밍을 하는 것은 당연히 인간이다. 인간은 프로그래밍을 하는 것으로 구현하고자 하는 처리내용에 대한 명령을 논리적으로 기술해서 컴퓨터에 넣는다. 이것이 프로그래밍이다.
컴퓨터에 대한 논리적인 명령이라는 목적이 있기 때문에 프로그래밍은 '논리적인 일'이라고 생각하게 되고, 프로그래밍 작업 전부에 대해서 인간쪽에서 논리적인 사고를 가지고 작업하게 되는 것이다. 사실 프로그래밍의 작업의 거의 대부분에 걸쳐서 논리적인 사고라는 것은 '전혀'라고 해도 좋을 정도로 필요 없다.
예를들어서 논리적이지 않은 작업에 대해서 생각해보자. 음악을 듣고 '이거 좋네' 라고 생각한다거나, 영화를 보고 감동한다거나 하는 작업은 논리적 사고보다는 직감적인 작업이다. 음악을 들으며 '이 주파수나 패턴의 음색이 xx msec 마다 연속으로 나타난다. 이거 좋네' 라고 항상 논리적으로 사고했다간 음악을 제대로 듣는 것은 불가능하다. 훨씬 직감적으로 '어째서인지 말로는 표현할 수는 없지만, 이 음악은 좋다' 라는 느낌이 생기는 것이다.
컴퓨터 프로그래밍을 읽고 쓰는 따위의 논리적인 기술방식을 대상으로 하는 작업이라도 음악을 듣는 것과 마찬가지로 논리적인 사고방식이 전혀 필요 없다.
논리적이지 않은 사고를 하는 것이 중요하지만 여기서는 일단 '직감적인 사고'라고 써서 표현하기로 한다.
일단 현재의 과학으로는 인간의 뇌는 컴퓨터와 비슷한 것으로 알려져있다. 하지만 물론 폰 노이만식 컴퓨터(보통의 컴퓨터) 아키텍쳐는 아니다. 훨씬 효율이 좋은 방법으로 여러가지 작업을 수행할 수 있는 것이다.
현재의 컴퓨터는 논리적인 처리밖에 할 수 없지만, 인간은 직감적인 사고처리가 가능하다. 인간의 아키텍쳐와 현재의 컴퓨터 아키텍쳐는 전혀 효율이 다르다. 그런데, 어째서인지 프로그래밍작업을 하다 보면 대상이 되는 컴퓨터가 논리적인 처리밖에 하지 못하기 때문에 인간쪽도 어느샌가 무의식적으로 논리적인 사고밖에 할 수 없게 된다. 여기서 커다란 문제가 생긴다.
인간의 아키텍쳐는 감각적 사고에 의해 동작하고, 그 처리능력은 매우 높다. 그래서 인간은 노력에 따라 직감적 사고의 기능을 기반으로 보통의 컴퓨터가 하는 것과 비슷하게 논리처리 환경을 에뮬레이션 해서 여러가지 논리적 프로그램을 실행하는 것이 가능하다. 예를들면 전자 계산기를 쓰지 않고 암산을 한다던가 짧은 프로그램이 있으면 컴퓨터에 입력하지 않고 머리속에서 실행할 수 있는 것이다.
하지만 인간의 감각적 사고기능을 기반으로 에뮬레이션한 논리처리기능은 결국 에뮬레이터나 마찬가지기 때문에, 실물(인간 본체)와 비교하면 처리속도가 매우 느리다. 오버헤드가 너무 크기 때문이다. 이런저런 방식의 처리를 순간적으로 동시에 실행하는 것이 가능한 인간의 두뇌가 있는데도 불구하고, 논리적처리를 위한 가상환경을 뇌내에 탑재하고 그 위에서 생각을 하다보면 효율이 나빠진다.
이것이 보통의 소프트웨어 개발자가 한달동안 수백줄~3천줄 정도밖에 코딩하지 못하는 원인이다. 인간에게 탑재된 가상논리처리 에뮬레이터의 성능이 매우 안좋은 것이다.
그래서 논리적사고를 최대한 배제하고 인간 본래의 장기인 사고법, 즉 직감적 사고기능을 이용해서 여러가지 작업을 하면 매우 고효율이 된다.
여기서 대부분의 사람들은, 이 인간이 가진 초고성능의 '직감적 사고능력'이 작곡이나 소설의 집필, 영화의 제작등의 예술적인 창작작업에만 사용되는 것이 가능하고, 프로그래밍이나 설계나 계산이나 그런 종류의 논리적 작업에는 사용할 수 없다고 오해하고 있다. 논리적으로 생각하면 분명히 논리적인 작업은 논리적인 기반으로밖에는 할 수 없다.
하지만 나는 프로그래밍이나 그 밖의 논리적인 작업에 대해서도 초 고성능인 '감각적 사고 기능'을 직접 사용해서, 일부러 뇌내 회로를 에뮬레이션에 사용하지 않더라도 효율좋게 처리할 수 있는 방법을 알고 있는 덕택에, 그쪽을 사용하고 있는 것 뿐이다.
실제로 프로그래밍작업을 예로 들어서 설명하겠다.
우선, 대충 이런 소프트웨어가 있었으면 좋겠다 라던가, 이런 기능을 붙일 필요가 있겠군 이라던가, 매우 추상적인 것에 대해 생각이 떠오른다. 이 경우, "반드시 논리적으로 생각하지 않을 것"이 필요하다. 조금이라도 논리적으로 생각하게 되면 잘 나가다가도 갑자기 무너져 버려서 처음부터 다시 시작하게 될 수 있으므로 조심해야한다. 감각적인 사고로 생각해보는 것이다.
대충 이미지가 떠오르면 다음은 머리속으로 소프트웨어 설계나 데이터 구조를 떠올린다. 여기서 주의할 것은 '절대로 논리적으로 생각하지 않고 설계할 것' 이다. 감각적인 사고를 가지고 설계를 하는 것이다.
이것으로 거의 모든 작업이 끝났다. 남은 것은 마지막으로 컴퓨터에 대해서 프로그래밍을 하는 것뿐이다. 이 작업에는 물리적인 컴퓨터 키보드가 꼭 필요하다. 종이에 펜으로 적다간 손이 힘들기도 하거니와 키보드를 쓰지 않고도 컴퓨터에 입력할 수 있는 편리한 장치는 아직 없기 때문이다.
프로그래밍의 목적은 컴퓨터에게 처리를 맡기는 것이기 때문에 컴퓨터에 프로그램을 입력하지 않으면 의미가 없다. 그래서 어쩔 수 없이 컴퓨터 앞에 앉는다.
컴퓨터 앞에 앉아서 키보드 위에 양손을 얹으면 그 다음은 별로 생각할 필요가 없다. 자동적으로 손이 키보드를 쳐서 프로그램을 입력해서 완성해준다. 이 처리는 전부 논리적 사고에 의해 이루어지는 것이 아니기 때문에 도중에 논리적 사고를 하는 것은 엄금한다(작업에 방해된다). 그냥 아무것도 생각하지 않는다.
입력 에러가 생기지 않는 정도에서 손을 움직이는 속도에는 물리적인 한계가 있다. 많아야 하루 1만줄 정도다. 그래도 입력 에러는 빈번하게 발생한다. 이 작업은 에네르기가 필요하기 때문에 식사를 제대로 해야 하고, 좋아하는 음료(100% 오렌지 쥬스가 좋다 ※역자주 : 오렌지주스는 마시다보면 질리므로 적당히 묽은게 좋다)등을 책상위에 준비해 두는것이 좋다.
프로그램이 일단 완성되면, 테스트해본다. 역시 약간의 버그가 발생한다. 이것의 대부분은 컴퓨터 프로그램을 입력할때 발생하는 뇌의 변환 에러인 것이다. 뇌에 있는 감각적 프로그램의 구성 데이터를 컴퓨터가 이해가능한 논리적 프로그래밍 언어로 바꾸는 부분이 약간 틀리는 경우가 있다. 하지만 이것도 반복하다 보면 정확도가 높아지므로 걱정할 필요는 없다.
몇번 테스트 해 봐도 나중에 버그가 나오는 경우가 있다. 논리적으로 생각해보면, 위에서 쓴 것처럼 정확한 프로그래밍 작업결과에는 약간의 에러도 없어야 하지만, 이것은 논리적인 처리가 아니기 때문에, 어째서 버그가 발생하는지는 논리적으로 알 수 없다. 이것은 어쩔 수 없기 때문에 버그를 고치면 그 뿐이다. 그래도 보통의 프로그래머가 논리적으로 생각해서 쓰는것에 비교하면 버그의 발생 건수는 훨씬 줄어서 편해진다.
위에서 쓴 방법은 아마도 프로그래밍이 아니라 이런저런 설계나 문장의 집필, 자동차등의 운전에서 대부분의 사람들이 활용하고 있는 것이 아닐까하고 생각해본다.
게다가 이 방법은 일절 노력을 하거나 고생을 할 필요가 없어서 매우 편하다.
또한 컴퓨터관계의 일을 하는 사람중 작업효율이 좋은 몇명과 얘기를 해보면 대개 위에서 얘기한 것처럼(표현은 다르지만) 하는 것을 알 수 있다. 덕분에 평균 레벨과 비교해보면 높은 능력으로 일을 하는것이다.
최대의 문제점은, 모처럼 위의 글을 읽더라도 대부분의 사람들의 머리속에 있는 논리적 사고가 '저건 논리적으로 말이 안돼' 라고 논리적으로 생각해버려서 언제까지고 논리적으로만 생각하는 것이다.
논리적으로 생각하지 않는것이 잘 된다고 듣더라도 그것이 옳은 것인지 해보지도 않고, 논리적인 판단을 하려고 해서 '논리적으로 생각한 결과, 설마 그렇지는 않겠지' 라는 논리적 사고를 좇아 언제까지나 해보지 않는것이다. 그건 너무 아깝지 않은가.
그래서 다음에 시간이 되면 일기나 뭐 어딘가에 여기에 대해 자세하게 해설해서, 가능하면 누구든지 이용할 수 있도록 정리했으면 좋겠다.
-------- 여기까지 ---------
번역: mithrandir - http://tisphie.net/
오탈자 및 오역은 알아서 보세요 (...)
Posted in 프로그래밍 | Tags 감각적사고, 코딩, 프로그래밍 | 3 comments | no trackbacks