재설계
사람들이 미술을 처음 시작하면 잘못된 부분을 다시 그리는 것을 꺼려한다. 일단 그 정도로 그린 것에 만족하며, 다시 손을 대다가 혹시 더 망치지나 않을까 염려한다. 그리하여 방금 그린 것이 그렇게 나쁘지는 않다고, 어쩌면 최선의 작품일지도 모른다고 생각하여 스스로를 설득한다. 폴 그레이엄, 해커와 화가
전에 언급한 Non-ASCII 문자 스트링과 관련한 Java와의 호환 문제가 Charles Nutter가 예고한대로 JRuby 1.0에서는 말끔하게 해결되었음을 저의 테스트 케이스로 확인했습니다. 강문식 군에 의하면 이창신 님이 이 작업에 기여하신 모양입니다.
이 글은 2004년 12월 14일, 네오위즈에서 일하던 시절에, 팀 내부에 공유한 메일입니다. (영어 단어나 어법 오류 등은 수정했습니다.) 현재의 제 생각과는 약간 다른 부분도 있지만,
등은 저 뿐만 아니라 많은 사람들이 동의하는 프로그래밍의 원칙들입니다.
이름 짓기
바쁜 일정과 많은 업무로 인해서 팀 내에서는 ‘이름 짓기’가 중요하게 여겨지지 않고 있지만, 저는 이름 짓기에 대해서 강한 의견을 가지고 있는 사람입니다. ;-)
객체와 메서드의 이름을 지을 때는 그것이 하는 역할에 맞게 이름을 짓는 것이 좋습니다. 당연히 이 역할은 객체가 해결하려는 문제의 도메인 안에서, 그 도메인의 언어로 정의됩니다. 따라서, 객체와 메서드의 이름은 문제 도메인의 언어로 기술하는 것이 가장 바람직합니다. (일반화된 이름은 원래 문제 도메인의 이름이 아닌 경우가 있지만, ‘일반화’ 역시 일종의 해결하려는 문제입니다)
예를 들어, 6살짜리 어린이가 가게에서 사탕을 사먹는 문제에 대해서 해결 방법을 기술하려면, 6살짜리 어린이가 이해할 수 있어야 하고, 사탕이라는 단어가 거의 반드시 들어가야겠죠. 또한, 사탕을 사 먹어야 하는데, 다른 도메인의 언어, 즉 음표라든가, 양자역학 같은 단어가 나오면 곤란합니다.
junkmemocheck를 희생양으로 삼아 예를 들어보죠. (junkmemocheck는 쪽지를 너무 많이 보내는 사람을 차단하기 위해 사용자별로 최근에 쪽지를 보낸 수를 세어주는 컴포넌트입니다.)
메서드 이름 짓기
제가 이해한 바로는, junkmemocheck(이하, 줄여서 JMC)에 관련된 시나리오는 다음과 같습니다.
- 사용자 A가 쪽지를 보낼 때, A가 쪽지를 보냈음을 JMC에 알려줍니다.
- 사용자 A가 미리 정해진 시간 내에, 쪽지를 보낸 수를 얻거나, 너무 많이 보냈다는 정보를 얻어옵니다.
이를 좀 더 단순한 말로 적어보죠.
- 특정 사용자가 쪽지를 보냈다.
- 특정 사용자가 최근에 쪽지를 보낸 수를 주세요.
메서드 이름으로 바꿔보죠.
쪽지는 Memo라는 용어로 대치하고, ‘미리 정해진 시간 내에’라는 requirement에 대해서 ‘Recently’라는 단어를 도입했습니다.
- sentMemo(user)
- getCountOfMemoSentRecently(user)
좀 더 줄이면,
- sentMemo(user)
- getRecentMemoSent(user) 또는 getMemoSent(user)
클래스 이름 짓기
이러한 역할에 비추어보면, junkmemocheck는 (Sent)MemoCounter 같은 이름이 더욱 적당하지 않을까 싶습니다. (사실 ‘정해진 시간 내’라는 제약 조건이 있어서, “Counter”라는 비유가 약간 부적절해 보이므로, 좀 더 나은 비유가 있으면 좋을 듯 하네요.)
MemoCounter
+ increaseCount(user)
+ getRecentCount(user)일반화된 이름 짓기
나중에 다른 요구사항이 생겨서, 쪽지만이 아니라 다른 곳에도 이 어플리케이션이 사용되기도 결정되었다고 합시다. 우리는 “Counter”라는 비유를 이미 사용했으므로, 이를 그대로 사용하면 될 것 같습니다. 사용자 대신 슬롯(slot)이라는 개념을 사용합니다.
Counter 클래스의 역할(Role)은 다음과 같습니다.
- k 슬롯의 카운터를 하나 증가시킨다.
- 일정 시간 내에 k 슬롯에 증가된 카운터 값을 가져온다.
이를 바탕으로 다음과 같이 이름을 지을 수 있겠네요.
Counter
+ increaseCount(k)
+ getRecentCount(k)개선된 디자인
사실 Counter 안에 k라는 슬롯을 찾는 것보다는, k라는 이름의 Counter가 있는 것이 더욱 직관적입니다. Counter의 메서드에 k를 명시하기 보다는, k에 해당하는 Counter 객체가 있는 것이 낫겠죠.
kCounter = CounterCollection.getCounter(k)
kCounter.increaseCount()
kCounter.getRecentCount()좀 더 단순하게 만들어볼까요? CounterCollection에 Count가 있는 것은 당연하고, Count를 increase하는 것은 당연하므로,
kCounter = CounterCollection.get(k)
kCounter.increase()
kCounter.getRecent()성능 고려하기
MemoCounter 든, Counter든 역할에 따라 두개의 operation으로 분리했습니다. 하지만, 내부적인 구현에 따르면, 각각이 server로 메시지를 따로 보내야 한다면, 그리고 거의 항상 두 operation이 같이 쓰인다면, 이러한 분리는 비효율적입니다. 한번에 물어볼 수 있는 방법이 필요합니다.
Counter
+increase(k)
+getRecent(k)
+increaseAndGetRecent(k)가능한 한 원래의 인터페이스가 직관적이므로 유지하는 것이 좋다고 생각하지만, 이를 유지하면서 성능을 개선할 수 있는 더 나은 방법이 있을지도 모르겠습니다.
인터페이스 최소화
거의 항상 단순한 인터페이스가 좋습니다. 필요없는 인터페이스는 사용자를 혼란스럽게 합니다. 예를 들어, increaseAndGet(k)만이 사용되고, 다른 메서드는 사용될 가능성이 별로 없다면,
Counter
+increaseAndGetRecent(k)만으로도 충분합니다.
결론
저는 메서드 이름부터 새로 짓기 시작했지만, 좀 더 일반적인 방법은,
- 문제 해결에 필요한 객체의 이름과 역할을 정합니다. 객체를 정할 때는 문제를 해결하기 위한 비유를 생각해보면 좀 더 쉽게 지을 수 있습니다. 문제는 얼마나 적절한 비유인가인데, 어떤 비유가 객체의 역할 즉, 문제의 해결방법에 얼마나 근접하느냐를 따져야할 것입니다. 객체의 이름은 항상 문제 도메인의 언어나, 비유의 이름으로 짓습니다.
- 객체 역할에 따라 메서드를 추가합니다. 하나의 동작에 하나의 메서드를 추가합니다. 메서드 이름 역시 항상 문제 도메인의 언어로 짓습니다.
- 이 후에도 얼마든지 성능 고려나 인터페이스 최소화를 할 수 있습니다.
Heroes 에피소드 10에서 웨이트리스를 구하기 위해 시간이동을 하다가 6개월전으로 가버린 히로가 안도에게 도움을 구하기 위해 전화를 하지만, 과거의 히로가 전화를 받죠. 그 때 – 서로 다른 시간에 존재하는 자신을 조우했을 때, 어떤 현상이 일어나는지 모르니까 – 히로가 놀라서 하는 말이 “Great Scott!”입니다.
위키피디아 내용대로라면 Great Scott은 놀람을 표현하는 감탄어구라고 볼 수 있는데, Superman 같은 수퍼히어로물이나 나르니아 연대기 등에서도 사용되었다고 하는군요. 그 기원은 남북전쟁 시대의 유명한 장군의 이름이라고 하는데, 그것이 왜 감탄어구로 자리잡게 되었는지는 알 수가 없군요.
어쨌든 히로 너무 귀엽습니다아.
Dynamics of Software Development by Jim McCarthy
요즈음 널리 유행하는 방법론들처럼 체계화 되어있는 것은 아니지만, 이 책은 소프트웨어 개발의 여러 부분들에 걸친 조언을 담고 있는 책이다. 그 범위는 소프트웨어 개발에서 어떤 것이 바람직한 리더쉽인가, 어떻게 팀을 만들 것인가, 고객이나 비즈니스 부문 등의 팀 외부와 어떻게 소통할 것인가, 경쟁 시장에서 어떻게 포지셔닝할 것인가,빌드와 출시, 개발 일정과 주기는 어떻게 할 것인가, 사람은 어떻게 뽑을 것인가와 같이 소프트웨어 개발 팀에 관련된 거의 모든 부문을 다루고 있다고 해도 과언이 아니다.
저자는 소프트웨어 개발팀을 생태계와 같은 것으로 보고 있다. 팀원들은 팀장의 지시에만 따르고, 미리 정해진 역할을 수행하는 것이 아니라, 팀장은 팀원에게 권한을 위임해야하며 (지식노동에 있어서 이것은 이미 황금률이다.) 팀원들은 자신의 능력이 다른 팀원들과 조화를 이루도록 역할을 진화시켜 나간다. 이러한 관점은 소프트웨어가 지식 노동의 산출물이기 때문에 무엇보다도 팀원들부터 아이디어가 자유롭게 나오고 그 중에서 최상의 아이디어가 선택되어야한다는 이유에 비롯한다.
애자일 소프트웨어 개발 프랙티스 (이를테면 XP와 같은)에서와 비슷한 주장들을 1995년에 쓰여진 이 책에서 하고 있는 것도 재미있는 점이다. (참고로, C3 프로젝트는 1996년에 시작되었고, Kent Beck이 유명한 Extreme Programming Explained를 내놓은 것은 1997년의 일이다.) 신속하게 개발주기를 반복한다든가, 알려진 상태를 유지하는 것, 고객과의 관계의 강조 등에서 그러한 것들을 엿볼 수 있다. Scrum과 같은 방법론은 1993년에 적용되기 시작했고, Iterative and Incremental Development: A Brief History와 같은 문서를 보면, 1980년대에 이미 점진적인 개발 방법이 소프트웨어 개발계에 떠들썩하게 떠오르고 있음을 할 수 있다.
설령 책이 제시하는 세부적인 방법들에 동의를 하지 않는다고 하더라도 한번이라도 팀에서 소프트웨어 개발을 해본 경험이 있다면, 지난 날의 경험을 회상하며 이 책의 조언에 대해 깊히 생각해보는 것은 매우 유익한 일일 것이다. 다만, 저자는 인문학적인 배경이 있는지 몰라도 문학이나 철학에 기원한 개념들을 자주 빌려쓰고 있을 뿐만 아니라 전체적인 문체도 간명한 편은 아니어서, 읽기가 쉽지 않은 면이 있다. 단지 번역의 탓만은 아닌 듯 보인다. 반대로 이러한 점 때문에, 한문장 한문장을 곱씹어볼 경우 여러가지 경우에 여러 의미로 다가올 수도 있을 것이고, 비단 저자의 조언을 곧이곧대로 받아들이기보다는 풍부한 고민의 원천이 될 수 있는 면도 있을 것이다.
밸브(Valve) 사의 게임 배포 시스템인 스팀(Steam)에서 게임(Tomb Raider: Anniversary)을 구입한 후 설치 도중 진행률 99%에 멈춰서 더이상 진행되지 않고, 게임도 플레이할 수 없는 문제가 생겼습니다. (SexyDino님도 경험하셨더군요.)
스팀 A/S에 문의해보니 FAQ 답변을 제시해주었고, 모든 방법을 시도해보았으나, 해결에 도움이 되지 않았습니다. 거의 포기하고 있다가, 마지막 방법으로 ‘유니코드를 지원하지 않는 프로그램용 언어’ ([제어판]-[국가 및 언어 옵션]-[고급])의 설정을 영어로 하고 다시 설치를 시도하니까 정상적으로 설치가 되고 이 설정을 원래대로 복구한 후에도 플레이가 가능했습니다.
스팀 A/S에도 이러한 해결책을 알려주었고, 스팀 측에서도 개발자들에게 이러한 이슈를 알려주고 다른 사용자들이 비슷한 문제를 겪을 때에도 신경을 쓰겠다고 하는군요.
Lizardlings에 관한 글에 이은 Neverwinter Nights 2에 관한 글입니다.
은 파편(silver shard)를 가지고 네버윈터 시로 향하는 도중, 주인공 엘레넬라 레인(Elenella Lane)은 위핑 윌로우 여관(The Weeping Willow Inn)에 도착하게 됩니다. 여기서 드워프 (Dwarf; 정확히는 쉴드 드워프 Shield Dwarf) 하나가 깡패임직한 여럿과 싸움이 붙은 것을 보게됩니다. Chaotic Good 성향의 주인공이 그냥 두고볼 수 만은 없죠. 잘생기지는 않았지만 그를 도와주게 됩니다.
그의 이름은 김리…가 아니라 켈가 아이언피스트(Khelgar Ironfist). 부모님이 날 때부터 그렇게 이름을 지어준 건지 자기가 직접 개명을 한건지는 몰라도, 이름 그대로 그는 주먹질을 좋아하는 파이터입니다. 그는 한때 수사(monk)와 싸우다가 당한 적이 있어서 수사가 되기를 열망합니다. (D&D 설정에서 수사는 맨손전투를 하는 직업이죠. 디아블로 2를 해보신 분은 익숙하실 겁니다.) 수사는 싸움질만 하는 직업이 아니라고 얘기해줘도 막무가내입니다. 어쨌든 이리하여 켈가는 네버윈터 시로 향하는 여정에 동료로 참가하게 됩니다.
로크 요새(Fort Locke)의 외곽에 도착하자 또 싸움이 벌어졌군요. 한무리의 병사들이 티플링(Tiefling) 하나를 둘러싸고 때릴 기세입니다. 티플링은 Planetouched, 즉 이 세상의 종족이 아닙니다. 신기하게도 머리에 뿔이 달려있죠. 마이너한 종족이라고 왕따 시키는 것은 그냥 지나칠 수 없습니다.
이 티플링의 이름은 니쉬카(Neeshka)로 직업은 로그(Rogue)입니다. 그녀는 기대하지 않았던 도움을 얻게된 것에 대해 대단히 고마워합니다. 사실 고마워해야하는 쪽은 이쪽이죠. 로그나 도적 계열은 잠긴 문이나 상자를 열 수 있고, 위험한 함정을 쉽사리 발견해주기 때문에 파티에 한명 있으면 게임 진행이 대단히 수월합니다.
세번째 파티원은 Highcliff로 향하는 도중에 만나는 우드 엘프(Wood Elf) 드루이드(Druid), 엘라니(Elanee)입니다. 드루이드인 그녀는 자연을 사랑하고 교감합니다. 그녀의 동지들이 있는 Maiden’s Glen으로 가보았을 때는 그녀의 동지들은 보이지 않고 동물들이 모두 포악해져서 파티를 공격합니다. 그녀는 동지들을 잃은 것에 슬퍼하지만, Maiden’s Glen을 떠나 파티를 따라가기로 결정합니다.
로크 요새의 지휘관이었던 Tann을 구출하는 과정에서 Shadow Priest를 한명 처치하게 되는데, 이를 통해서 로크 요새를 함락하려는 음모를 저지시켰다는 것을 알게해주는 cut scene이 진행됩니다. 대체 ‘Master of the Fifth Tower’란 이 분은 정체가 무엇일까요?
이러한 의문을 뒤로하고 일행은 드디어 네버윈터 시의 남부 항구 지역인 블랙레이크 가 (The Blacklake District)에 도착합니다.
처로군 집에 가서 보고 마음에 들어서 가로폭 1.6m 짜리 탑책상 샀는데, 막 설치완료했습니다. 컴퓨터에 관련된 배선을 모두 새로 하느라 좀 고생했습니다. 책상은 조립형인데, 상판이 튼튼하고 묵직한데다가, 크기도 크다보니 무게가 좀 됩니다. 그래서 책상을 들지않고 밀거나 하면 고정쇠 부분이 빠지거나 하네요. 하지만 가격대 성능비는 만족입니다.
엑스박스 360을 놓다보니 기존에 억지로 올려놓던 서버용 모니터를 놓을 자리가 없네요. 기존 책상을 방 어딘가에 배치해야할 것 같네요.
국내에서도 인기있는 히어로즈(Heroes)의 22화가 현지시각으로 2007년 5월 14일 오후 9시에 방영되었습니다. 그러니까 우리나라 시간으로는 대략 오늘 오전 11시 정도라고 보면 되겠죠. 한글 자막은 오후 5시 30분 경 디씨 히갤에 올라왔습니다. 그렇다면 우리의 웹검색 서비스들은 어떨까요? 다음은 한국 시각으로 2007년 5월 14일 오후 9시 30분경에 검색한 결과의 첫페이지들입니다. (이러한 결과를 처로군이 처음으로 제보해주었습니다.)
결과를 요약하면, 네이버는 웹검색을 통해 씨즐 게시판의 글(오후 7시 30분경)에서, 다음은 블로그 검색을 통해서 (오후 6시 30분경)자막을 얻을 수 있었지만, 엠파스와 구글, 다음의 새로운 웹검색은 검색에 실패했습니다.
네이버와 다음은 2, 3시간 정도 내에 국내의 웹을 검색 결과에 반영할 수 있다는 얘기지요. 네이버의 지식인과 같은 자체 커뮤너티 효과를 무시하더라도 말입니다. 네이버 지식인을 고려하면 더욱 차이가 날 수 밖에 없습니다. 최근의 박지윤 아나운서 사건의 경우에도 사건 후 4시간 정도 경과 시점에서 구글 검색에서는 전혀 알 수 없지만, 네이버에서는 지식인을 통해서 그 사건을 알 수 있었죠.
다음의 결과는 상대적으로 손쉬운 블로그 검색에서만 원하는 결과를 얻을 수 있고 웹 검색결과에서는 얻을 수 없다는 점(웹 검색결과에 히갤 결과가 나온 것은 좋았지만, 원하는 결과가 아닐뿐더러 12시간 이전의 결과입니다.)이 네이버 쪽에 손을 들어주게 만드는군요. 엠파스는 네이버나 다음의 수준을 전혀 따라가지 못해서 실망스럽습니다.
이러한 결과는 단편적이고, 하나의 현상에 불과하지만 그 원인은 국내 검색엔진들이 국내 웹의 freshness에 좀 더 신경을 쓰고 있거나, 국내 웹의 특성(이를테면 게시판 위주)에 잘 맞추어 작동하고 있다고 볼 수도 있을 것 같습니다.
시간이 나는대로 이러한 테스트를 여러번 반복해서 좀 더 객관적인 결과를 도출해낼 수 있어야할 것 같습니다.
제1장 ‘정치철학이란 무엇인가?’의 제2절 ‘신념에 대한 비판적 평가’의 요약입니다.
전통적인 철학의 근본적 목적은 바로 신념들을 받아들이거나 거부할 수 있는 합리적인 근거를 제공하려는 시도이다. 과학은 설명을 추구하고 인과적 설명의 형태를 띄나, 철학은 정당화를 추구하고 신념에 필요한 합리적 근거를 탐구한다.
따라서, 철학의 역할은,
양립불가성을 해결하는 방법에는, 전통적인 신념을 제거하거나 반대로 새로운 신념을 거부하는 방법이 있고, 2개의 신념 체계 중 하나를, 이들이 양립할 수 있도록 수정하는 있다. 이러한 작업에는 관련된 모든 사실에 알맞는 관념의 새로운 틀을 제시하는 작업이 뒤따를 수 있다. 또한, 하나의 문제가 새로운 개념적 틀이나 철학 체계를 통해 해결되면 철학자들의 관심을 그 체계 자체에로 전환하기 쉽다.
지식 철학(인식론, 형이상학)이 무엇이 참인가에 대한 신념에 관심이 있다면, 실천 철학(도덕 철학, 사회 철학, 정치 철학)은 인간과 사회를 위해 무엇이 옳으며 선한지에 관한 신념과 원리에 관심이 있다.
신념이 합리적으로 정당화되기 위한 2가지 기준은 (내적인) 일관성과 사실과의 일치다.
사실의 문제(matter of fact)에 관한 신념의 경우, 즉 사실 철학의 문제에서, 일관성을 가진다고 하더라도, 실제 사실의 세계에 적용되거나 또는 일치하는지를 알아야 한다. 이 때, 철학자는 일관성을 검증할 수 있으나 무엇이 관련된 사실인가를 알아내는 것은 바로 과학의 임무다. 따라서, 지식 철학은 한 신념이 사실과 일치하는 지를 결정할 수 없다.
실천 철학은 사실과의 일치라는 기준을 대신하는 것이 무엇인지 분명하지 않다. 상충하는 가치체계 중 어느 것이 사실적, 객관적인 것으로 간주될 수 있는지 결정하기 위한 인정된 절차는 없다. 대안은 비판적인 평가에 있다. 비판적인 평가란, 한 신념을 직접적으로 정당화하는 것이 아니라, 그 신념에 대한 다른 대안을 제거함으로써 간접적으로 그것을 지지하는 형식을 말한다.
정치철학에 국한해서 실천철학에 대한 비판에 대한 반론은 다음과 같다.
일관성이라는 기준이 부정적 검증으로서 어느 정도 결정적일 수 있음을 과소평가 (과학에서도 마찬가지.)
전통적인 정치 철학에 대한 비판은 사실이 가치 판단을 뒷받침하는 역할을 수행한다는 점을 간과 (가치 판단은 종종 일치성의 시험을 받는 사실에 관한 신념을 전제한다.)
정치철학에 있어서 비판적인 평가의 대상이 되는 모든 문제가 이 같은 방식으로 해결될 수는 없다. 갈등이 일어나는 대립적 주장을 살펴봄으로써, 불일치성이나 잘못된 실제적 전체들을 밝혀내는 철학적 방법은, 비교상의 가치(comparative value)에 대한 견해의 차이(e.g. 자유와 평등이라는 가치에 대한 서로 다른 상대적인 평가)라는 핵심적인 문제를 미해결된 상태대로 내버려두는 문제점을 가지고 있다.
Problems of Political Philosophy, Chapter 1, Section 2 더 읽기"