»
S
I
D
E
B
A
R
«
[나쁜 팀 문화] 가능한 한 많은 일을 병렬로 (II)
Jan 15th, 2010 by Wegra Lee

2009년 10월에 같은 제목으로 포스팅 한 글[1]의 연장선에서 몇 마디 더 적어보고자 한다.

제목만으로도 충분히 짐작할 수 있듯, 우리 팀의 일하는 방식은 가능한 많은 일들을 가능한 한꺼번에 진행하는 것이다. 그런데 최근 상황을 보면 문제가 더욱 심각해지고 있는 것 같다.

어딘가에서 요청이 들어오면, 차후 뒷감당에 대해 충분히 고려하지 않고 일을 진행시키는 경향이 엿보인다. 얼핏 생각해도, 그리고 경험상으로도 그 일 하나의 파급는 너무 막대하여, 추후 기능 개선이나 유지보수에 심각한 영향을 미친다. 하나만 예로 들면, 지금껏 별로 신경쓰지 않았던 내부 모듈들을 우리 통제권 밖의 팀에서 사용하라고 공개하는 것이다. 앞으로는 내부 모듈에 대해서도 하위 호환성을 고려해야 한다. 이런 우려들을 이야기해도 마땅한 안은 제시지 못한다. 요즘은 과제 진행에 집요하게 관여하지 않아서이기도 하겠지만, 상대방이 원한다는 정도의 답변 정도만 받았던 것 같다.

지금껏 관련 기능을 전혀 사용해보지 않은 사람에게 단독으로 그 기능을 제공하는 모듈을 개발하게 시키기도 한다. 더 정통한 사람이 있어도 다른 일로 바쁘므로(여유가 있는 사람은 찾을 수 없다. 팀원 중 누군가가 여유가 생기면 메니저가 관리를 제대로 못하는 것이란 강박관념이 있는 것 같다. [2] – ‘쉬어가기.. 혁신을 이끌어내는 방법’ 참조) 함께 하지 못한다. 물론 둘이 하나의 태스크를 공유하는 것은 ‘가능한 많이 한꺼번에’ 정책에 위배된다. 궁금하면 물어보면 된다는 입장인데, 알아야 제대로 된 질문을 할 수 있다. 질문을 받은 측도 질문자가 어느 방향으로 가다가 어떤 관점에서 이런 질문을 하는지 그 문맥을 알지 못하면 제대로된 답변을 줄 수 없다. 우문현답을 기대하지 말자. 질문하는 측도 이 모든 걸 상대가 한 번에 이해할 수 있게 설명할 수 없다. 충분한 이해를 위해 이런저런 사족을 다 얘기하다보면 상대는 오히려 짜증을 낼 수도 있다. 자신도 다른 일로 정신 없는 입장이기 때문이고, 질문한 사람의 일이 잘 안되는 건 자신과 큰 상관이 없기 때문이기도 하다.

혼자 하느라 갑갑하고 진도도 더딘데, 주어진 시간은 항상 촉박하다. 결국 유사한 기능의 타 제품을 몇개 참고해서 비슷하게 흉내내는 수준의 작품이 나올 수 밖에 없다. 제품 전체 중 일부는 어쩔 수 없이 그럴 수 있다 치지만, 내가 보기엔 그 정도가 심하다.

우선.. 아무리 흉내를 낸다 해도, 이해할 수 있는 만큼만 구현할 수 있다. 문외한이었던 사람이 혼자 짧은 시간동안 이해할 수 있는 범위는 가장 기초적이고 정석적인 부분뿐일 것이다. 고급 기능이나 색다른 (경험이 많은 사람이라면 ‘아! 이런 방법도 있었군!’ 이라 생각할만한, 때로는 혁신적인) 형태는 쉽게 이해할 수 없다.

뿐만 아니라, 우리 제품에 가장 적합한 방식이 무엇인지도 판단하기 힘들다. 특정 기능에 대해 이견이 있을 때 우리 팀에서 가장 힘있는 근거는 ‘제네도 이렇게 해요’ 이다. 정통한 노하우나 깊은 고민 없이 이곳 저곳 유사 플랫폼, 유사 기능의 제품을을 흉내내고 있음을 잘 보여주는 대목이다. 이것마저 각 모듈마다 별다른 커뮤니케이션 없이 독자적으로 진행하니, 제품 전체를 꽤뚫는 우리만의 색깔과 혼을 찾을 수 없다. 타 제품에서의 멋진 디자인도 우리 제품에 가져오면 효과가 반감된다. 특정 모듈에서만 효과가 있을 뿐, 다른 모듈에서는 그 특성을 십분 활용하도록 고민되지 않았기 때문이다. 전혀 필요 없는 기능을 멋모르고 집어 넣는 경우도 종종 있다. 플랑켄슈타인 같다고 해야할까. 동작은 하지만 조화롭지 못하고 보기 흉한 제품. 영화에서처럼 힘이라도 세지면 좋겠으나, 현실에선 과연 어찌될지……

p.s. 요즘은 포스팅 의욕이 많이 저하되었다. 대충 쓰고 올린다. ;;;


References

  1. [나쁜 팀 문화] 가능한 한 많은 일을 병렬로 (wegra.org)
  2. 쉬어가기.. 혁신을 이끌어내는 방법 (wegra.org)
쉬어가기.. 혁신을 이끌어내는 방법
Jan 11th, 2010 by Wegra Lee

우리는 창의력과 혁신을 강조하는 시대에 살고 있다. 소프트웨어 개발도 당연히 그 중심에 서 있다. 하지만 우리의 소프트웨어 개발 문화는 창의력을 심히 제한하는 방식으로 굳어져 있다.

일반적으로 우수한 편에 속하는 지적 능력을 가지고 있고, 새로운 것을 만들어내는 것을 즐기는 소프트웨어 개발자들. 그들은 회사에서 어떤 대우를 받고 있나. 조직이 조금만 커져도 기획은 별도의 부서에서 진행하고, 소프트웨어 개발은 몇몇 관리자들이 이끌게 된다. 소프트웨어 개발자들은 창의력을 발휘하기 보다는 시키는 일만 열심히 해야 하는 위치에 놓이게 된다. 코드를 찍어내고 타의에의해 변경된 요구사항들 때문에 수정/테스트를 반복하는 나날을 보내며 발언권은 점점 작아진다.

기술 개발을 중시하는 몇몇 소수 기업을 제외하고는 대부분(대기업)의 윗사람들은 아직까지 소프트웨어 개발자들을 단순 노동자 취급하고 있다. 이를 빗대어 나는 ‘소프트웨어 제조업’ 에 종사하고 있다고 얘기하곤 한다.

반면, 개발자들의 능력을 믿고 그들에게 스스로 혁신을 일으킬 수 있도록 지원해주는 대표적인 기업들로 Google, Apple, Rally Software 등을 들 수 있다.

Google 은 20% 제도로 유명하다[1]. 자신에게 주어진 시간 중 20% 정도를 주업무가 아닌 다른 일에 할애하도록 권장하는 제도로, 다양한 형태로 응용 가능하다. 매일매일 20%의 시간을 다른 일에 투자하는 것은 대부분의 경우는 현실적이지 않다. 프로젝트 마감이 코앞인데 다른 일에 정신 팔기도 힘들고, 하루 1~2시간씩 해서는 진도도 나가지 않기 때문이다. 대신 그들은 1주일에 하루, 1달에 1주, 혹은 6개월에 1달, workaholic 이라면 주말을 이용 등등.. 자유롭게 변형해서 일한다. 과제가 바쁠때는 열심히 그 일에 매달렸다가 한가할 타임에 그동안 못 쓴 20%를 쓰는 식이다.

20%의 시간에는 어떤 일을 할까? 이것도 아주 자유롭다. 전혀 새로운 과제를 수행할 수도 있고, 관심있는 다른 팀 과제를 지원할 수도 있고, 자신의 주 과제를 진행하면서 불편했던 부분을 자동화하거나 유용한 유틸리티를 만들거나, 최적화/리펙토링을 할 수도 있고, gmail/chrome browser 등에 유용한 플러그인을 만들어넣을 수도 있다. 공부를 할 수도 있다.

이렇게 해서 나온 결과들은 팀의 개발 생산성을 향상시키고, 제품의 품질을 좋게하고, 새로운 것을 배우게 만들고, 운이 좋으면 구글의 미래를 이끌어갈 제품으로 거듭날 수도 있다. Gmail, Google News, Google Talk, Orkut, Google Sky [2], Go programming language [3] 등은 모두 20% 시간에 시작된 프로젝트들이다.

Apple 의 경우 1년에 1달 가량 자신이 원하는 일을 할 수 있게 해준다지만.. 자세한 내용은 잘 알려지지 않았다[4].

마지막으로 Rally 의 경우 8주의 개발 사이클 중 마지막 1주는 회사의 미션과 관련된 일이라면 어떤 것이든 할 수 있는 권한이 주어진다[5]. 기간이 일정하게 주어져 있기 때문에 융통성이 조금 부족하지 않을까 우려되긴 하지만 한 숨을 돌리며 자신들의 과거를 뒤돌아볼 수 있다는 점만으로도 확실한 장점이 될 것이다.

다시 암울한 우리의 이야기로 돌아와보자.

나는 현 회사의 윗사람으로부터 ‘관지자가 할 일은 개발자가 놀지 않게 하는 것’ 이란 얘기를 들었다. 여기서 논다는 것은 ‘주업무와 직접적으로 관련 없는 모든 일’을 지칭한다. 내게는 ‘공장 가동을 멈추지 말 것’ 정도로 들렸다. 공식적인 주업무 외에는 회사에 기여하지 못하는 것으로 여겨기기 때문에 일거리를 만들어서라도 주지 않으면 능력 없는 관리자가 되는 것이다.

개발자 입장에서도 마찬가지다. 좋은 아이디어가 있더라도 side job 은 업적으로 인정받기 어렵다. 놀고 있는 것으로 받아들여지므로 드러내놓고 할 수도 없다. 결국 몰래 하거나 개인 시간을 희생해서 짬짬이 하게 되고, 인정받지 못하기 때문에 의욕이 생길리 만무하다.

고급 인력인 개발자들의 좋은 두뇌를 활용하지 못하고, 반대로 창의성을 저하시키는 이런 문화는 하루 빨리 고쳐져야 한다. 말로만 소프트웨어가 중요하다고 하지 말고, 소프트웨어 개발의 특성과 개발자들을 이해하려는 노력이 절실하다.

두서 없지만 이 글은 이쯤에서 마무리하기로 하고, 유사 주제로 작성하고 있는 글이 있으니 그 쪽에서 정리를 시도해보기로 하겠다. ^^


References

  1. Pros and Cons of Google’s 20 percent time concept? (Ask MetaFilter)
  2. Top 20 Percent Projects at Google (eWeek.com)
  3. The Go Programming Language (Google, golang.org)
  4. 애플 “한국을 모바일 테스트베드로 활용” (아시아 경제)
  5. Principles of Agile Architecture (wegra.org)
[나쁜 팀 문화] 안티 투명성
Jan 7th, 2010 by Wegra Lee

몇달 전에 프로젝트 투명성(Project Transparency)에 대한 글[1]을 올린 적이 있다. 당시에는 프로젝트에 투명성을 부여함으로써 얻을 수 있는 장점을 중심으로 설명하면서, 이를 읽은 프로젝트 팀들에서 투명성 확보를 위해 노력해주길 바라며 글을 적었다. 하지만 최근에 들어서는 관리자들이 일부러 과제를 불투명하게 만들고 있는 것이 아닌가 하는 의구심이 들기 시작했다. 아니! 감시 받는게 아니냐는 느낌을 떨치기 어려운 실무자들도 아니고, 오히려 현 상황을 정확히 알고 싶어할 듯한 관리자들이 도대체 왜? 지금부터 천천히 이야기 해보기로 하자.

나는 Rational Team Concert (RTC) [2] 라는 Application Lifecycle Management 시스템은 팀 내에 소개/교육/운영하고, 몇 차례에 걸처 그 결과를 공유한 적이 있다. 당시 (지금까지도) 우리 팀은  과제 시작 후 크고 작은 릴리스 중 단 한 번도 목표일을 지켜본 적이 없었고, 지연 기간도 들쑥날쑥 예측이 어려웠다.  릴리스가 끝나고 나서야 비로서 ‘아! 이번엔 이만큼 지연됐구나’를 알 정도였다[3].

수 개월 동안 몇 차례의 릴리스 기간을 거치면서 RTC 가 보여주는 정보는 항시 일관적이고 명확했다. ‘현 상태로는 일정을 맞출  확률은 0% 이다.’ ‘당신의 팀은 task를 끝내기도 전에 끊임없이 새로운 task들을 더 추가한다.’ ‘당신 팀의 업무 수행 능력은 이 정도이다.’ ‘따라서 목표를 다 이루려면 x 일 정도 지연될 것이다.’ ‘일정에 맞추려면 a, b, c 등의 task 를 뒤로 미뤄야 한다.’ 이런 정보들을 한 눈에 확인할 수 있는 실시간으로 그래프를 제시해준다. 대표적인 그래프인 burndown chart 의 예[4]는 아래와 같다.그림과 같이 프로젝트의 현 상황과 진행 추이, 예상 완료 시점 등을 바로 확인할 수 있는 그래프를 전체 팀은 물론 서브팀별로 만들어주고, 누구나 보고 싶으면 언제든 웹을 통해 접근할 수 있다.

(Note: 위 그림은 우리 과제에서 얻은 실제 데이터 도, RTC 가 생성한 그래프도 아니다. 이해를 돕기 위한 단순 참고용이다. 또한 burndown chart 의 개념은 RTC 라는 특정 툴에 종속적이지 않다. Agile/Scrum 쪽에서 널리 활용하는 프로젝트 관리 기법으로 툴 없이도 쉽게 만들어 활용할 수 있다. RTC는 단지 이를 지원할 뿐..)

자! 어떤 결과가 예상되는가? 실무자들 중에는 사용해보고 싶다는 사람들이 조금씩 늘어났다. 반면 관리자들 중에서 관심을 가지는 사람은  거의 전무했다(그나마 계정만 만들고 실제 사용은 안함). RTC 라는 새로운 환경에 적응하기 위해 가장 많은 변화와 노력을 기울여야 하는 실무자들이 관심을 더 보이는 이유는 무엇일까? 역으로, 프로젝트의 목표와 일정을 세우고, 우선 순위를 조정하고, 업무 부하를 관리해야 하는 관리자들은 도데체 무엇 때문에 관심 자체를 보이지 않았던 것일까?

실무자들이 쓰는 이유는 주로 이러했다.

  • 자신에게 할당된 task 들을 효율적으로 관리/진행/보고하기 위해
  • 상사의 말도 안되는 업무 요청에 대한 방어/협상 자료로 활용키 위해
    • 내가 놀고 있나요? 그 일을 하길 원한다면, 여기 쌓여 있는 현 일들 중 어떤 것을 미룰까요?

관리자들이 쓰는 이유는 알 수 없다. 쓰는 사람이 없으니 -_-a

그렇다면 관리자들이 외면하는 이유는? 물론 수많은 요인들이 복합적으로 작용했고, 사람들마나 차이도 많다. (Note: 설문조사를 한 것은 아니고.. 대부분은 이런저런 주변 정황과 평소의 대화들을 토대로 유추해본 것 뿐이다.)

  • 현 상태에 만족해서 (여러 사람과 이야기해보았는데, 우리팀에는 해당되지 않는다. 모두가 불만이다.)
  • 단지, 새로운 것을 익힐 심적/시간적 여유가 없어서 (제법 많다. 위에서 시키지 않은 일에 에너지를 할애하길 꺼려한다.)
  • 다년간 체득한 ‘나서서 좋을 것 없다’ 는 경험 때문에 (조금 있다. 정말 좋으면 남들이 써보고 전파해주겠지 하는 생각.)
  • 귀찮아서 (역시 제법 되어 보인다. 새로운 것은 익히기 보단 다소 불편하더라도 익숙한 것에 머무르려 한다. 시도조차 안해본다.)
  • 투명해지면 안된다고 생각한다. (조금 있어 보인다. 이 글의 주제이므로 바로 뒤에 별도로 설명하겠다.)
  • 기타.. (여러가지 더 떠오르지만 주제와 큰 관련이 없으므로 생략)

투명해지면 안된다고 생각하는 사람들은 상위 지배층과 외부 사람들(stakeholder, customer 등)을 대하는 사람들일 경우가 많다. 이들에게 투명한 과제가 장점을 발휘하려면, 그 과제가 정말 잘 진행되고 있어야 한다는 전제가 깔린다. 이러저러한 문제들이 산적한 상태에서 잘못 공개되면 지원이 줄어들고 대기 수요가 빠져나간다. 이들에게는 안좋은 것을 숨기고 희망찬 메시지만 전달해주어야 한다. 단번에 ‘3달쯤 지연될 겁니다’라고 얘기하면 ‘그렇게까지는 못 기다립니다’라고 하지만, ‘1주일만 더 기다려주세요’를 여러차례 반복하면 ‘이왕 기다린 거, 이번엔 꼭 된다니깐 조금만 더 기다려보지.  등 돌리기도 늦은 것 같고..’ 하는 반응을 이끌어낼 수 있다.

위와 같은 이유로 의도적으로 투명성을 제한하려는 사람들이 있다고 믿는 근거는.. ‘팀 리더로써 가장 중요한 것은 프로젝트를 부러뜨리지 않는 것’ 이라거나, ‘이런 건 누구누구가 알면 안되는데’ 라며 정보 공개를 불편해하는 발언 등을 하는 윗 사람들을 종종 보았기 때문이다. 프로젝트를 계속 유지하는 것은 물론 중요하다. 하지만 외부에 알려진 것 대비 심각하게 안좋은 상황에서도 무리하게 정보를 숨기는 것은 과연 어떨까? 상황을 만회하기 위해 뒤에서 열심히 고생하는 개발자들과 이를 믿고 투자하는 사람, 제품을 기다리는 고객 모두에게 악영향을 미치게 된다. 투자자가 개발팀이 속한 회사 자체라면(내부 프로젝트), 그 팀은 프로젝트를 유지할 수록 회사의 경쟁력을 떨어뜨리게 된다.

다른 관점에서도 불투명한 과제가 (부정적인 의미에서) 도움이 될 때가 있다. 우리 팀의 모습을 앞서의 그림에 맞춰 비유해보면, 윗사람은 day 10 에 ‘자! 내일이 드디어 릴리스 날입니다. 오늘 저녁까지 남은 일들을 모두 완료해 주시고, 검증이 완료될 때까지 자리를 지켜주세요.’ 라고 당당히 요구하고, 또 그것이 개발자들에게 먹힌다. ‘얼마나 걸릴까요?’ 라는 질문은 없다. ‘반드시 끝내세요.’ 라는 요청이 전부이다. 실무자들은 불만이 있어도 드러내놓고 표출하지도 못하고, 밤 늦게나 자정을 넘어서까지 일을 한다. 당연히 기적은 일어나지 않는다. 만약 위와 같은 정보가 다 공개되어 있다면? 윗사람이 앞서와 같은 요구 자체도 할 수 없겠지만, 만약 그런 요구를 한다면 ‘당신은 눈이 없소?’ 라고 반박해도 할 말이 없을 것이다. 즉 과제가 투명해지면 지금까지와 같은 무리한 명령을 내릴 수 없다.

이상의 이유들로, 수단 방법을 가리지 않고 과제를 살리려 한다거나 전통적(?) 지배체제를 유지하고자 한다면, 프로젝트가 투명해지는 것은 커다란 위험요소가 될 수 있다. 이에 해당하는 사람들은 의도적으로 진행상태를 숨길 수 있다.

만약 이런 현상이 정말로 의도적으로 이루어진 것이라면 개선하기란 정말 쉽지 않다. 앞서 언급했듯, 팀을 이렇게 만든 사람들은 대부분 프로젝트 방향을 좌지우지할 수 있는 힘있는 사람들이기 때문이다. 자료를 아무리 제시해도, 개선의 움직임이 보이긴 커녕 거들떠도 보지 않는다면 실무자들도 제풀에 지쳐 변화를 포기한다. 힘있는 자들의 마인드가 바뀌지 않으면 조직의 문화를 바꾸는 것은 거의 불가능하다.

정리: 관리자들 대부분이 이와 같다는 의미는 절대 아니지만, 그 중 일부가 이런 생각을 어느 정도 가지고 있는 것은 분명한 것 같다. 따지고 보면 비단 특정 팀이나 회사, 소프트웨어 개발에만 국한된 현상도 아니다. 정보를 통제하는 언론, 기업의 홍보 부서, 조직의 대변인, 심지어 모든 사람 개개인이 외부로부터 자신을 지키기 위해 어느 정도는 이런 성향을 가지고 있다. 하지만 숨기는 대상에 외부 경쟁자들뿐 아니라 자신들을 믿고 따르는 조직원들까지 포함시켜 그들에게까지 희생을 강요하는 상황에 이른다면 문제는 심각하다. 이런 조직에서 과연 얼마나 많은 사람들이 진심으로 자신의 역량을 모두 쏟아 부어줄까? 하나의 팀이라고 말하기조차 부끄럽다.


References

  1. 프로젝트 투명성 (wegra.org)
  2. Rational Team Concert (IBM Rational)
  3. [나쁜 팀 문화] 점진적 지연 (wegra.org)
  4. Burndown chart (wikipedia)
Testable Design Anti-Patterns
Dec 17th, 2009 by Wegra Lee

한 4년쯤 전에 정리를 시작했던 주제로, 지인 몇 명과 논문으로 써볼까 기고를 할까 고민하다 제 때 빛을 보지 못했다. 실례를 찾아 보강하는 것이 가장 큰 숙제였는데, 불행히도 그 후 테스트 관련 업무를 접할 기회가 없었어서 기고까지는 하지 못했다.

Testable Design Fundamentals

In other to make software testable, designer should follow some rules. If you are interested in software design, some of them must be familiar to you. That’s because they are rules for improving software ‘design‘ in testability perspective. Lets look into the rules one by one.

  1. Clear Specification: Specification should cover all possible situations even for illegal conditions. Moreover, it must be clearly defined without any ambiguous sentences.
  2. Controlability: Target should provide mechanisms to read/write the conditions or to run the operations which are required to verify its functionality. It should be easy enough to implement.
  3. Modularity: Adequate modularization is one of the fundamental requirements not only for design, implementation, and reuse, but also for test. For an example, a module which has many relationships with other modules is hard to test independently. It should use stub/mock object of wait until the dependant modules are implemented.
  4. Readability: Easy and intuitive naming reduces human errors and decreases design/implementation time. It makes overall testing time shorter.
  5. Consistency: All of the above rules should be reflected consistently so that the software can be look like designed and implemented by one person.

Software which satisfies these rules can be called testable. However, it is very hard to measure quantitatively how well the rules are reflected. I’ll remain this issue for other dedicated articles.

(in Korean)

테스트 가능한 소프트웨어를 만들기 위해서는, 설계자는 몇 가지 규칙을 따라야 한다. 소프트웨어 설계에 관심있는 사람이라면, 친숙한 이름의 규칙들을 찾을 수 있을 것이다. 이유인 즉, 이 규칙들은 테스트의 관점에서 소프트웨어의 ‘설계‘를 향상시키기 위한 지침이기 때문이다. 그럼 그 규칙들을 하나씩 살펴보도록 하자.

  1. 명확한 기능 명세: 소프트웨어 명세서는 잘못된 상황까지 포함한 모든 가능한 상황을 기술해야 한다. 이 때, 의미가 분명한 문장만을 사용해야 한다.
  2. 조작성: 테스트 대상은 그 기능 동작 여부를 판단할 수 있는 정보를 읽고/쓰거나 기능을 동작시킬 수 있는 메커니즘을 제공해야 한다. 또한 소프트웨어 적으로 쉽게 구현할 수 있어야 한다.
  3. 모듈화: 적절한 모듈화는 소프트웨어 설계, 구현, 재활용 뿐 아니라 테스트를 위해서도 꼭 필요하다. 예를 들어, 다수의 다른 모듈과 종속성이 있는 모듈은 독립적으로 테스트하기 어렵다. Stub/Mock Object를 사용하거나, 타 모듈들이 구현되기까지 기다려야 한다.
  4. 가독성: 쉽고 직관적인 이름(모듈, 함수 등 모든 경우에 해당됨)은 휴먼 에러(human error)를 줄여주고, 설계와 구현 시간을 단축시킨다. 결과적으로 테스트에 소요되는 전체 시간을 단축시키는 효과가 있다.
  5. 일관성: 이상의 모든 규칙들은 마치 한 사람의 설계하고 구현한 것처럼 일관성 있게 적용되어야 한다. 각각의 모듈마다 그 정도가 다르다면 휴먼 에러(human error)를 증가시킬 것이다.

이상의 규칙들이 충족된 소프트웨어라면 ‘테스트할 수 있다’고 얘기할 수 있을 것이다. 단, 이런 규칙들이 얼마나 잘 반영되었는지를 정량적으로 측정하는데는 분명한 한계가 있다. 측정 이슈는 주제의 범위를 벗어나므로 본 글에서는 더 자세히 다루지 않을 것이다.

(Read the full article)

설계 vs. 프로그래밍 언어
Dec 14th, 2009 by Wegra Lee
나는 객체지향 개념을 접하기 시작한 97년부터
모든 프로그램을 짤 때에 설계에 초점을 맞춰왔다.
그래서 자연스럽게
객체지향, UML, GRASP, Design Pattern, Bug Pattern, Refactoring, Aspect-Oriented 등등..
의 개념을 접하게 되었고,
실제로 3개월 정도 설계만 하고 보름 미만으로 코딩해서
제대로 돌아가는 프로그램을 만들어본 경험도 있다.
이리저리하여 난 설계의 중요성을 인식하고 권장하게 되었지만,
이상하게도 주위 다른 사람들은 그렇지 않았다.
처음엔 굉장히 답답하여 계몽(?) 시키고자 노력해보았지만,
설계를 시켜도 도저히 설계라 하기 민망한 수준에서 더 이상 진척이 없었던 것이다.
그러면서도 코딩을 시키면 마음엔 안들어도 그럭저럭 돌아가게는 만들어 냈다.
내게 ‘아하~!’하는 깨달음이 온 것은..
1년하고 조금 더 전쯤..
영어 공부 한답시고 한동안 자칭 ‘영어로 사고하기’ 놀이를 하고 다닌 적이 있다.
그러면서 깨달은 것은 ‘아는 만큼 생각한다’이다.
한국어로 생각하고 영어로 표현하려면 어휘력이나 문장력이 부족해 표현을 못한다.
하지만 처음부터 영어로 생각하면 사고의 범위 자체가 좁고 얕아지는 걸 느꼈다.
나는 남들에게 자신 있게
‘난 Java로 free talking 할 수 있다’고 얘기한다.
그리고 대다수의 배테랑 개발자들은
나와 같은 의미에서 자신의 주 언어로 free talking할 수 있을 것이다.
문제는 설계이다.
UML은 개발 언와와는 또 다른 종류의 언어이다.
하지만 거의 100%의 개발자들은 설계용 언어 보다는
개발용 언어를 먼저 익힌다.
필요에 의해서건, 흥미에 의해서건
설계용 언어를 접할 때는 이미 상당 수준의 개발 경험이 갖춰진 후이다.
그들에겐 낯설은 설계 언어로 사고하는 것은 너무 답답하다.
코드로 작성하면 금방 만들 수 있는 것도
설계 언어로는 어떻게 표현해야할 지 알질 못한다.
영어에 능숙치 못한 한국인이
미국인에게 무언가 얘기는 하고 싶은데
말 못하는 것과 마찬가지 이치다.
결국 설계를 하느니

그 시간에 직접 코딩하는 걸 택한다.

우연히 하드 디스크에서 발견한 글이다. 마지막 수정 시간은 2005년 4월 5일. 무슨 계기로 적어놨는지 기억도 나지  않고, 지금보니 설익은 느낌도 들지만 이곳으로 옮겨놓고 지워버리기로 했다. ^^

나는 객체지향 개념을 접하기 시작한 97년부터 모든 프로그램을 짤 때에 설계에 초점을 맞춰왔다. 그래서 자연스럽게 객체지향, UML, GRASP, Design Pattern, Bug Pattern, Refactoring, Aspect-Oriented 등의 개념을 접하게 되었고, 실제로 3개월 정도 설계만 하고 보름 미만으로 코딩해서 제대로 돌아가는 프로그램을 만들어본 경험도 있다.

이리저리하여 난 설계의 중요성을 인식하고 권장하게 되었지만, 이상하게도 주위 다른 사람들은 그렇지 않았다. 처음엔 굉장히 답답하여 계몽(?) 시키고자 노력해보았지만, 설계를 시켜도 도저히 설계라 하기 민망한 수준에서 더 이상 진척이 없었던 것이다. 그러면서도 코딩을 시키면 마음엔 안들어도 그럭저럭 돌아가게는 만들어 냈다.

내게 ‘아하~!’하는 깨달음이 온 것은.. 1년하고 조금 더 전쯤.. 영어 공부 한답시고 한동안 자칭 ‘영어로 사고하기’ 놀이를 하고 다닌 적이 있다. 그러면서 깨달은 것은 ‘아는 만큼 생각한다’이다. 한국어로 생각하고 영어로 표현하려면 어휘력이나 문장력이 부족해 표현을 못한다. 하지만 처음부터 영어로 생각하면 사고의 범위 자체가 좁고 얕아지는 걸 느꼈다.

나는 남들에게 자신 있게 ’난 Java로 free talking 할 수 있다’고 얘기한다. 그리고 대다수의 배테랑 개발자들은 나와 같은 의미에서 자신의 주 언어로 free talking할 수 있을 것이다.

문제는 설계이다. UML은 개발 언와와는 또 다른 종류의 언어이다. 하지만 거의 100%의 개발자들은 설계용 언어 보다는 개발용 언어를 먼저 익힌다. 필요에 의해서건, 흥미에 의해서건 설계용 언어를 접할 때는 이미 상당 수준의 개발 경험이 갖춰진 후이다.

그들에겐 낯설은 설계 언어로 사고하는 것은 너무 답답하다. 코드로 작성하면 금방 만들 수 있는 것도 설계 언어로는 어떻게 표현해야할 지 알질 못한다.

영어에 능숙치 못한 한국인이 미국인에게 무언가 얘기는 하고 싶은데 말 못하는 것과 마찬가지 이치다.

결국 설계를 하느니 그 시간에 직접 코딩하는 걸 택한다.

[나쁜 팀 문화] 너는 생각할 필요 없어. 생각은 나 혼자..
Dec 11th, 2009 by Wegra Lee

내가 최근 과제를 진행하면서 가장 불만이 많았던 문화 중 하나로, 간단히 이야기하면 소수의 누군가가 생각해서 가이드를 만들고 다수의 사람들에게 기계적으로 적용하는 문화이다. 얼핏 생각에 괜찮은 어프로치로 생각될 수 있고, 심지어 권장되는 상황도 많다. 하지만 잘못 남발하면 부작용이 큼을 몸소 느꼈기에 주의하자는 차원에서 정리해보았다.

시작..

우리 팀은 ‘아키텍트(Architect)’라는 멋진 이름의 조직을 갖추고 있다. 이름에 걸맞게 팀내 주요 아키텍쳐적 이슈들을 논의하고 해결안을 찾아 지침을 내려준다. 팀원들도 나름 팀내에서 선별된 사람들로 구성되어 있다. 여기까지만 보면 문제가 있기는 커녕 모범적이라 할 수 있다.

하지만 아키텍트 그룹이 내놓은 가이드의 상당수가 많은 헛점을 보여왔다. 지침대로 적용을 하려던 개발자들로부터 많은 공격을 받아 갈팡질팡하고 번복되기 일쑤였다. 아키텍트들의 결정에 대한 신뢰가 점점 떨어졌고, 개발자들 사이에서는 ‘최대한 늦게 적용하는게 좋다’ 라는 말까지 공공연히 오고가기도 했다.

무엇이 문제였을까? 단순히 아키텍트들의 실력이 부족해서는 아니었다. 이런 현상이 발생할 수 밖에 없었던 상황을 나름 조명해보았다.

팀 환경/문화

팀의 아키텍트 그룹이 제 역할을 하지 못하게 된 데에는 수많은 문제들이 복합적으로 작용한 것으로 보인다. 팀의 전반적인 상황은 지금까지 기술되었던 (그리고 앞으로 더 추가될) 모든 Bad Team Culture 시리즈[1]의 종합 선물세트라 보면 된다. 빠른 진행을 위해 간략히 요점을 정리해보았다.

우리 팀은 거의 항상 무리한 일정에 맞추기 위해 과속 주행을 해왔다. 산적한 모든 일들이 최상의 시나리오대로 완료되어야만 한다. 그 시나리오도 실무자가 아닌 윗선에서 정한 deadline 에 기반한다. 팀 창설 이래 단 한 번도 deadline 에 맞춰본 역사가 없음에도 항시 같은 패턴이다.

거의 모든 아키텍트들의 주 업무는 사실 관리다. 이들은 대부분 서브팀의 리더들로, 자신의 서브팀 업무 처리로도 이미 숨이 벅차다. 더구나 이들은 개발 실무를 담당할 여력도 없다. 큰 그림의 아키텍처나 팀원들이 제기한 구현 상의 이슈에 대해 의사 결정은 참여하지만 직접 구현에 참여하거나 팀원들이 작성한 소스를 살펴보진 못한다.

개발자들 역시 발등에 떨어진 업무들로 다른 논의에 참여할 마음의 여유를 갖지 못한다. 구현 하나만으로도 일정이 빠듯한데, 각종 요청들이 ‘가능한 빨리’ 라는 수식어와 함께 동시 다발적으로 날아온다. 코드 리뷰나 리펙토링 같은 사치스런 용어는 책속에서나 볼 수 있을 뿐이다.

다수 모듈에 적용되는 공통 가이드에 대해서도 깊이 있는 논의와 충분한 공유 대신, ‘일주일 내로 모두 적용해!’ 와 같은 명령이 떨어진다. 가이드 자체도 결함 없는 완벽한 것이라는 이상적 결과를 기준으로 한다. 보완책으로 일부 모듈을 대표로 적용해보기도 하지만 서브팀 내에서의 커뮤니케이션도 부족한 상황에서 도메인이 다른 특정 모듈이 전체를 대표하리란 기대는 품지 않는 것이 좋다.

부작용과 악영향

결과는 아주 부정적이다.

‘아키텍트 = 관리자’ 이므로 논의가 계속 산으로 간다. 한국적 정서상의 문제도 있겠지만, 회의의 비효율성을 불평하면서도 둘을 분리하지 못한다. 어떤 회의에서건 두 이슈가 마구 섞여 논의되므로, 소수의 전담 아키텍트(non-관리자)는 진행 상황조차 파악하기 어려울 때도 많다. 예를 들어, 잠시 묻혀 있던 이슈를 결론짓기 위해 꺼내놓으면 ‘아! 그거 지난번 관리회의에서 x로 결정해서 a, b, c 가 진행중이야.’ 라는 이야기를 아무렇지도 않게 들려준다. 그러면서 전담 아키텍트이니 아크 이슈들을 추적 조율하라는 모순적인 요구를 한다.

팀 전체의 상황을 고루 파악하고 있는 아키텍트가 없다. 다른 서브팀의 상황까지 신경쓸 여유가 없으므로, 아키텍트 회의가 소집되어도 자신의 팀과 직접적으로 관련되어있지 않다면 잘 참석하지 않는다. 충분한 사전 조사와 깊은 논의 없이, 모인 사람만으로 쉽게쉽게 결론을 내는 경향이 생겨 추후 번복의 여지가 많다. 일부 모듈을 대표로 선정해 해결책을 검증해 보더라도, 다른 모듈에는 대대적 칼질을 요하는 경우가 많았고, 가끔은 적용 과정에서 지침을 수정해야만 하는 counter example 이 나오기도 한다.

General 아키텍트의 고뇌.. 에피소드

이러한 상황에서도 어쩔 수 없이 아키텍트로써의 일을 수행하며 개인적으로 많은 고충들을 겪었다. 다른 아키텍트들 대부분은 자신의 분야에 대해서만 직접적인 책임을 지는데 반해, 나는 어지간한 이슈들에는 다 끼어 들어가야 했다. 즉 general 아키텍트였고.. 팀에 단 한 명 뿐이었다.

그러는 와중, 여러 모듈에 걸친 가이드를 만들어야 하는 업무들이 자주 떨어졌다. 나름 최선의 안을 내보려 노력하지만, 결정 과정에서는 언제나 trade off 가 발생한다. 특히나 논의 단계에서의 실무자 참여를 배제하는 상황에서는 수많은 추측과 가정들 위에서 이리저리 저울질을 하게된다. 중간중간 상황을 공지하지만 관심을 주는 사람은 거의 없다. 관심 좀 가져달라고 애원을 해야 한 두 명 답변을 준다. 실무자들을 참여시켜달라는 요청에는 그들은 시급한 다른 일로 시간이 없다는 답변만이 메아리칠 뿐이다.

어찌저찌 가이드를 만들어 공지하지만, 본격적인 일은 이 때부터다. 가이드를 만들면 매니저는 N 일 내로 가이드를 적용하라고 공지한다. 그제서야 드디어 실무자들의 피드백들이 쏟아지기 시작한다. 질문이 터져나오고, 문제점을 지적하고, 나아가 대안을 제시하기도 한다. 개발자들의 성향과 경험이 다양한 만큼 다양한 안들이 나올 수 있다. 대부분은 사전 고려된 안들이기어, 그들들에게 trade off 와 이러저런 상황 요소를 열심히 설명한다. 결국 논리와 양해로 설득을 한다 치더라도 가이드와는 다른 이야기들이 오고가기 시작하면 개발자들은 우왕좌왕 하기 시작하고, 정리된 하나의 안으로 재공지될 때까지 자신의 모듈에 적용하는 것을 미루려 한다. 정리되는듯 싶다가도, 늦게서야 적용하는 모듈 때문에 또 한바탕 소란이 벌어지기도 한다.

묵묵히 가이드를 잘 따르는 것 역시 그리 좋지 않다. 대부분의 가이드는 이상 추구보다는 현실 수용적이다. 과제 초기라면 누가봐도 깔끔한 가이드를 제시하며 떳떳해할 수 있겠지만 현실은 너무도 다르다. 수년에 걸쳐 이미 수십만 라인의 코드를 만들어놨고, 개발자들을 릴리즈 일정에 쫓기고, 다수의 레거시 모듈들을 버무려야 하는 상황인 것이다. 그렇다면 변경량이 적고 에러 유발 가능성이 적으면서 그럭저럭 봐줄만한 절충안을 내놓을 수 밖에 없다. (싹 뜯어 고치자 하면 기획팀/매니저들이 동의하지 않는다.) 내가 봐도 부끄러운 가이드를 던져주면서 사람들이 뭐라고 생각할 지 걱정한 적도 있다. 실력있는 사람들은 보자마자 훨씬 좋은 방법들이 머릿속에 떠올릴 수 있었을 것이고, 그렇지 않은 사람들에겐 그닥 좋지 않은 가이드를 익히게 만든 것이다. 결과로 만들어진 가이드 자체는 부족하더라도, 그 결론까지의 여러 대안들을 연구/분석하고 장단점을 저울질하는 과정을 함께 한다면 모두의 역량 향상에 큰 도움이 됐을 것이지만, 안타깝게도 그럴 시간은 주어지지 않았다.

그나마 현 상황을 함께 겪고 있는 지금의 동료들은 부족함을 이해해 주겠지만, 나중에 합류한 사람들은 어떨까? 결과물만 보고 전임자의 무능함을 욕해도 딱히 비난할 수도 없다. 그리고 그 제품이 세상에 공개된다면? 이력에 적어 넣기도 부끄럽고, 공백기로 둘 수도 없는 계륵 경력이 되어버린다.

가정 자체가 틀어질 때도 있다. 한 번은 개발자들이 도메인에 익숙하지 않고 영향 범위가 제법 크다는 가정으로 2~3주에 걸쳐 좀 억지스러운 가이드를 만들었다. 첫 설명회에서 모두들 ‘우린 그런 문제 없어.’, ‘해당 사항이 거의 없으니 조금만 신경쓰면 충분히 할 수 있을 거 같아.’ 라는 반응들이 것이다. 그 자리에서 바로 정석적인 방식으로 진행키로 결정하고 그에 맞게 약간의 보강 설명을 해주는 것으로 설명회를 마무리했다. 2~3주의 시간을 쓸데 없이 허비한 꼴이 되었다. ‘사전 조사해서 상황을 파악해달라’ 는 초창기 요청에는 한 두 모듈만 피드백을 주었고, 그래서  ’모듈별로 실무자들을 한 명씩만 배정해달라’는 몇 차례의 요청 역시 묵살되었던 케이스였다.

아키텍트 시절 초기에는 의욕을 불태워봤지만, 나의 개선 요구들이 매번 거절당하면서 점차 회의를 느끼게 되었다.

다시 돌아가..

이런 현상의 더 근본적인 원인은 지도층의 마인드 때문이 아닐까 싶다. 리더가 아닌 매니저(관리자) 중심[2]의 팀이라, 중장기 비전을 위한 팀원들의 역량 향상보다는 눈앞의 단기 목표 달성을 최우선시한다. 심지어 팀원 역량 개발은 관리자의 롤에서 배제시키기도 한다. 같은 맥락에서, 소수의 핵심 멤버가 의사를 결정하고 그 외의 다수는 기계적으로 구현만 하면 된다고 얘기하는 것도 가끔 들을 수 있었다.

물론 윗사람들 모두가 이렇지는 않다. 어쩌면 대부분은 단지 정신없는 일정 압박에 어쩔 수 없이 끌려가고 있을 수도 있다. 하지만 일부는 분명 위와 같이 생각하고 있고, 그들의 힘이 강하게 작용하고 있다.

100% 틀렸다고 얘기하는 것도 역시 아니다. 상황에 따라선 이런 어프로치가 도움이 될 때도 있다. 단발성 프로젝트라던가, 초단기로 1차 결과물을 내놓아야 한다던가, 너무나도 자기 주장이 강한 독불장군들이 모인 팀이라던가, 명확한 스팩/설계의 외주 과제라던가, 누구나 인정하는 천제 아키텍트가 이끌고 있다던가 등 다양한 상황들이 떠오른다. 심지어 커뮤니케이션만 잘 이루어진다면 보통의 팀에서도 크게 문제될 것이 없다. 하지만 어설프게 머리를 정하고 권한을 주기에 앞서 팀의 모습을 세심히 살펴보도록 하자.

그리고 앞으로 몇 년 몇 십년을 이 분야에 종사해야 할 지 모르는데 나의 미래에는 아무런 관심도 없는 상사를 만났다고 생각해보자. 변화의 여지가 보이지 않는다면, 오래 함께하고픈 타입은 아닐 것이다. 소프트웨어는 사람이 머리로 만드는 것임을 잊지 않기를 바란다. 지금의 아주 일부만이라도 미래를 위해 투자하자. 팀원을 키우라는 이야기다.

p.s. 이 주제는 정말 오랫동안 수정에 수정을 거듭했다. 아무리 고치고 고쳐봐도 내가 진정 하고픈 말을 정확하고 효과적으로 표현하지 못하겠다. 여전히 맘에 들지 않는 상태이지만.. 언제까지고 고치고만 있는 것도 지겨워서 포스팅한다.


References

  1. [나쁜 팀 문화] 시리즈 (wegra.org)
  2. 리더 vs. 매니저 (wegra.org)
Dependency Injection
Dec 7th, 2009 by Wegra Lee

Spring Framework 관련 한글책[1]을 보다가 Dependency Injection(DI)의 번역에 대한 역자주에서 생각해볼 만한 것이 있어 보충 설명 겸, 잠시 끄적여본다. DI의 개념이 아직 모호한 사람이라면 이 글을 먼저 읽어본 후 참조한 wikipedia[2]의 글을 보면 전체적인 윤곽을 잡는데 도움이 될 것이다.

역자주: 종속객체 주입, 즉 DI(dependency injection)는 스프링에서 가장 기본이 되면서도 매우 중요한 의미를 갖는다. 기존에 가장 많이 쓰이던 번역은 ‘의존성 주입’이었다. 그러나 역자가 보기에 이 번역은 ‘없는 의존성을 만들어 주입한다’는 오해를 일으키고, 이 때문에 DI의 이해가 어려웠다고 생각한다. DI는 없는 의존성을 주입하는 것이 아니라 의존성은 이미 존재하되, 실제 객체가 필요로 하는 종속객체를 주입하는 것을 의미한다. 따라서 ‘의존성 주입’보다 뜻이 명확하도록 ‘종속객체 주입’이라고 번역했다. .. (후략)

일단.. 이 역자가 잘 봤다고 말하고 싶다. DI에서 dependency를 의존성으로 번역한 것은 확실히 잘못된 것이다. UML, OOAD 등 지금까지 IT 기술 관련 대부분의 상황에서는 모듈 간 관계를 명시하기 위해 dependency라는 용어를 사용해왔기 때문에 여기서도 습관적으로 의존성이라는 단어를 선택했으리라 생각한다. 하지만 단어는 문맥에 따라 여러 가지 의미를 가지고 있음을 잊어서는 안 된다.

DI를 직역하더라도 의존성 주입은 아니다. 오히려 위 역자가 사용한 종속객체 주입이 더욱 적절하다. 약간 아쉬운 게 있다면 DI는 object 세상에 국한되지 않기 때문에 ‘객체’라는 말은 여전히 논란의 소지가 있다는 점 정도. 범위를 제한하지 않으려면 module 정도의 추상적인 용어를 사용할 수 있겠지만, object라는 용어도 꼭 OOP에서 말하는 object로 제한되는 것은 아니니 상관없을 듯하다.

그럼 다시.. 왜 직역을 했는데도 의존성은 틀린 것일까? 이는 DI 패턴의 구조[2]를 살펴보면 쉽게 이해가 된다. DI 패턴은 세 개의 요소로 구성된다. 적절한 한글 대용어를 찾기 어려워 대강 번역해보면 이렇다.

이 패턴은 최소 3개의 구성 요소로 이루어진다: dependent와 그의 dependencies, 그리고 injector (혹은 provider, container). Dependent 는 컴퓨터 프로그램에서 작업(task)을 수행해야 할 소비자(consumer)다. 작업 완료를 위해선 특정 부작업들(sub-tasks)을 수행하는 다양한 서비스(dependencies)들을 활용해야 한다. 마지막으로 Injector는 dependent와 그에 필요한 dependency들을 조합해서 작업을 수행할 준비를 갖추는 컴포넌트로써, 이 객체들의 전반적인 라이프 사이클을 관리하기도 한다.

위 설명에서와 같이 DI의 dependency는 객체 간의 관계 속성을 의미하는 것이 아니라 서비스를 제공해주는 ‘실체’를 가리킨다. 그 실체를 (의미 그대로) dependent에서 주입시켜주는 것이다. 위 역자의 용어에 맞추어보면 대략 이렇게 되지 않을까 싶다.

  • Dependent: 의존객체
  • Dependency: 종속객체
  • Injector: 주입자
  • Dependency Injection: 종속객체 주입

이 용어들을 적용해 다시 번역해보면 아래처럼 되겠다. 깔끔하려나.. ^^

이 패턴은 최소 3개의 구성 요소로 이루어진다: 의존 객체(dependent)와 그의 종속 객체들(dependencies), 그리고 주입자(injector, provider, or container). 의존 객체는 컴퓨터 프로그램에서 작업을 수행해야 할 소비자다. 작업 완료를 위해선 특정 부작업들을 수행하는 다양한 서비스(종속객체)들을 활용해야 한다. 마지막으로 주입자는 의존객체와 그에 필요한 종속객체들을 조합해서 작업을 수행할 준비를 갖추는 컴포넌트로써, 이 객체들의 전반적인 라이프 사이클을 관리하기도 한다.


References

  1. Spring in Action SE (Craig Walls / 장시형, 전지훈 / Manning)
  2. Dependency injection (wikipedia)
중복 제거: Master Method
Nov 29th, 2009 by Wegra Lee

이번엔 널리 알려져서 누구나 다 알고 있을법한 (하지만 의외로 안지키는 사람도 많은) 방법을 소개한다.

Problems & Constraints

  1. 메서드를 오버로딩 해야한다.
  2. 입력 인자의 타입은 동일하며 그 유무만이 다르다.
    e.g.> doSomething(a, b) and doSomething(a, b, c)

Solution

가장 많은 인자를 받는 메서드를 Master Method 로 정하고, 다른 메서드에서는 부족한 인자를 default 값으로 채워 Master Method 를 호출한다. 생성자(constructor) 구현 시에도 동일한 규칙이 적용된다.

Examples

int read(byte[] buf)
{  .. // tens of lines
}

int read(byte[] buf,  int offset, int length)
{  .. // tens of lines
}

위에서 첫 번째 메서드는 두 번째 메서드의 특수한 형태로, offset 을 0으로, length 를 buf 의 size 로 해서 호출한 것과 완벽히 동일하게 동작한다. 따라서 첫 번빼 메서드는 아래와 같이 구현할 수 있다.

int read(byte[] buf)
{ return read(buf, 0, buf.size); // redirect to Master Method with appropriate parameters
}

Notes

Master Method 는 코드 중복 최소화 외에도, 오버로딩된 메서드들을 가지고 있는 클래스를 상속할 때 개발자 실수를 최소화 시킬 수 있다는 장점도 있다. 예를 들어, 오버로딩된 메서드 a, b, c 를 정의하고 있는 클래스 A 가 있다. 이 때 이를 상속한 클래스 B 에서 기능을 약간 변경하고자 할 때, Master Method 가 없다면 메서드 a’, b’, c’ 를 잊지 말고 모두 정의해줘야 한다. 실수로 무엇 하나를 빼먹었다면 의도치 않은 동작을 하게될 것이고, 그 원인을 찾기는 쉽지 않을 것이다. 하지만 만약 a 가 Master Method 였다면, a’ 만 재정의하면 문제를 미연에 예방할 수 있다. 따라서 Master Method 를 정하고, 어느 메서드가 Master 인지 명시하는 것이 좋다.

또, C++ 의 경우 Google 은 default parameter 를 흉내낼 목적으로는 사용하지 말기를 권고한다[4]. 그 단점을 아래와 같이 기술하고 있으니 참조하기 바란다.

One reason to minimize function overloading is that overloading can make it hard to tell which function is being called at a particular call site. Another one is that most people are confused by the semantics of inheritance if a deriving class overrides only some of the variants of a function. Moreover, reading client code of a library may become unnecessarily hard because of all the reasons against default function parameters.

If you want to overload a function, consider qualifying the name with some information about the arguments, e.g., AppendString(), AppendInt() rather than just Append().


References

  1. 권장 리팩터링 순서Recommended Sequence for Refactoring (wegra.org)
  2. 중복 제거: God Method (wegra.org)
  3. 중복 제거: Convert & Redirect (wegra.org)
  4. Google C++ Style Guide : Function Overloading (Google)
중복 제거: Convert & Redirect
Nov 26th, 2009 by Wegra Lee

계속해서 Recommended Sequence for Refactoring[1] 의 가장 첫 단계인 Remove duplications 에 적용할 수 있는 리펙토링 기법 하나를 더 소개한다. 먼저 소개한 God Method[2] 와는 얼핏 유사한 상황 같지만 분명한 차이가 있다.

Problems & Constraints

  1. 복수의 동일 목적 함수가 입력 인자의 타입만이 다르다.
  2. 입력 인자들 사이에선 서로 타입 변환이 가능하다. 즉 값(value)은 같으나 표현 형태만 다르다.

Solution

하나의 마스터 함수만 구현은 유지하고, 다른 함수들은 받은 입력의 타입만 변화시켜 마스터 메소드를 호출한다.

Examples

다음의 두 함수는 다른 입력을 받지만 목적은 같다.

toDate(long  timestamp)
{  .. // tens of lines
}

toDate(DateTime dateTime)
{  .. // tens of lines
}

long 타입의 timestamp 를 DateTime 으로 변환시켜 (convert) Date 용 함수를 호출한다.

toDate(long timestamp)
{  DateTime dateTime = new DateTime(timestamp); // convert
return ConvertDateTimeToServerDate(dateTime); // then, redirect
// no more duplicated lines
}

toDate(DateTime dateTime) // master method
{  .. // tens of lines (unchanged)
}


References

  1. 리팩터링 권장 순서 (wegra.org)
  2. 중복 제거: God Method (wegra.org)
중복 제거: God Method
Nov 25th, 2009 by Wegra Lee
1.1. Problems & Constraints복수의 유사 목적 함수가 존재하고 구현 로직이 거의 동일하다. 극히 일부만 다른 코드가 여러 함수에 중복되어 있어, 향후 로직/결함 수정 시 human error 를 유발시키기 쉽다.입력 인자 중 일부가 서로 베타적이어서 하나로 합쳐서 제공하거나, 하나의 함수에서 다른 함수를 직접적으로 호출할 수 없다.Public API 가 이미 고정되어 있어, 서로 다른 인자들을 묶는 공통 타입을 만들고 함수들을 하나로 통합시키는 방법을 사용할 수 없다.혹은, 공통 타입이 존재하나 그 중 일부에 대해선 아무런 지원 계획이 없어, 이를 명확히 알리기 위해 복수의 독립적인 API 를 제공하고 싶다.1.2. Solution하나의 God Method(모든 상황에 필요한 인자의 합집합 받으며, 입력 조합에 반응하여 동작함)을 ‘내부’에 두고, 공개 메서드에서는 인자를 적절히 조합하여 이 God Method 를 호출한다.1.3. CautionsGod Method 는 하나의 기능에만 특화된 메서드에 비해 로직이 복잡하므로, 일반적인 경우에는 지양해야할 어프로치다.’중복량 vs. 복잡도 증가’ 를 잘 판단하여 적용 여부를 결정해야 하며, 적용하더라도 내부(private) 메서드에 한정 것이 좋다.1.4. Example아래의 세 함수들은 입력 인자 중 하나만이 다르며, 구현에서도 총 70라인 중 단 한 라인(CreateHttpRequestN 호출부)만이 다르다.DoSomething(..){       ..requestString = CreateRequestString(.., null, null,  ..);..}DoSomething(Circle circle, ..){       ..requestString = CreateRequestString(.., null, circle,  ..);..}DoSomething(Rectangle rectangle, ..){       ..requestString = CreateRequestString(.., rectangle, null,  ..);..}CreateHttpRequestN 함수에 필요한 모든 인자를 받아들이니 God Method 를 만들어 구현을 하나로 모은다.DoSomething_God // 새로 추가된 God Method(       Rectangle rectangle, Circle circle, ..){       ..requestString = CreateRequestString(.., rectangle, circle,  ..); // 받은 인자를 bypass..}DoSomething(..){       // 전후 중복 라인 사라짐return DoSomething_God(null, null,  ..); // God Method 호출}DoSomething(Circle circle, ..) const{return DoSomething_God(null, circle,  ..);}DoSomething(Rectangle rectangle, ..) const{return DoSomething_God(rectangle, null,  ..);}God Method 를 자세히 보면, public API 와 달리, Rectangle 와 Circle 인자를 포인터로 받고 있다. 이는 Rectangle, Circle 중 아무것도 사용하지 않는 메서드를 포용하기 위해서이다.
Problems & Constraints
복수의 유사 목적 함수가 존재하고 구현 로직이 거의 동일하다. 극히 일부만 다른 코드가 여러 함수에 중복되어 있어, 향후 로직/결함 수정 시 human error 를 유발시키기 쉽다.
입력 인자 중 일부가 서로 베타적이어서 하나로 합쳐서 제공하거나, 하나의 함수에서 다른 함수를 직접적으로 호출할 수 없다.
Public API 가 이미 고정되어 있어, 서로 다른 인자들을 묶는 공통 타입을 만들고 함수들을 하나로 통합시키는 방법을 사용할 수 없다.
혹은, 공통 타입이 존재하나 그 중 일부에 대해선 아무런 지원 계획이 없어, 이를 명확히 알리기 위해 복수의 독립적인 API 를 제공하고 싶다.
Solution
하나의 God Method(모든 상황에 필요한 인자의 합집합 받으며, 입력 조합에 반응하여 동작함)을 ‘내부’에 두고, 공개 메서드에서는 인자를 적절히 조합하여 이 God Method 를 호출한다.
Cautions
God Method 는 하나의 기능에만 특화된 메서드에 비해 로직이 복잡하므로, 일반적인 경우에는 지양해야할 어프로치다.
‘중복량 vs. 복잡도 증가’ 를 잘 판단하여 적용 여부를 결정해야 하며, 적용하더라도 내부(private) 메서드에 한정 짓는 것이 좋다.
Example
아래의 세 함수들은 입력 인자 중 하나만이 다르며, 구현에서도 총 70라인 중 단 한 라인(CreateHttpRequestN 호출부)만이 다르다.
DoSomething(..)
{       ..
requestString = CreateRequestString(.., null, null,  ..);
..
}
DoSomething(Circle circle, ..)
{       ..
requestString = CreateRequestString(.., null, circle,  ..);
..
}
DoSomething(Rectangle rectangle, ..)
{       ..
requestString = CreateRequestString(.., rectangle, null,  ..);
..
}
CreateHttpRequestN 함수에 필요한 모든 인자를 받아들이니 God Method 를 만들어 구현을 하나로 모은다.
DoSomething_God // 새로 추가된 God Method
(       Rectangle rectangle, Circle circle, ..)
{       ..
requestString = CreateRequestString(.., rectangle, circle,  ..); // 받은 인자를 bypass
..
}
DoSomething(..)
{       // 전후 중복 라인 사라짐
return DoSomething_God(null, null,  ..); // God Method 호출
}
DoSomething(Circle circle, ..) const
{
return DoSomething_God(null, circle,  ..);
}
DoSomething(Rectangle rectangle, ..) const
{
return DoSomething_God(rectangle, null,  ..);
}
God Method 를 자세히 보면, public API 와 달리, Rectangle 와 Circle 인자를 포인터로 받고 있다. 이는 Rectangle, Circle 중 아무것도 사용하지 않는 메서드를 포용하기 위해서이다.

지난달 포스팅한 Recommended Sequence for Refactoring[1] 의 가장 첫 단계인 Remove duplications 에 적용할 수 있는 리펙토링 기법이다.

곧 한 두개의 기법이 추가로 뒤따를 예정이다.

Problems & Constraints

  1. 복수의 유사 목적 함수가 존재하고 구현 로직이 거의 동일하다. 극히 일부만 다른 코드가 여러 함수에 중복되어 있어, 향후 로직/결함 수정 시 human error 를 유발시키기 쉽다.
  2. 입력 인자 중 일부가 서로 베타적이어서 하나로 합쳐서 제공하거나, 하나의 함수에서 다른 함수를 직접적으로 호출할 수 없다.
  3. Public API 가 이미 고정되어 있어, 서로 다른 인자들을 묶는 공통 타입을 만들고 함수들을 하나로 통합시키는 방법을 사용할 수 없다.
  4. 혹은, 공통 타입이 존재하나 그 중 일부에 대해선 아무런 지원 계획이 없어, 이를 명확히 알리기 위해 복수의 독립적인 API 를 제공하고 싶다.

Solution

하나의 God Method(모든 상황에 필요한 인자의 합집합 받으며, 입력 조합에 반응하여 동작함)을 ‘내부’에 두고, 공개 메서드에서는 인자를 적절히 조합하여 이 God Method 를 호출한다.

Cautions

God Method 는 하나의 기능에만 특화된 메서드에 비해 로직이 복잡하므로, 일반적인 경우에는 지양해야할 어프로치다.

‘중복량 vs. 복잡도 증가’ 를 잘 판단하여 적용 여부를 결정해야 하며, 적용하더라도 내부(private) 메서드에 한정 짓는 것이 좋다.

Examples

아래의 세 함수들은 입력 인자 중 하나만이 다르며, 그에 따라 달라지는 코드 라인수는 전체 코드 구현에서 비중이 작다. 혹은 중복 코드의 절대량이 많다.

public Object DoSomething(.. /* series of params */)
{  .. // tens of lines
MakeSomething(.., null, null,  ..);
.. // tens of lines
}

public Object DoSomething(Apple apple, .. /* series of params */)
{  .. // tens of lines
MakeSomething(.., apple, null,  ..);
.. // tens of lines
}

public Object DoSomething(Orange orange, .. /* series of params */)
{   .. // tens of lines
MakeSomething(.., null, orange,  ..);
.. // tens of lines
}

DoSomething 함수에 필요한 모든 인자를 받아들이니 God Method (DoAnything) 를 만들어 구현을 하나로 모은다.

private Object DoAnything(Apple apple, Orange orange, ..) // newly introduced god method
{  .. // tens of lines
MakeSomething(.., apple, orange, ..); // bypass the given params
.. // tens of lines
}

public Object DoSomething(..)
{  // no more duplicated lines
return DoAnything(null, null,  ..); // invoke the god method
}

public Object DoSomething(Apple apple, ..)
{
return DoAnything(apple, null,  ..);
}

public Object DoSomething(Orange orange, ..)
{
return DoAnything(null, orange,  ..);
}


References

  1. 권장 리팩터링 순서 (wegra.org)
  2. 중복 제거: Convert & Redirect (wegra.org)
»  Substance: WordPress   »  Style: Ahren Ahimsa