Skip to main content

Posts

Showing posts from March, 2007

Blub 레벨 높이기

갑->을이라고 할 때: '갑'는 '을'보다 자신이 더 잘났다고 생각한다. 갑<->을 이라고 할 때: '갑'과 '을'은 둘 다 자신이 더 잘났다고 생각한다. 출처: 프로그래머 서열 . Beating the Average 라는 글에 보면 Blub Paradox라는 말이 있습니다. Blub Paradox를 이해하기 위해서는 먼저 프로그래밍 언어는 모두 가지고 있는 힘이 다르다는 사실을 인정해야 합니다. C언어가 기계어보다 더 강력하듯이 python이나 C++, ruby, java, lisp 등의 고급 언어들 사이에도 이런 서열이 존재한다는 것이죠. 그럼 이제 Blub이라는 가상의 언어를 생각하고 이 언어를 현재 우리가 사용하고 있는 언어라고 합시다. 이 언어가 COBOL보다는 강력한 언어라고 가정하면 서열은 다음과 같습니다. 기계어 < COBOL < Blub < ? 이제 Blub 프로그래머가 아래, 즉 COBOL과 같은 언어를 보면 COBOL이 왜 Blub보다 약한 언어인지를 알 수 있습니다. 자신이 사용하고 있는 Y라는 기능이 COBOL에는 없기 때문이죠. 심지어 어떻게 Y라는 기능도 없는 언어로 프로그래밍을 할 수 있는지 궁금해 합니다. 하지만 반대로 위를 올려다보면 우리는 우리가 보고 있는 것이 무엇인지를 깨닫지 못합니다. 단지 Blub으로도 할 수 있는 일을 이상한 문법이나 방법으로 하고 있다고 생각하기 쉽죠. 결국 그 언어가 왜 Blub보다 강한지 알지 못하는데 이를 Blub Paradox라고 합니다. 이렇게 더 강한 언어의 강력함을 이해하지 못하는 이유는 바로 우리가 현재 Blub의 높이에서만 생각할 수 있기 때문입니다. 위의 내용에서 유추해보면 결국 모든 언어의 장/단점과 차이를 이해하기 위해서는 가장 강력한 언어를 알아야 한다는 결론이 나옵니다. 물론 위에서 언급한 Paul Graham의 글에서는 이 언어가 Lisp이라고 이야기하고 있죠. 얼마전까지 제 Bl

C++ of the Day #39 - State with NVI (or Template Method)

프로토콜을 다루는 프로그램에서 가장 많이 사용되는 design pattern은 아마 State pattern일 것입니다. GoF의 State pattern 설명에서 Structure 부분을 보면 다음과 같습니다. (State pattern의 설명은 다들 아실테니 생략합니다.) 이번 글에서는 프로토콜을 다루는 코드 대신 Wikipedia에 있는 State pattern 코드 를 가지고 설명하겠습니다. 이 예제는 drawing program에 대해서 다루고 있습니다. 먼저 Wikipedia에 있는 코드를 보시죠. 아래의 AbstractTool 클래스는 위의 State pattern의 Structure에서 State 에 해당합니다. ((AbstractTool 클래스에는 public virtual 소멸자가 있어야 하나 Wikipedia에 있는 코드를 그대로 사용합니다.)) class AbstractTool { public: virtual void MoveTo(const Point& inP) = 0; virtual void MouseDown(const Point& inP) = 0; virtual void MouseUp(const Point& inP) = 0; }; 다음으로 ConcreateState 에 해당하는 PenTool과 SelectionTool 클래스가 있습니다. class PenTool : public AbstractTool { public: PenTool() : mMouseIsDown(false) { } virtual void MoveTo(const Point& inP) { if(mMouseIsDown) { DrawLine(mLastP, inP); } mLastP = inP; } virtual void MouseDown(const Point& inP) { mMouseIsDown = true; mLastP = inP; } virtual voi

안다고 생각하는 것과 아는것

처음으로 강의라는 것을 해봤습니다. :mrgreen: 친구의 부탁으로 총 네번에 걸쳐서 했는데 내용은 Design Principles (( SRP , OCP , LSP , DIP , ISP 를 소개했습니다.)) Design Patterns Refactoring C++ 이었습니다. 3번째 날까지는 나름 준비도 열심히 하고 해서 그럭저럭 한 것 같은데 네번째 날은 긴장이 풀어져서 그런지 듣는 분들을 별로 배려하지 못했다는 생각이 듭니다. :-| 네개의 주제중에 그나마 제일 자신 있는 주제였는데 말이죠. 각 강의에서는 주로 다음 책들의 내용을 소개하였습니다. Agile Software Development Design Pattern Explained Refactoring C++ Coding Standards 이번에 강의를 하면서 배운 점이 있다면 스스로 안다고 생각했던 것들 중 많은 것들이 실제로는 1) 전혀 모르고 있었거나 2) 다 이해하지 못하고 있었다는 사실입니다. ((GoF에 나온 패턴중에서도 Flyweigth, Memento같은 패턴들은 다시 보기 전까지 전혀 기억이 나질 않더군요. Bridge 패턴은 원래 이런거였나라는 생각이... :-| )) 혼자서 책을 읽는 것과 책의 내용을 누군가에게 가르치기 위해 읽는 것은 전혀 다른 일이더군요. 무엇이든 남에게 쉽게 설명할 수 있어야 비로소 알았다고 얘기할 수 있을 것 같습니다. 한동안은 다(多)독이 목표였으나 이번 강의 경험을 계기로 정독을 해치지 않는 정도의 다독으로 바꾸었습니다. 다독이 목표가 되었던 이유는 물론 너무나 좋은 책들이 많이 나왔기 때문입니다. 단순히 읽어야 될 책들이 많아진 것이 아니라 전체적으로 내용의 질이 매우 좋아진 것 같습니다. ((하지만 아직도 번역서의 경우에는 질이 형편없는 경우들이 종종 발견되더군요. 전 되도록 못하는 영어지만 전공 책은 원서로 읽는 편인데 얼마전 번역서를 읽다가 서문만 보고 집어 던진 책이 있으니 바로 소프트웨어 장인정신 이라는 책입

Textiler plugin test page

This post is for testing Textiler plugin . This plugin uses Textile engine (version 2.0.0). The sample text is come from Textile test page. (Note that the result will be vary according to your CSS options.) Supported wiki syntax Rendering result h2{color:green}. This is a title h3. This is a subhead p{color:red}. This is some text of dubious character. Isn't the use of "quotes" just lazy writing -- and theft of 'intellectual property' besides? I think the time has come to see a block quote. bq[fr]. This is a block quote. I'll admit it's not the most exciting block quote ever devised. Simple list: #{color:blue} one # two # three Multi-level list: # one ## aye ## bee ## see # two ## x ## y # three Mixed list: * Point one * Point two ## Step 1 ## Step 2 ## Step 3 * Point three ** Sub point 1 ** Sub point 2 Well, that went well. How about we insert an <a href="/" title="watch out">old-fashioned hypertext link</a>? Will the quo

Refactoring과 Optimization

이번 글에서는 refactoring이 어떻게 optimization에 도움을 주는지 알아보도록 하겠습니다. 아래 코드와 같이 극단적인 예를 사용해서 말이죠. :-) 다섯개의 함수가 있습니다. func1과 func3는 주어진 수까지의 짝수의 합을 출력하고 func2와 func4는 홀수의 합을 출력합니다. func5는 하나의 루프에서 둘 다를 계산한 후 출력하고요. void func1(int cnt) { int e_sum = 0; for (int i = 0; i < cnt; ++i) if (i % 2 == 0) e_sum += i; printf("%d\n", e_sum); } void func2(int cnt) { int o_sum = 0; for (int i = 0; i < cnt; ++i) if (i % 2 == 1) o_sum += i; printf("%d\n", o_sum); } void func3(int cnt) { // same as func1 int e_sum = 0; for (int i = 0; i < cnt; ++i) if (i % 2 == 0) e_sum += i; printf("%d\n", e_sum); } void func4(int cnt) { // same as func2 int o_sum = 0; for (int i = 0; i < cnt; ++i) if (i % 2 == 1) o_sum += i; printf("%d\n", o_sum); } void func5(int cnt) { int e_sum = 0; int o_sum = 0; for (int i = 0; i < cnt; ++i) { if (i % 2 == 0) e_sum += i; else o_sum += i; } printf("%d\n", e_sum); pri

std::map에 insert하기

얼마전 회사 동료가 refactoring한 코드를 열심히 revert하고 있어서 물어보니 다음과 같은 문제였습니다. 원래 코드와 refactoring한 코드는 다음과 같더군요. nvp[name] = value; // original code nvp.insert(make_pair(name, value)); // refactored 아시겠지만 위의 두 라인은 전혀 다른 기능을 하죠. C++03에 보면 각각 다음과 같이 설명되어 있습니다. 23.1.2/7 Associative containers a_uniq.insert(t): pair<iterator, bool> inserts t if and only if there is no element in the container with key equivalent to the key of t. The bool component of the returned pair indicates whether the insertion takes place and the iterator component of the pair points to the element with key equivalent to the key of t. 23.3.1.2/1 map element access [lib.map.access] T& operator[](const key_type& x); Returns: (*((insert(make_pair(x, T()))).first)).second. 원래 코드는 매번 새 값으로 이전 값을 overwrite했지만 새 코드는 이전에 키가 존재하면 새값으로 overwrite하지 않습니다. 따라서 원래 기능이 제대로 동작하지 않게 된것이죠. 그래서 물어봤죠. "왜 이렇게 했어?" "insert가 성능이 더 좋다 그래서 했지." :-? 사실 Fowler 아저씨는 Refactoring 책에서 refactoring은 성능을 optimizing하기 위한 것이 아니다라

Core Dump Pattern?

지난 주에 현장에 있던 시스템에서 core dump가 발생했습니다. :-( 제가 담당하는 부분은 아니어서 쳐다보지도 않고 있다가 오늘 뭔가 의심스러운게 있는지 확인하기 위해 불려갔지요. 사실 core dump를 열어 보지도 않아서 그냥 듣고만 있었는데 듣다 보니 원인이 뭔지는 짐작이 가더군요. 소멸자에서 core가 났는데 소멸자 코드안에는 아무 것도 없습니다. 그리고 call stack의 마지막 부분은 std::string에 있는 lock 관련 함수에서 났어요. 해당 pstack은 담당자의 말대로 다음과 같았습니다. 4~6 라인을 보시면 됩니다. ((c++filt를 적용한 pstack입니다.)) ((어제 밤에 CodeHighlighter 에 line number 출력 기능을 넣었어요. :-) )) ----------------- lwp# 153 / thread# 73 -------------------- ... --- called from signal handler with signal 11 (SIGSEGV) --- fe42b1d8 _mutex_lwp_lock (ef1860, fe44e000, 2ef1800, de55cc, ef1860, 40000013) + 20 00de55cc void std::basic_string ,std::allocator >::__unLink() (9e0070c, 1ec9fdb8, 1ec9fdb8, f7901774, 1daa6770, 1e1cbc80) + 4c 00dc3f64 BRISession::~BRISession() (9e003a0, 2df4c44, 88f2e0, 1, 0, 1e3799b8) + 124 00de75e4 __SLIP.DELETER__G (9e003a0, 1, f7901860, f790185c, 44, 4122640) + 4 ... 아마 core dump를 많이 보셨다면 이미 위의 말만으로도 원인을 짐작하실 수 있었을겁니다. 원인은 바로 double delete 죠. 한번 지워진 object에