2010년 4월 28일 수요일
수사법
놀고먹으면서 일 잘하는 방법 - 우리의 Agile 실험
"놀고먹으면서 일 잘하는 방법은 없을까?"
제가 입사한 후 근 9개월동안 알게 된 IT 현실은 다음과 같습니다.
1) 개발자는 노동강도가 세다. 그들에겐 밤도, 주말도 존재하지 않는다. 왜냐면...
2) 대부분의 개발자들의 업무가 과중하고 업무를 처리하는 방식이 비 효율적이기 때문이다.
(주 업무의 70% 이상이 유지보수 = 버그잡기 이고 신규개발에 의한 과중은 얼마 안되었습니다.)
3) 개발자들도 이 사실을 알고있다.
4) 하지만 여러가지 이유를 들어 섣불리 개선하지 못하고 있다.
5) 그리고 타인과 조직이 잘못되어 있다고 한탄한다.
약간 다른 이야기지만, 저는 몇년전부터 "효율적으로 일하는방법 = 놀면서 일하는 방법"을 고민해 왔습니다.
사실 이러한 저의 고민은 저의 학창시절의 고민에서 시작되었습니다.
저의 학창시절 소원은 1등을 해보는 것이었습니다. 저는 5시간만 자고 공부만 했지만 항상 8시간 이상 자고 친구들과 자주 스타크래프트를 하는 1등이 항상 부러웠습니다. 시험에서의 퍼포먼스와 삶에서의 퍼포먼스 양쪽을 다 잡고있는 그가 매우 부럽고 시기했었습니다. 그리고 저는 "천재"가 아니기 때문에 그러한 것이 불가능할 것이다라고 단정지었었죠.
하지만 대학들어와도 바로 옆 친구가 시험기간동안 게임을 즐기면서도 항상 평점은 4.0 이상 이었던것에 비해, 저는 딱히 노는것도 없이 밤새는데 3.5를 간신히 넘는 상황이 발생하자 그동안 제가 해온 공부 = 일의 방식이 매우 비 합리적이고 아둔하지 않았나 생각하게 되었습니다.
무엇에 차이가 있나 저는 그때부터 잘하는 녀석들을 붙잡고 물어보고 저와 비교하는 일을 시작했습니다. 그 과정은 매우 괴로웠습니다. "나도 이렇게 진작 했다면 좀더 나았을텐데" 라는 생각과 "내가 멍청했다." 라는 자괴감 때문에 많이 괴로웠거든요. 무조건 시간을 오래 쏟는다고 성능이 나아지지 않는것인데 저는 그저 인내하고 파기만 하면 모든게 해결될줄 알았던 것입니다.
아래의 링크는 유명인사들이 왜 다른 평범한 사람들과 같은 시간을 보내면서도 탁월한 성과를 올릴수 있는가에 대한 이야기입니다.
http://lifedev.net/2008/03/10-ways-historys-finest-kept-focused-at-work/
정리하자면, 그들은 자신이 일하는 방식에 대한 그들만의 원칙이 있고. 결코 오래 엉덩이를 붙이고 있는것이 능사가 아니라는 것을 알고 있었으며 짧은시간동안 최대한 문제에 집중하고 나머지 시간은 몸과 뇌를 놀리는데 썼다는 것입니다.
역시 학창시절에 저보다 우월한 녀석들은 "모든 일을 줄기차게 많이 하는것" 보다 "중요한 일에 단시간 집중하여 탁월한 성과를 내는것"을 선호하고, 각자 그렇게 하는 자기만의 최적화된 방법을 연구하고 체득하고 있었다는 겁니다.
결국, "놀면서 일 잘하는 방법에 대한 패턴"은 존재했다고 생각합니다.
그래서 저는 저만의 방법을 찾아 연구했고 이를 간단히 실험해 보았습니다. 공부의 원칙과 시간을 세우고 제가 잘하는 "그림/동영상 기억법"을 이용해서 "숲에서 나무로 훓어 내려가는"공부를 해 보았습니다. 그리고 공부시간 외의 시간은 음악을 듣고 군것질을 하고 잡담을 하고 만화책을 보며 게임을 했습니다. 이전에 시험기간동안 공부에만 투자한 시간이 하루 10시간 이라면 이를 5시간까지 줄였습니다.
그 결과는 생각 외였습니다. 저는 이전보다 많은 시간을 공부에 할애하지 않아도 많은 양을 기억할수 있었고 (일부는 지금도 기억합니다.) 성적도 0.3포인트 이상 더 잘 나왔던 것입니다.
다시 회사 이야기로 돌아가서, 수많은 개발자들이 오늘도 죽음의 행진을 하고 있습니다. 아직 초년때에 이 죽음의 대열에 막 발을 담그고 "정말 대한민국에서의 회사생활과 IT엔 답이 없는가?" 하며 괴로워 하고 있을때 한 상사분께서 다음과 같은 조언을 몇가지 해주었었습니다.
1) 주요이슈(issue)는 정리되어야 한다. (잠재적인것도 포함)
2) 문제는 잘게 쪼개어야 한다.
3) 히스토리는 기록되어야 한다.
4) (상사가 보기에)중요한 몇가지에 우선 집중하라.
5) 문서와 코딩은 같이 가야한다.
6) 설계와 코드는 자주 리뷰되어야 한다.
7) 설계는 절대 폼잡지 말고 실용적이어야 한다.
8) 프로세스를 세우고 이에 맞추어 일하라.
9) 일 할땐 하되, 자주 쉬어라.
10) 개선할것은 시간을 들여서라도 자주 개선하고
11) 위 모든것은 보고하여 실적화가 가능한 형태로 준비하라.
저는 이러한 조언이 그분의 직장생활 10년동안에 나온 귀중한 경험이자 하나의 패턴이라고 생각했습니다. 하지만 그 상사분도 이러한 것들을 제대로 실천하고 계시지는 못하고 계셨습니다. 그래서 저는 여기에 아래와 같은 약간의 변형을 가하고 이를 구체적으로 패턴화 하고 실천하는 작업에 들어갔습니다.
12) 모든 업무는 파이프라인처럼 병렬적으로 진행하도록 한다.
(신속한 태스크 스위칭을 통해서)
저는 스프레드쉬트로 각 업무에 맞는 문서를 만들었고, 오늘의 프로세스를 세워 이를 적어두고 하나씩 실천했습니다. 처음에는 상당히 귀찮을 뿐더러, 번거롭기 그지 없었지만. 이것이 몇달이상 쌓이게 되자 위 11가지 사실을 어느정도 만족시킬수 있는 자료가 되고, 그 자료를 근거로 RISK를 예측하고, 문제에 당황하지 않으며, 한번 해결한 문제가 두번 열리지 않게 하고 남는시간에 중요한 문제에 포커스 하며, 결국 단위시간동안 이전보다 좀더 많은 일을 해결할 수 있음을 알게 되었습니다.
통계를 내본결과. 적용전에 하루 3개 정도의 업무를 해결했었으나 이후 5개 이상 최대 하루 10개까지 완료했다는 사실을 발견했기 때문입니다. (이를 가능하게 해준 Franklyn Planner에게 감사~:) )
결국 개발자들이 겪는 수많은 문제들이 정말 IT란 것이 일이 단순히 많아서가 아니라, 과거에 처리한 Bug가 다시 reopen되거나 대충한 설계와 구현때문에 요구사항이 바뀔때 대응을 못하고, 정작 이러한 모든 일에 대한 전체적인 정리된 문서나 설계서가 없기 때문에 문제원인 파악과 대책마련에 시간이 걸린다는 것을 깨닭게 되었습니다. (결국 인간의 기억력에는 한계가 있는데, 많이들 이를 간과합니다.)
문제가 생기지 않는다는 것은, 그 문제를 끊임없이 관리하기 때문이라는 사실도요.
저는 주로 유지보수일을 하고 있었기 때문에, 신규개발만 하는 분들에게 있어서는 별로 공감이 안갈수도 있겠습니다. 그래서 저는 신규개발에도 이러한 "패턴"을 발견하고 여기서 프로세스를 만들어 이를 실천함으로서 현재와 미래의 퍼포먼스와 RISK 안전성을 높이는 작업 이 가능한지 실험해 보기로 하였습니다. 그래서 몇가지 프로세스를 만들었고 이를 실험하여 "우리의 Agile 실험" 이라는 태그를 붙여 블로그에 포스팅 하려 합니다.
그리고 저 뿐만 아니라 저 주변의 사람들도 이러한 실험을 통해서 개발에 대한 새로운 눈을 뜰수 있게 되길 소망합니다.
2010년 4월 27일 화요일
객체지향의 아름다움
[객체지향의 아름다움]
세상의 만물은 독립된 실체(엔티티)들과 이들 사이의 수평적인 관계로 구성되어 있다.
이들 만물들 사이에는 종적(수직적)인 관계를 가지고 있는 것이 아니라 횡적(수평적)인 관계에 그 바탕을 두고있다. 사람과 나무의 관계가 종적 관계가 아닌 횡적인 관계이며 생명체의 세포들 사이의 관계도 수평적인 관계이다. 세포들은 서로의 내부에는 전혀 신경 쓰지 않고 오직 표준화된 인터페이스를 통해서만
교류하며, 서로의 내부 구조는 가려 주어 완전히 캡슐화 되어 있다고 한다. 이러한 모습을 통해 모든 세포들이 자율적으로 움직이고 있다. 객체 지향은 하향식에서 나타나는 수직적인 관계가 아닌 평등에 기초한 수평적인 관계로의 변화를 의미한다.
객체 지향은 객체 각자가 독립적, 자율적이며 어느 누구에게도 일방적인 강요 없이 각자의 주어진 임무를 수행한다. 이러한 관점에서 보면 우리 주변의 자연이나 인체구조는 대단히 객체지향적이다. 사람 몸을 구성하는 세포들 사이의 관계, 장기들 사이의 관계도 수직적인 관계가 아니라 평등에 기초한 수평적인 관계이며, 이를 통해 우리 몸의 조화와 균형을 이루어 나간다. 또한 자연에 있는 세상 만물들은 독립적으로
존재하며 필요에 따라 관계를 맺고 있다.
자연 속의 개미나 벌을 보자. 그들의 일하는 모습을 보면 수직적인 구조나 감독 없이 일하는 모습을 볼 수 있다. 스스로들 알아서 능동적으로 찾아서 일을 한다. 아마도 개미나 벌들은 유전적으로 이러한 능력을 갖고 태어난 모양이다. 그들 사이에는 일방적으로 지배하는 수직적인 관계가 없고, 서로 돕고 전체를 위하여 최선을 다하는 오직 수평적인 관계만이 존재한다. 그들은 서로 도우며 조화를 이루어 나간다. 자연에 속한 모든 객체들은 서로 독립성을 유지하며, 관계를 가지고 필요에 따라 서로 교류한다. 자연이
만들어진 모습을 자세히 들여다보면 객체지향적인 개발기법이 적용된 결과물이라는 것을 파악할 수 있으며, 자연은 이들 구성원들 사이의 수평적인 관계를 통해 조화를 이루어 갈 수 있도록 만들어진 훌륭한 걸작품이다.
생물학적인 관점에서도 객체들 사이의 강요나 지배가 없는 조화와 질서가 생명체의 본질인 것처럼 인간이 만드는 시스템 개발에 있어서도 이러한 자연의 섭리가 적용된다. 소프트웨어도 다른 시스템 또는 생명체와 마찬가지로 구성 요소들이 서로 독립적인 기능을 수행하며 서로 보완적인 관계를 유지하고 균형과 조화를 이룰 때 가장 이상적인 모습을 갖게 된다. 이는 시스템의 구성요소들이 상하관계를 이루는 것이 아니라 오히려 대등 병립 관계를 가진다는 점에서, 우리에게 익숙한 기존의 구조적, 하향식 구조와는
전연 다른 모습을 띄게 된다.
객체지향은 객체에 대한 자율성과 철저한 업무분담을 원칙으로 한다. 객체지향은 시스템의 조직과 기능을 구성 요소로 보는 것이 아니라 시스템을 구성하고 있는 객체를 기본 요소로 인식한다. 시스템의 각 구성 요소인 객체가 자신의 기능을 독립적으로 수행하고, 객체들 사이의 조화와 균형이 이루어질 수 있도록
설계될 때 시스템은 이상적인 모습을 갖는다.
시스템을 구성하고 있는 객체들이 독립적, 주도적으로 움직이며, 이러한 성숙된 객체들 사이에서 원숙한 관계가 맺어질 때 진정한 객체지향 사회라 할 수 있다. 미국의 경우 책임 있는 객체들을 생성하려는 노력을 해 나가고 있는 객체 지향적 사회라고 볼 수 있으나, 사람들 사이의 원숙한 관계를 이루어나가는 데 있어서는 아직도 객체 지향 사회의 초보적인 단계라 할 수 있다.
반면 우리 사회는 상대적으로 구조적인 틀을 바탕으로 하고 있으며, 객체 지향화가 덜 되어 있는 상황에서 객체보다는 관계를 더욱 중요시하여 왔다. 그러나 이러한 구조적인 틀로는 빠른 변화를 요구하는 이 시대에 쉽게 대처하고 적응할 수 있는 힘을 배양하기 어렵다. 구조적인 틀에서는 개인의 자율성과 독립성이 극대화되기 어렵다. 사람은 누구나 다르다. 남이 나와 다르고 내가 남과 다를 수 있는 권리를 인정해 주어야 하지만 그러하지 못했던 것이 사실이다. 우리 사회도 각 개인의 창의력과 자율성이 극대화되는 객체 지향사회로 변할 때보다 많은 사람들이 행복해지고 아름다워 질 수 있을 것이다.
하향식의 구조적인 접근은 단기적인 효과를 목표로 하는 반면, 객체 지향적 접근은 장기적인 관점에서 이상적이라 할 수 있다. 이러한 객체 지향 구조는 수직적인 관계보다 효율을 극대화시킬 수 있는 장점이 있으며, 독립적으로 움직이기 때문에 변화에 적응하기 쉽게 해주어 어울림, 헤어짐 등 인간의 삶에서 나타나는 변화에 조화롭게 작용하고 균형을 찾고 순응할 수 있는 단초를 제공한다. 한편 구조적(structured)인 틀은 하향식의 체계를 가지고 있으며, 기능을 수행하기 위해 단순하고 빠르게 만들어 질 수 있다는 장점을가지고 있다. 반대로 객체지향적인 틀은 상향식의 개념을 기초로 하고 있으며, 이러한 시스템을 만들려면 시간이 걸리고 많은 에너지를 필요로 한다. 우리나라의 옛 정치구조인 왕권 중심적인 틀은 하향식의 구조적인 모습을 가지고 있다. 요사이 확산되고 있는 지방자치 제도 정치의 객체지향화이며, 이러한 객체지향적인 틀을 마련하는 데는 많은 노하우(know-how)를 필요로 한다. 우리가 겪는 지방자치제의 시행착오도 그 예라 할 수 있다.
가정에서도 객체 지향화가 이루어지려면 아버지는 가족구성원에게 많은 것을 양보하고 그들의 요구를 귀담아 들어야 한다. 이를 위해 가족들 사이의 관계가 새롭게 정의되어야 하고 이 과정에서 겪는 시행착오를 감수해야만 한다. 우리의 전통을 생각해 보면 자식들에게 강요하지 않고 지배하지 않는 부모와 자식 사이의 관계가 그리 쉬운 일이 아니다. 요사이 「고개 숙인 아버지」의 모습도 가정의 구조가 객체 지향으로 옮겨가며, 패러다임의 이동으로 겪는 혼동이 아닌가 생각된다.
인생을 살아오며 자연스러운 것보다 아름다운 것은 없다는 생각이 든다. 자연스러운 것이 아름다운 것은 객체 지향적이라는 것에서 그 이유를 찾을 수 있을 것 같다. 자연적인 것은 부드러우며 일반적으로 인간이 만든 인공적인 것보다 변화에 쉽게 적응할 수 있는 힘을 가지고 있다. 객체 지향 접근방법은 인위적인 것이 아닌 자연스러운 접근 방법이며, 우리 주변, 특히 가정, 회사, 국가 등 여러 분야에도 적용해 볼 만하다. 조직의 최소 단위라 할 수 있는 가정에서도 객체 지향화가 이루어지면 가족 모두가 행복을 누릴 수
있는 확률이 높아지며, 구성원 모두가 자신의 기량을 최대한 발휘할 수 있다. 미래의 사회는 구성원들 사이에 수직적인 관계가 아니라 수평적인 관계에 기초할 것이다.
조물주가 만든(엔지니어링한)제품인(?)사람이나 자연을 보면 객체 지향으로 만들어진 훌륭한 시스템이며 가히 걸작품이라 할 만하다. 현재 인간은 조물주가 만든 사람과 동물의 설계도면인 염색체 구조를 밝혀 내어 복제를 하기에 이르렀다. 시간이 지나면 조물주가 만든 각종 제품의 요구사항까지 규명하여, 완전한 역공학을 실현할 시대가 올지도 모른다. 다음의 질문들은 우둔하거나 인간으로서 주제넘은 질문일까? 조물주는 공학에서 요구되는 분석,설계, 구현 등 체계적인 엔지니어링과정을 거쳐 사람을 만들었을까?
사람을 설계하기 전에 요구사항을 완벽히 정의하였을까? 사람을 만들 때 요구사항을 미리 완벽히 정의하고 하향식으로 만들었을까? 필자의 생각으로는 조물주가 이렇게 사람이라는 훌륭한 시스템을 만든 것을 보면 미리 완벽히 요구사항을 정의하고 차곡차곡 엔지니어링한 것이 틀림없어 보인다. 조물주의 엔지니어링 기법을 밝히는 것은 대단히 위험스럽고 신비스러운 일일 것이다.
참고문헌 : 성공적인 소프트웨어 개발 기법 - 윤청 저
저의 객체지향 개념은 이렇습니다. = 책임과 소통을 명확히 하고 서로 느슨히 협업하게 하라
이 글은 스프링노트에서 작성되었습니다.
2010년 4월 26일 월요일
세상을 바꿀수 있는 작은 모임
김창준님 블로그 글에서 AC3 관련하여 다음의 내용 발췌 ( http://agile.egloos.com/5302614 )
Never doubt that a small group of thoughtful people could change the world. Indeed, it's the only thing that ever has.
사려깊은 사람들로 구성된 작은 모임이 세상을 바꿀 수 있다는 것을 결코 의심하지 마세요. 사실 지금까지 세상을 바꿀 수 있었던 것은 그런 모임들 뿐이었어요. --마가렛 미드(Margaret Mead)
요즘들어 이런 모임에 참가하거나 또는 만들고 싶다는 생각을 많이 합니다...
스스로 발전하기엔 한계가 크다는 것을 느끼기에...
여럿이서 발전할수 있는 작은 그룹/기회에 소속될수 있었으면 합니다.
2010년 4월 23일 금요일
2010년 4월 19일 월요일
홍대 잇초메(一丁目)
푸우가 먹은 소유라멘. 이건 좀 짰어요.
오빠가 먹은 돈까스 덮밥. 돈까스가 맛있고 육수도 적당한 양으로 있었습니다. 너무 많지도 않고 적지도 않고 간도 알맞았어요.
돈까스의 바삭바삭함~
아이스크림 튀김도 먹었어요. 아이스크림 튀김은 처음인지라 신기했다는.. 모양도 좀 신기 ㅋㅋ
생각보다 맛있더라구요. 바삭한 튀김 옷에 달콤한 아이스크림이 베어서 달콤하고 따뜻한 과자를 먹는 느낌이었습니다. 근데 두조각 먹은 후에는 느끼했어요. 조금만 먹는게 맛있는 음식이었습니다. ^^
Photo Slider
2010년 4월 12일 월요일
인터페이스 이야기
1) 인터페이스는 무엇을 위한 것인가
인터페이스(interface, 문화어: 대면부, 결합부) 또는 접속기는 사물 간 또는 사물과 인간 간의 의사소통이 가능하도록 일시적 혹은 영속적인 접근을 목적으로 ...
B가 D를 public 상속 하면 이는 is-a 관계로서 B에서 되는 것은 모두 D에서도 되어야 한다.
2) 인터페이스는 언제 어떻게 써야 할까
제가 처음 인터페이스에 대해서 너무 궁금해서 여기저기 찾아 보았지만 명확한게 없어
제 코드 멘토였던 분에게 질문한적이 있었습니다. 그분은 다른말은 안하고 코딩으로 직접 알려 주셨던 기억이 납니다. 아래는 그 내용을 제가 기억을 살려 재구성한 것입니다.
옛날옛날에, 웹에서 휴대폰 문자 메세지를 보내는 서비스를 하던 회사가 있었는데 이 회사의 메세징 라이브러리는 다음과 같이 구성되어 있었다.
그리고 이를 사용하는 메인코드는 다음과 같이 구성되어 있었다.
[code csharp]
public void Main(string ISPName, int phoneNo, string message)
{
if (ISPName == "SKT")
{
SKTSMSManager manager = new SKTSMSManager();
manager.InitSKT();
manager.SendSKT(phoneNo, message);
manager.CloseSKT();
}
else if(ISPName == "KTF")
{
KTFSMSManager manager = new KTFSMSManager();
manager.InitKTF();
manager.SendKTF(phoneNo, message);
manager.CloseKTF();
}
else if(ISPName == "LGT")
{
LGTSMSManager manager = new LGTSMSManager();
manager.InitLGT();
manager.SendLGT(phoneNo, message);
manager.CloseLGT();
}
}
[/code]
처음에는 이러한 방식이 별 문제가 없었다. 하지만 시간이 지남에 따라 SMS 뿐만 아니라, MMS 또한 지원해야만 하게되었다. 통신사는 3개지만, 구현해야 하는 클래스는 6개로 늘어나게 되었다.
그리고 위 메인코드의 분기문또한 2배로 늘어나게 되었다. 이후 통신사 서비스, 요금제마다 또 방식이 바뀌게 되어 결국 이에 맞추어 새로운 클래스와 분기문 코드를 만들어야만 했다. 분기문이 길어지다보니 코드들이 서로 꼬이는 부분이 늘어나 버그가 급증하고 읽기도 어렵게 되었다. 사장은 코드중복을 줄이거나 버그를 열심히 잡으려 노력했지만 늘어나는 클래스와 분기문을 주체하기 힘들었다. 게다가 클래스들이 동작하는 방식들이 각 통신사들이 서비스마다 메세징을 지원하는 방식에 따라 미묘하게 달라 이들을 추상화하거나 통합할 엄두를 내지 못하고 있었다. (이런일은 현업에서 매우 비일비재합니다.)
그때 혜성처럼 한 개발자가 나타났다. 그는 재야의 숨은 고수로 불리던 이XX 였다.
그는 3개월 이라는 시간만에 이 복잡한 클래스와 분기문들을 싹다 정리하고 수천만원을 챙기고 다시 재야로 사라졌다. 그가 사용한 방법은 무엇이었을까?
그는 인테페이스를 사용했던 것이었다.
각 클래스마다 공통으로 수행해야 하는 시퀸스를 담은 메소드들 Init(), Send(), Close()를 인터페이스로 추상화 하고 모든 메세징 클래스들이 이를 상속받게 한다. 이렇게 하면 새 메세징 클래스가 만들어 지더라도 IMessenger라는 인터페이스에서 요구하는 메소드들을 구현해야 되므로, 모든 클래스가 동일한 방식으로 접근하고 동작할수 있도록 강제할수 있다.
따라서, 메인에서 분기문을 없애고 직접 해당 메세징 클래스 객체를 넘기도록 다음과 같이 수정할수있다. 메세징 클래스에 접근하는 방법을 하나로 통일한 것이다. 결국 아래 메인 코드는 메세징 클래스가 늘어나거나 줄어들거나 상관없이 일관된 동작을 수행한다.
[code csharp]
public void Main(IMessenger messenger, int phoneNo, string message)
{
IMessenger manager = messenger;
manager.Init();
manager.Send(phoneNo, message);
manager.Close();
}
[/code]
여기에 약간의 추상화를 더하여 추상 베이스 클래스를 만들수 있다. 하지만 이는 세부적인 구현과 관계된 문제 : 서비스 방식이나, 통신사 규약이냐는 차이점에 따라 달라질수 있기 때문에 이번 화에서 이야기하려는 범위를 벗어남으로 "추상화와 추상 클래스 이야기"에서 다루도록 합시다...
어쨌든, 인터페이스를 통해서 서로다른 것들에 일관된 접근 방법을 제시함으로서 우리는 아래의 목적을 달성할수 있습니다.
1) 여러 클래스 간의 일관된 구현/확장 강제
2) 여러 클래스를 일관되게 Access 하고 싶을때
2010년 4월 8일 목요일
Bottom-up/Top-down 설계
'신의 한줄'을 위한 생각 - Bottom-up/Top-down
소프트웨어 개발자의 세계에 있어서,
설계와 코딩은 서로 떼놓을수 없는 정말 중요한 작업들입니다.
좋은 설계는 코딩을 편하게 하고, 좋은 코딩은 설계가 유연해지도록 돕습니다.
하지만 다들 코딩은 어떻게든 하겠는데, 설계는 어떻게 해야 할지 몰라서 헤매는 경우가 많습니다.
시중에 나온 책들도 코딩을 잘하는 방법(테크닉)을 가르쳐 줄뿐이지, "설계는 이것이다" 라고
딱히 이야기해주지 않습니다. 그나마 전산학과에선 설계를 가르친다고는 하나, 이들 학교에서
배우는 내용도 매우 두리뭉실할 뿐, 현실에서는 거의 적용하기 힘든때가 많습니다.
그렇다면 우리는 설계를 어떻게 시작해야 좋을까요?
저뿐만 아니라 많은 개발자들이 여기에 대해서 수없이 고민해 왔습니다.
그리고 각자 자신만의 결론에 도달하게 되죠, 그것이 옳던 아니던 간에.
(사실 맞고 틀린것은 없습니다, 자기가 좋아하는 방법이 최선인 것입니다.)
제가 생각하는 설계는 2 가지가 있습니다.
(여기선 이전단계인 요구사항 분석이 끝났다고 칩시다.)
하나는 정말 설계다운 Top-Down방식
다른 하나는 부지런한 리팩토링에 따른 Bottom-Up 방식
참고로 아래 예시를 설명함에 있어,
저는 구현과 설계를 병행한다는 것을 고려하시기 바랍니다.
Top-Down방식
Top-Down방식은 두리뭉실한 것을 구체적으로 만들어 나가는 것입니다.
이전에 완료된 요구사항중 공통되는 핵심 기능만을 우선적으로 객체로 모델링을 합니다.
여기서는 개발자라면 많이 사용하는 버튼, 콤보박스, 리스트 등등의 UI Control이
어떻게 설계될수 있는가에 대해서 이야기하도록 하겠습니다.
우선 "화면에 보여야 한다"라는 요구사항을 만족시키기 위해서 Visual 이라는 객체를 하나 만들었습니다.
이 Visual은 Draw() 라는 메소드가 있어, 스스로 화면에 그려질수 있습니다.
그리고 여기서 "마우스로 조작할수 있어야 한다." 라는 요구사항을 만족시키기 위해서 아래와 같이
Control 이라는 객체를 만들었습니다.
마우스로 조작하려면, 화면에 보여야 하기 때문에 이 Control은 Visual의 특성을 가져야 하므로,
상속을 이용하여 다음과 같이 표현합니다.
여기서 좀더 구체적인 요구사항 "마우스로 클릭하면 실행되어야 한다." 를 만족시키기 위해서
Button을 만들었습니다.
Button은 역시 마우스로 조작되어야 한다는 앞의 요구사항을 만족해야 하기 때문에 Control의
특성을 지녀야 하므로, Control을 상속 받습니다.
그런데 Button으로 만족되지 않는 다른 요구사항 : "클릭하면 다시 클릭될 때까지 눌린 상태(체크)를
유지해야 한다." 가 있습니다. 버튼은 클릭하면 뭘 수행하는 기능만 있기 때문에, 이때쯤 새로운
객체를 하나 더 디자인 합니다. 이를 CheckBox 라 하겠습니다. 역시 화면에 보이고, 마우스로
조작되어야 하기 때문에 Control을 상속 받습니다.
여기에 또 다른 요구사항 : "스크롤 해서 항목을 선택할수 있어야 한다." 가 있습니다.
이는 Button, CheckBox 모두와 서로 안맞는 요구사항이므로, Button이나 CheckBox를 상속받는
행위를 하면 안됩니다.(서로 맞는지 아닌지 두리뭉실해서 확신이 안서면 문제에 대한 이해나
요구사항 분석이 잘못된것입니다. 좀더 자세히 해놓을 필요가 있습니다.) 보통 초반에 잘 설계해놓고
마구 상속하고 이게 감당이 안되서 overriding 하여 설계를 망치는 경우가 많습니다. 조심해야 합니다.
이러한 실수를 막고자 상속은 3단계 이상 하지말것,
다중 상속 금지 등의 "경험적인 Rule"이 생겨난 것입니다.
결국, Button과 CheckBox 모두와도 서로 요구사항이 맞지 않지만, Control이 만족하는 요구사항
"화면에 그려지고, 마우스로 조작될수 있다."라는 조건을 맞추기 위해서 ListBox라는 객체를 만들어
Control을 상속받습니다.
이렇게 하여 하나의 Tree 모양의 설계가 일단 완료되었습니다.
더 복잡하게 하면 머리아프고 쓰기도 힘드니, 여기서 더 자세히 나가지는 않겠습니다.
이 방식의 경우 추상적인 곳에서 구체적인 곳으로 나아가면서 설계가 이루어지기 때문에
Top-Down = Bottom까지 내려가야 실제 사용할수 있는 구체적인 컴포넌트가 나타나게 됩니다.
개발자 입장에서는 차근차근 뭔가 두리뭉실한게 명확해진다, 뭔가 이루어진다는 느낌이지만,
빨리 눈에 보이거나 뭔가 나오는게 없어 성격급한 관리자들이 싫어하는? 방법이기도 합니다.
Bottom-up방식
이번엔 Bottom-up 방식의 설계 기법을 보여 드리겠습니다.
역시 위와 마찬가지로 UI Framework 구조를 만들어 나가는 과정입니다.
일단 Bottom-up에서는 가장 구체적인 요구사항을 모두 만족하는 객체를 먼저 만듧니다.
(일단 닥치고 만듭니다.)
- Button의 경우
- 화면에보이고,
- 마우스로 조작 가능하며
- 클릭할수 있다
는 요구사항을 모두 구현합니다.
- CheckBox의 경우
- 화면에보이고,
- 마우스로 조작 가능하며,
- 클릭하면 다시 클릭될 때까지 눌린 상태(체크)를 유지해야 한다.
는 요구사항을 모두 구현합니다.
- ListBox의 경우
- 화면에보이고,
- 마우스로 조작 가능하며,
- 스크롤 해서 항목을 선택할수 있어야 한다.
는 요구사항을 모두 구현합니다.
여기서 주의할 것은, 각 기능을 구현하는데 객체 내에 위 요구사항을 만족하는 기능들의 응집도가
높으면 안된다는 것입니다. 응집도가 높으면 리팩토링하기가 너무 힘들고, 한다고 해도 제대로
부작용(Side-Effect)없이 동작한다고 보장하기 힘듭니다.
디미터 룰(실용주의 프로그래머(인사이트) 참고)을 철저하게 지키던가 아니면 내부 구현을 최대한
간단하게 한다던지 각자의 방법으로 잘 정리해 합니다.
어쨌든 구현이 끝나고 각 객체의 리팩토링이 끝나면, 위 요구사항중에서 공통되는 요구사항
"마우스로 조작 가능하다" 를 뽑아내어 Control이라는 위 3개 요소를 대표할수 있는 좀더
두리뭉실한 이름의 객체로 만든후, 이 요구사항과 관계된 Code중 공통되는 부분을 뽑아
이 Control 안에 넣습니다. 그리고 3개 컴포넌트가 이 Control을 상속받게 합니다.
역시 마찬가지로 "화면에 보이다" 라는 공통되는 요구사항을 뽑아 Visual이라는 객체로 표현후
3개 객체에서 화면그리는데 공통되는 Code를 뽑아 내어 집어 넣습니다.
그리고 3개 Control이 이 Visual을 상속받게 합니다.
여기서 C++등의 언어에서는 이렇게 한 객체가 2개의 상위 객체를 상속받게 허용합니다.
이를 "다중상속"이라고 부릅니다. 하지만 앞에서도 이야기 했듯이, 이 다중상속 때문에
설계 및 디버깅 전체가 점점 더 어려워지는 문제가 있어 C#등 최신 언어들에서는 다중상속을
지원하지 않습니다.
(다중상속의 폐해에 대해서는 Scott Myers의 Effective C++ 등의 저서를 참고하세요)
저는 C#으로 먹고살기 때문에 다중상속이 가능하지 않습니다.
따라서 Visual과 Control이 같은 Level 선상에 놓여야 하는지 고민해야 합니다.
결국, Control도 화면에 보여야 하기 때문에, 좀더 근본적인 요구사항을 만족시키는 Visual을
최상위 객체로 둡니다. Control은 Visual을 상속받게 됩니다.
어떻습니까? 앞과 마찬가지로, 결국 하나의 Tree 모양이 완성됩니다.
내부의 구현은 Top-Down과 다를수 있지만 외부에서 보았을때엔 동일한 구조입니다.
여기서 "부지런한" 이라는 수식어를 붙인 이유는, 이러한 Bottom-up 설계가
계속 중복된 요소를 잡아내고, 이를 추상화 시키며 정리해 나가는 리팩토링 과정과 함께 하기 때문에
Top-Down보다 매우 바쁘게 움직여야 한다는 것입니다. 마치 정원사가 계속 정원을 다듬듯이
그렇게 다듬어 주어야 차츰차츰 좋은 설계가 나타나는 것입니다.
하지만, 이렇게 힘이 많이 드는 대신에 Top-Down 방식에서 일어나기 쉬운
"불필요한 추상화/구체화"가 덜하다는 장점이 있습니다.
실전에선 어떻게 하나?
위에서는 예로 설명하고자 두 방법을 분명히 구분지으려 노력했지만,
실전에서는 두 방법이 서로 보완하면서 번갈아 이용됩니다. 서로 장단점을 보완해 줄수 있기 때문이죠.
예를들어, Top-Down으로 만든 구조에서 다음과 같은 새로운 요구사항이 들어왔다고 합시다.
"클릭할수 있지만 클릭하면 푹 들어가 다시 클릭될 때까지 나오지 않는다."
뭔가 애매합니다. 클릭도 되고, 푹 들어가서 또 누를때까지 나오지 않는다....
위에서 이야기한 Button과 CheckBox의 성질을 모두 가지고 있지만, 어느것 하나의 성질도
가지고 있지 않은 상황입니다. 아래와 같이 교집합적인 성질을 지니고 있는 것처럼 보입니다.
그럼 Top-Down적으로 생각해서, Control을 상속밭는, 완전히 새로운 것을 하나 더 만들어야 할까요?
당장은 이게 가장 쉬운 방법처럼 보입니다. 하지만 이런 식으로 자꾸자꾸 새로운 것을 만들면
아래처럼 잔가지가 수십개나 달리는 = 중복되는 코드가 수십개나 되는 지저분한 구조가 되어
같은 기능을 수정할 때마다 여러 클래스에 있는 기능을 다 수정해줘야 하는 문제가 생깁니다.
경험상 제일 귀찮으며, 손이 많이가고, 제일 야근을 심하게 하게 만드는 요소이죠.
여기서, Bottom-up적인 생각이 적용될수 있습니다.
Bottom-up적인 생각이란, 앞에서 말했듯이 공통되는 부분을 집어내어
이를 묶는 좀더 대표적인 객체를 만드는 = 한단계 추상화 시키는 것입니다.
여기서 공통되는 부분은
1 클릭(Click)
2 토글(Toggle) - 클릭하면 푹 들어가 다시 클릭될 때까지 나오지 않는다.
입니다.
앞에서 말했듯이 "다중상속"은 안 쓴다고 했습니다.
따라서 공통되는 Toggle 기능(또는 특성)만을 위한 객체를 따로 만들어서 Control과 함께 상속받게
할수는 없습니다. 하지만 이 공통되는 특성을 두 객체에 강조하고 싶습니다.
이럴때 쓰는게 Interface 입니다. 공통되는 성질을 이용하기 위한 Interface : IToggle을 만들어
CheckBox와 새로 만들 객체 (여기선 요구사항대로 위 1, 2 성질을 모두 표현하는 ToogleButton
이라고 이름 짓습니다.)가 상속받게 합니다. 그리고 IToggle이 요구하는 구현사항을 모두 구현합니다.
만일 ToggleButton의 IToggle구현과 CheckBox의 IToggle 구현이 동일하고, 여기서도 중복을
없애고 싶다면 IToggle을 구현하는 별도의 상위 객체 (예를들어, ToggledControl 등)을 CheckBox와
ToggleButton의 상위 클래스로 두면 되겠지만, 이럴경우 Button의 Click 특성까지 별도 상위 클래스를
두면 ToggledButton은 다중상속이 되어 C# 에선 구현이 안됩니다. 결국 Click과 Toggle 둘중 더
중요한 특성을 상위 클래스로 뽑고, 다른것은 인터페이스로 뽑아 유형만 구현하도록 합니다.
이 예시에서는 Click이 Toggle보다 좀더 중요하며, 근본적인 특성이라고 보고 설계하였습니다.
따라서 ToggleButton은 Button의 공통 특성인 Click 기능을 가진 ButtonBase 라는
상위 추상 클래스를 하나 만들어, 이를 상속받게 합니다.
ButtonBase가 추상 클래스인 이유는 클래스 자체로는 인스턴스화할 필요가 없이
Click 에 대한 공통 구현만 제공하며,
하위 클래스에서 재정의 하여 사용하기 용이하도록 하기 위함입니다.
(ButtonBase가 추상 클래스이기 때문에, 이 위의 상위 클래스 모두 추상 클래스여야 합니다.)
이제 Click의 특성을 가진 ButtonBase를 Button 과 ToggleButton이 모두 상속받음으로서
아래와 같이 Tree 형태를 유지하는 깔끔한? 전체적인 구조가 완성되었습니다.
(그리고 이것이 바로 WPF의 UI Control Framework 설계 모습이기도 합니다.)
이렇게 Top-Down적인 설계가 한계에 다다랐을때,
아래에서 Bottom-up하는 설계/생각을 도입하여
좀더 Elegant 하게 설계의 문제를 해결할수 있습니다.
결론
하지만 앞에서 살펴본 설계에는 한가지 꼭 필요한 요구사항이 있습니다.
바로 "전체를 보면서 설계하라" 라는 의미입니다.
전체 클래스들의 배치와 구조 그뿐만 아니라 각 클래스의 중복점을 알지 못하면
객체지향의 요소들의 존재이유와 특징을 음미하지 못하는,
제대로 안된 설계만이 나올 뿐이고, 개발자는 더욱 고생하게 됩니다.
그래서 전체를 보는데 도움이 되는 팁을 몇개 정리했습니다:
객체지향 설계의 원칙 = 되도록 기능의 책임을 잘게 나눠라 잘라라
전체 설계 구조의 형태 = Tree 모양을 유지하라
끊임없는 문서화와 리팩토링 = 가지치기를 많이 할수록 정원이 좋아진다.
2010년 4월 7일 수요일
예스맨 프로젝트
2010년 4월 5일 월요일
모바일 퍼스널 트레이너
아래는 관련 설문입니다. 응해 주시면 감사하겠습니다. ^^
2010년 4월 4일 일요일
윈도폰 7에선 더이상 네이티브 개발이 안된다?
2010년 3월 26일 ... 윈도폰7용 파이어폭스 개발이 중단된 이유. 임민철 기자 imc@zdnet.co.kr. 2010.03.28 / PM 03:09. 모질라, 파이어폭스, 브라우저, 모바일, 스마트폰, ...
이미 회자된 것이지만,
윈도폰 7에는 더이상 네이티브 개발이 들어갈 자리가 없군요...
기사의 내용은, 파이어폭스는 기존의 윈도우 개발환경을 사용하지 않는 완전히 독립된
개발로 진행되어 왔고, 네이티브로 만들어져 와서 현재 윈도폰 7처럼 개발을 한정지을 경우
이를 위해서 코어를 다시 만드는 개발을 진행할수는 없다.
따라서 파폭 모바일 7은 못만들겠다.
이러한 이야기입니다.
이미 MS에서 이야기 한대로 윈도폰 개발의 2 방법은 다음과 같습니다.
1) 일반 앱 : 실버라이트
2) 게임 : XNA
둘다 c# 기반의 매니지드 환경이라 C++이 치고 들어갈 틈이 없어 보입니다.
왜 C++을 버리게 되었을까요? 최근 MS의 행보를 기준으로 유추해보면
1) .NET 프레임웍을 주력으로 확정짓기 위한 행보
(여기엔 차세대 윈도를 닷넷기반으로 만드는것도 포함됩니다.)
2) .NET 프레임웍 개발이 중심임을 기정사실화 하여 플랫폼 경쟁에서 우위를 선점하기 위해서
3) 아이폰에서 배운 애플의 폐쇄정책 (MAC + Xcode + Objective C)의 교훈
때문이 아닐까 합니다.
결국 가면 갈수록 저같은 MS .NET 빠돌이들은 개발할수 있는 영역이 늘어나는 반면
네이티브 개발자들은 점점 영역이 좁아질지도 모르는 일입니다.
(하지만 아직 MFC/C++/CLI에 대한 지원이 계속되고 있으니, 완전히 버렸다고는 할수 없겠지요.
하지만 완전 네이티브 개발도 계속 매니지드 영역으로 편입될 것으로 보입니다.
그리고 MS가 C#을 주력 언어로 밀어부치는 것도 확실하구요 : 여기에 대해선 추후 좀더 다루겠습니다.
할말이 많아서 ㅋㅋㅋ)
결국 차세대 윈도폰 개발을 하고싶은 사람들은
좋던싫던, 실버라이트/WPF/XNA를 배워야 할 날이 다가오고 말았습니다.
(뭐, 여러 개발사들의 반발이 심하면 플래쉬 경우처럼 네이티브 개발 영역을 열어줄지도 모르는 일입니다. )
뱀발:
누구는 MS가 점점 개발자를 바보로 만들고 있다고 하는데
(이경우 매니지드 환경 자체가 쉽기? 때문에 개발자를 바보로 만든다고 생각하는 편입니다.)
사실 MS입장에서는 자사 플랫폼이 좀 더 많은 사람에게 쓰이는 것이 목적이기 때문에
상위 개발자들보다 하위 개발자를 포섭시키고 개발업무의 효율성을 증가시킬수 있는 닷넷을
미는것이 옳습니다. 그리고 저같은 개발자 입장에서도 처음에는 닷넷이 별거 없다고 생각했지만
사실 CLR via C#. Effective C#, C# the programming language 등의 책을 읽어보면
.NET 프레임웍이라는 것이 현대 컴퓨터 공학의 정수를 많이 담아둔 것임을 알수 있을겁니다.
중요한건 자기가 처음부터 모래성을 다 만들면서 배우냐, 아니면 이미 잘 쌓여진 모래성을 연구하면서
실력을 쌓느냐에 달려있는것 같습니다. 결국 배움의 의지와 노력에 달린것이지요.
2010년 4월 2일 금요일
Windows Phone 7 - Hello PHOO~
SDK 깔면 같이 깔리는 VS 2010 Expression 버전으로 맛보기 개발이 가능합니다.
Portrait | Landscape |
2010년 4월 1일 목요일
Windows Phone 7 Information
안녕하세요, 불곰입니다.
윈도폰 7 관련하여 개발을 해보고자 여기저기 자료를 찾아서 몇개 모아봤습니다...
그리고 들리는 이야기로 LG에서 지난달 HW 데모를 내놨다는군요.
(삼성은 안드로이드 올인인데... 과연 Win7 Phone이 나올까요?)
MIX10
MIX10에 나온 윈도폰 관련 내용...
폰에 대포를 연결해서 가속도 센서로 각을 조절해 쏘는군요
(학교에서 공작수업으로 했던 포트리스가 생각납니다. ^^)
http://blogs.msdn.com/eva/archive/2010/03/17/mix10-7-ie9.aspx
이런거 보면 MS가 "재미"를 자꾸 강조하는것 같습니다.
삼성도 좀 "재미"를 강조했음 좋겠습니다.
(당장 "돈" 되는것 이외엔 별로 관심이 없으니...안타까울 따름입니다.)
윈도우폰 7 시리즈 무료 개발툴 다운로드
이 링크에서는 윈도 마켓플레이스 등록이 가능하고
http://developer.windowsphone.com
이 링크에서는 툴을 직접 다운로드 가능합니다.
http://developer.windowsphone.com/windows-phone-7-series/
위트스튜디오
지인들이 모여 만든 닷넷 전문 커뮤니티 - 위트
http://blog.witstudio.net/category/Developer/Windows%20Phone
페졸드 아저씨 책
CodeSamples_DRAFTPreview_ProgrammingWindowsPhone7Series.zip
이 아저씨는 정말 대단한것 같습니다.
책 빨리 내는것도 그렇고
쓰면 읽는사람 지치고 지루할 정도로 자세히,
그리고 두껍게! 쓰는것도 그렇고...
아마 MS에서 페졸드 아저씨 명성을 이용하려고 하는것도 있겠죠.
이 글은 스프링노트에서 작성되었습니다.