Altruistic Programmer's Blog (KR)

이타주의 프로그래머의 블로그

Archive for the ‘Facts and Fallacies of Software Engineering’ tag

소프트웨어 공학의 사실과 오해 10 – 연구, 마무리

without comments

http://www.yes24.com/24/goods/1418676

연구

그런데, 소프트웨어 연구에는 문제가 있다. 평가적 연구(방법, 모델, 이론 등을 검토하는 연구)가 거의 없다는 것이다. 소프트웨어 공학 연구 유형의 스펙트럼에서 14%만이 평가적 연구다. 컴퓨터 과학 연구도 단지 11%만이 평가적 연구다. 이와는 대조적으로, 정보 시스템과 같은 다른 주요 컴퓨팅 분야에서는 평가적 연구가 67%에 이른다.

p.265

Potts(1993)은 이런 잘못된 연구 방법을 ‘연구한 다음 전파하는 방식’이라고 불렀는데, 이는 새로 연구한 접근방법의 제안과 이를 실무에 전파하기 위해 제시하는 중간에 평가가 없다는 것을 뜻한다. 나는 동일한 상황을 나타내는데 ‘옹호적 연구’란 용어를 사용했다. (…) Tichy와 그의 동료들(1995)은 컴퓨팅 분야에 대한 400개의 연구 논문을 검토해 소프트웨어 공학과 컴퓨터 과학에 대한 40~50%의 논문에 평가적 요소가 결여돼 있음을 알아냈다.

p.266

학계의 소프트웨어 연구자들은 너무도 자주 새로운 개념을 제안하고, 이 새로운 개념이 대단히 중요한 것인 양 과장하고, 이를 즉각적으로 실무에 적용하지 않는 이들을 비난한다. 정형방법도 그런 사례 중 하나다. 연구자들이 평가적 연구를 시작하기 전까지는 그 아이디어의 이득에 대해 잘못 인도했고, 또 잘못 인도할 것이다.

p.267

소프트웨어 업계에는 검증되지 않은 개념이나 기술이 과대 선전되고 있다는 얘기. 하지만 결국 은 탄환Siver Bullet은 발견되지 않았다.

마무리

책을 읽고나서 그 내용을 깨끗하게 잊어버리는 데까지 그리 많은 시간이 걸리지 않는다는 걸 알려준 책이다. -_-;; 한 번 정독을 하고 나서, 블로그에 올릴 부분을 고르려고 다시 정독을 하게 되었는데, 처음에 감탄하면서 읽은 내용에 다시 한 번 감탄하고 있는 나를 발견할 수 있었다.

블로그에 올리면서 다시 또 훑어보았으니 3번은 읽은 셈이다. 예전 같았으면 시간이 아까웠을텐데, 오히려 앞으로 좋은 책은 꼭 여러 번 읽어야겠다는 다짐을 하게 되었다. Debugging Applications를 쓴 존 로빈스 아저씨가 자기는 매년 Code Complete을 다시 읽는다고 했을때, 왜 그럴까 했었는데 이제는 좀 이해가 간다.

소프트웨어 공학의 사실과 오해 8 – 유지보수

without comments

http://www.yes24.com/24/goods/1418676

유지보수

유지보수는 보통 소프트웨어 비용의 40~80%(평균 60%)를 차지한다. 따라서 유지보수는 소프트웨어 생명주기 중 가장 중요한 단계일 것이다.

p.209

몇 년 전에 신입사원을 가르치면서, “이렇게 하면 나중에 수정하기가 어려우니까 저렇게 하는게 좋다.”라는 식으로 얘기를 했더니 “팀장님은 나중에 수정하는 것을 굉장히 신경쓰시는 것 같아요.”라는 반응을 보였다. 내가 너무 당연하다고 생각하던 걸 신기하다는 듯이 얘기해서 어리둥절 했었는데, 그 때 이런 통계 자료가 있었다면 좋았을 걸.. 이라는 생각이 든다.

소프트웨 유지보수 비용에서 약 60%는 개선 작업에 쓰이는 비용이다. 오류 정정은 약 17% 정도다. 따라서, 소프트웨어 유지보수는 기존 소프트웨어를 보수만 하는 것이 아니라 새로운 기능을 추가할 때도 많다.

p.213

자, 60+17=77%다. 유지보수 비용의 나머지는 어디로 갔나? 18%는 환경이 변하더라도 소프트웨어가 계속 작동할 수 있도록 하는 적응성 유지보수(adaptive maintenance)라 불리는 것에 들어간다. -중략- 그런데 유지보수 비용의 나머지 5%는 뭘까? 이럴 때 항상 나오는 ‘기타’다. 여기에는 소프트웨어를 더욱 유지보수하기 편하게 만드는 작업도 포함된다. 이런 작업을 예전엔 예방적 유지보수(preventive maintenance)라 했고 최근에는 이런 활동을 표현하는데 리팩토링(Refactoring, Fowler 1999)이란 용어가 쓰인다.

p.214, 215

유지보수는 문제가 아니라 해결책이다. -중략- 유지보수는 “우리는 이런 것을 구축했지만 지금 보니 약간 다른 것을 구축했어야 한다.”와 같은 문제를 해결할 수 있는 유일한 방법이다.

p.217

유지보수는 귀찮은 문제를 해결하는 업무이고 그래서 안할수록 좋다라는 느낌이 있었는데, 사실은 신규 개발과 거의 차이가 없는 솔루션 개발 업무라는 것을 배웠다.

소프트웨어 유지보수 생명주기의 각 단계는 개발 생명주기와 거의 같다. 문제에 대한 요구사항을 분석하고, 수정 또는 개선 작업을 한다. 기존 시스템의 설계 컨텍스트 안에서 솔루션을 설계한다. 솔루션을 코딩하고 기존 시스템에 맞춰 넣는다. 코딩된 솔루션을 테스트하면서, 새로 변경한 것이 제대로 동작하는지, 예전에 제대로 작동하던 것들에 영향을 끼쳐 문제를 일으키지는 않는지 확인하다. 그리고 나서, 개선된 부분을 기존 시스템에 반영하고 계속 유지보수한다.

p.219

점진적인 개발 방식을 사용하면 지속적으로 작은 릴리즈를 하고 사용자의 피드백을 받아 개선하게 되니까, 점진적인 유지보수라고 부를 수도 있지 않을까? 처음에 돌고래 스몰토크를 써봤을 때 받은 인상도 비슷한데, 보통의 개발은 아무것도 없는 상태에서 기능을 생성해나가는 느낌이라면, 돌고래 스몰토크에서는 이미 잘 돌아가는 시스템을 리펙토링 해서 기능을 추가해나가는 느낌이었다.

하지만 유지보수 단계에서 “기존 시스템의 설계 컨텍스트 안에서 솔루션을 설계한다.”라는 것이 가장 큰 차이점인데 이는 생각보다 훨씬 어려운 작업이라고 한다. 그 이유는,

설계로 전환하는 시점에서 요구사항의 폭발적 증가, 대부분의 문제에서 설계 솔루션이 하나만 있는 것은 아니라는 사실, 설계는 복잡하고 반복적인 과정이라는 사실, 문제의 복잡성이 25% 증가하면 솔루션의 복잡성은 100% 증가한다는 사실. 이 모든 사실을 조합하면, 설계는 어렵고, 지적이며, 창조적인 작업이란 것을 알 수 있다. 여기서 말하려는 것은 역설계(undesign, 이미 구축된 시스템의 설계를 역공학으로 알아내는 것)라 부를만한 것으로, 이는 최소한 원래의 설계 작업만큼 복잡하다.

p.220

유지보수를 귀찮은 문제를 고치는 하찮은 작업으로 보기 쉽지만, 위의 증거들을 통해서 중요한 솔루션 개발 작업이며, 신규 개발에 필요한 것 이상의 높은 기술을 요구하는 작업이란 사실을 알 수 있다.

하지만 현실에서는 유지보수를 하찮은 작업으로 보는 경우가 많으므로 (담당자 스스로도!) 신입사원이나 경력이 적은 개발자에게 유지보수 업무를 맡기고, 실력이 좋은 개발자는 신규 개발에 투입되는 일이 흔하다. 그렇다보니 초기의 설계를 충분히 이해하지 못한 상태에서 코드의 수정이 이루어지고, 코드는 점점 더 엉망이 되어간다. 그러면 다시 새로운 시스템의 신규 개발이 시작되고 실력있는 사람들은 이 일에 투입된다. 기존에 유지보수를 하던 인력은 이 “실력있는 사람”들이 만든 또 다른 시스템을 유지보수 하게 된다. 불행하게도 여태까지의 내 경험과 일치하는 내용이다.

더 좋은 소프트웨어 공학 기술로 개발하면 더 많은(더 적은 게 아니라) 유지보수가 필요하다. -중략- 이런 시스템은 더 많은 수정이 가해지기 때문에 다른 시스템보다 더 오래 유지된다. 그리고 이런 잘 구축된 시스템은 개선하기가 쉽기 때문에 더 많은 수정이 가해진다.

p.226

이 사실은 “유지보수는 문제가 아니라 해결책이다.”라는 사실에 대한 흥미로운 예다. 유지보수 활동을 솔루션으로 본다면, 더 많은 작업을 할수록 좋다고 생각할 수 있다. 그러나 유지보수를 문제로 보는 시각에 묶여 있으면, 유지보수 활동이 늘어나는 것을 좋게 볼 수 있는 방법이 없다.

p.227

Written by muscly

January 18th, 2010 at 12:00 am

소프트웨어 공학의 사실과 오해 7 – 검토와 검사

with 2 comments

http://www.yes24.com/24/goods/1418676

검토와 검사

비약에 가까운 기법이 하나 있는데, 아이러니하게도 이 기법은 소프트웨어 오류 제거 활동에서 제외되어 한 구석에 처박혀 있다. 엄격한 검사가 그것으로, 소프트웨어에 포함된 오류를 찾기 위해 노력을 쏟는 이 기법은 거의 비약이라 할 수 있다. 연구 조사를 거듭한 결과 검사는 테스트 케이스를 실행시키기도 전에 소프트웨어 제품에 포함된 오류의 90%를 발견할 수 있다는 것이 밝혀졌다.

p.191

그런데도 불구하고 검토와 검사가  CASE 도구나 여러 방법론과 같은 더 못한 것들도 받던 찬사를 받지 못하는 이유는 아래의 4가지.

  • 검사로 돈을 버는 메이저 벤더는 거의 없다.
  • 검사에는 새로운 것도 없고 따라서 시장성도 없다.
  • 검사는 소프트웨어 생명주기의 뒤쪽 단계에 있는 보이지 않는 부분으로 간주된다.
  • 검사는 효율적이긴 하지만, 녹초가 될 정도로 정신을 집중해야 하는 고된 작업이다.

대부분의 방법론이나 프랙티스의 유행의 배경에는 해당 제품으로 돈을 버는 메이저 벤더가 있어왔다는 것이 이책의 일관된 주장이다. 실제로 은 탄환Silver Bullet이란 없기 때문에 애초에 유행할 것이 없지만, 과대선전자들에 의해 근거없는 유행이 생겨난다는 것.

제품의 출시후에 어떤 일이 있었는지 숙고하거나 앞으로 어떻게 개선할 수 있을지에 대해 기록하는 회고를 시행하는 조직이 거의 없다는 얘기에 이어서 아래의 내용이 나온다.

그 결과 소프트웨어 프로젝트에서 배운 모든 교훈은 버려지거나, 프로젝트가 끝날 때 바람과 함께 날아가 버린다. 왜 그럴까? 소프트웨어 분야의 광폭한 일정으로 인해, 어제 프로젝트에서 일하던 프로그래머들이 이미 내일 프로젝트로 흩어져 배치돼 버리기 때문이다. 그리고 거기서는 새로운 일정에 묶여 몇 달 전에 어떤 일이 있었는지 생각할 겨를도 없다.

p.200

결국 소프트웨어 분야는 한 자리에 처박혀 매 프로젝트마다 같은 실수를 반복하고 있고. 소프트웨어 분야의 지혜Wisdom는 증가하지 않는다는 얘기.

어떤 문제에 대한 올바른, 최적의 솔루션이 딱 하나만 있는 경우는 거의 없다고 했던 것을 상기하기 바란다. 솔루션을 검토할 때 다른 개발자가 선택한 방법의 관점에서 검토하는 것은 자신의 방법 관점에서 검토하는 것보다 어렵다. 다른 사람의 신발을 신고 먼 길을 걷는 것은 쉬운 일이 아니다.

p.205

동료 검토Peer Review에는 기술적 측면과 사회적 측면을 모두 중시해야 하는데, 위와 같이 기술적 검토 작업을 훌륭히 하는데 필요한 ‘집중’으로 인해 검토의 사회적 측면에 대한 주의가 감소한다고 한다.

엄격함을 달성하기 위한 집중 때문에 사회적 문제를 해결하기 위해 남겨둔 에너지까지 모두 소모돼 버린다. 따라서 검토기간 동안의 사회적 문제는 심각해질 수 있다. 비자아적 프로그래밍(egoless programming)을 부르짖지만, 우리는 대부분 자신이 작업하는 제품에 이성과 감정을 투영하게 되고, 이로 인해 다른 사람이 우리의 작업을 검토하면 쉽게 상처받는다. -중략- 모든 자아가 위태로워지고 사회적 방어 메커니즘이 감소한 상태에서, 사회학적 폭발을 초래하는 것은 그리 오래 걸리지 않는다.

p.206

동료 검토 하면서 얼굴 붉히는 경험은 다들 있을 것 같다. 잘 먹히는 해결책을 제시할 수 있으면 좋겠지만, 기술적 측면과 사회적 측면에 모두 주의를 기울여야 한다는 사실이라도 업계에 널리 퍼졌으면 좋겠다. 문제가 인식되면 해결책이 도출되는 것은 시간문제가 아닐까.

개인적으로는 저자 워크숍 방식을 코드 리뷰에 사용해보고 싶은 바램이 있다. (해보신 분 있으실지도)

Written by muscly

January 14th, 2010 at 12:00 am

소프트웨어 공학의 사실과 오해 6 – 테스트

without comments

http://www.yes24.com/24/goods/1418676

테스트

연구에 따르면, 프로그래머가 모든 코드를 완전히 테스트했다고 말할 때, 보통 55~60%의 로직 경로만이 실제로 테스트된 것이라 한다. 이는 소프트웨어 제품의 복잡성을 반증하는 것이기도 하고, 소프트웨어를 작성한 사람조차도 그들이 작성한 것에 대해 완전히 이해하지 못함을 보이는 것이기도 하다.

p.172

여기서 알 수 있는 것은, 수많은 종류의 테스트 방법이 존재하지만 소프트웨어 제품의 복잡성 때문에 완벽한 테스트는 불가능하다는 것이다. 이 때문에 (1)테스트를 수행하는 데 있어 타협할 수 밖에 없고, 적절히 선택해 타협하는 것이 매우 중요하며, (2)대부분의 주요 소프트웨어 제품이 오류를 포함한 채 출시되는 것 또한 놀랄만한 일이 아니다(순진한 사람들만이 오류 없는 소프트웨어를 기대한다).

p.173

많은 소프트웨어 전문가들이 오류 없는 소프트웨어를 만드는 것이 가능하다고 주장하며 이를 달성하지 못한 회사나 조직을 비난하지만, 이번 사실에서 명확히 알 수 있듯이 그 영광된 목표는 단지 아주 작은 규모의 소프트웨어 프로젝트에서나 가능할 것이다. 이제, 오류 없는 소프트웨어란 불가능한 목표는 포기하고, 매우 심각한 오류가 없는 소프트웨어 제작과 같은, 좀더 현실적이고 실현 가능한 목표에 집중하는 것이 중요하다.

p.174

어느 정도 규모가 있는 C++ 프로젝트에 유닛테스트를 적용해본 것은 작년이 처음이었는데, 왜 55~60%의 로직 경로만이 테스트 되는지 이해할 수 있을 것 같다. 제품 수준의 코드에는 인자의 유효성 체크, 상태의 유효성 체크, 실패에 대한 체크 등으로 엄청나게 많은 분기가 발생하는데 이런 예외 상황을 완벽하게 테스트하는 것은 비용대비 효율이 떨어지기 때문이다. 높은 테스트 커버리지는 반드시 달성해야만 하는 목표라기 보다는, 프로젝트의 여러 목표 중에 하나가 되어서 우선도를 따져보는 것이 맞는 것 같다. 적당한 테스트 커버리지에 대해서는 지난 번 포스팅 어느 정도의 테스트 커버리지가 필요할까를 참조.

100%의 테스트 커버리지가 가능하다 하더라도, 이는 충분한 테스트 기준이 아니다. 대략 소프트웨어 결함의 35%는 누락된 로직 경로에서, 40%는 로직 경로의 특정 조합을 실행할 때 나타난다. 이런 것들은 100% 커버리지로도 잡히지 않을 것이다.

p.176

100%의 구조적 커버리지가 발견할 수 있는 것은 단지 25%의 오류라는 의미다. 저자가 가진 오류 데이타베이스로부터 산출한 비율이라는 점도 감안하자.

소프트웨어 테스트 도구가 널리 사용되지 않는 데는 세 가지 주요 요인이 있다. 1. 소프트웨어 분야의 경영진과 학계는 모두 앞쪽 단계를 훨씬 더 중요하게 보이도록 만들었다. -중략- 2. 뒤쪽 단계의 작업은 기술적으로 너저분하다. -중략- 3. 생명주기의 뒤쪽 단계에는 일정 압박이 심하다. -중략-

p.181, 182

소프트웨어 업계는 요구분석, 설계, 구현을 지나서 테스트에 대한 관심이 높아지고 있는 것 같다. 앞쪽의 단계에서 은 탄환Siver Bullet을 찾지 못해서 자꾸만 뒤쪽 단계에서 기회를 찾으려 이동한다는 얘기도 있지만,  소프트웨어 분야의 모든 행위에 대해서 한 번씩 조명을 하고, 쓸데없는 미신이나 착각, 오해를 없앨 수 있었으면 하는 바램이다.

Written by muscly

January 13th, 2010 at 12:00 am

소프트웨어 공학의 사실과 오해 5 – 설계

without comments

http://www.yes24.com/24/goods/1418676

설계

요구사항을 설계로 옮겨갈 때 솔루션 프로세스의 복잡성 때문에 ‘파생 요구사항’(특정 설계 솔루션에 대한 요구사항)이 급증한다. 이런 설계상의 요구사항은 종종 원래의 요구사항보다 50배 넘게 늘기도 한다.
- 중략 -
모두들 요구사항 추적 용이성(traceability)이 바람직하다고 생각하지만 (부분적으로는) 요구사항의 폭발적 증가 때문이 이를 실현하기는 어렵다.

p.145, 146

현재 진행중인 프로젝트의 프로덕트 백로그(요구사항 리스트 비슷한 것)를 사용자 관점의 것과 개발자 관점의 것으로 2개 관리하자라는 말을 들었을 때, 이 얘기를 하면서 반대했던 기억이 있다. 개발자 관점의 것은 사용자 관점의 것보다 50배나 많아질 수도 있으니까.

소프트웨어 문제에 대해 최상의 솔루션이 하나인 경우는 거의 없다. – 중략 – 문제가 정의됐을 때 훌륭한 설계자들이 모두 동일한 최상의 설계 솔루션을 제시하는 경우는 거의 없다. (“최고의 설계자들이 모인 방에서 두 명의 설계자가 동의한다면 그게 다수 의견이다.”라는 말은 소프트웨어 분야에서 내가 좋아하는 인용구 중 하나다.)

p.150

전적으로 동의하지만, 동시에 이 얘기가 오해를 불러일으킨다고 생각한다.  좋은 설계를 찾기위한 노력을 게을리 하는데 좋은 구실이 되기 때문이다. 하지만 분명히 좋은 솔루션과 나쁜 솔루션이 존재하므로 더 좋은 솔루션을 찾기 위한 노력은 계속되어야 한다. 또 다른 오해는 몇 가지 설계를 두고 논쟁이 생겼을 때 어차피 정답은 없다는 이유로 토론을 회피하는 것이다. 하지만 이 경우에 논쟁의 대상이 되는 몇 가지 설계가 최상의 솔루션들인 경우는 거의 없으며 기본적인 설계 원칙들도 지키지 못하는 경우가 많다.  한 마디로 나같은 보통의 개발자에게는 해당되지 않는 얘기다.

전문 설계자들은 설계 작업에서 핵심을 파악할 때 경험적, 시행착오적 접근방법을 사용한다는 것이다. 관련된 문제에 대한 예전의 설계를 기반으로 해서 설계 솔루션을 하나 생각하고, 마음속으로 이 솔루션에 대표적인 데이터를 조금 넣어보고, 이 데이터에 대한 작동을 모의실험한 다음, 이 솔루션에서 데이터에 대한 출력을 뽑아낸다. – 중략 – 후보 솔루션을 약간 수정해 확인된 문제를 제거하고, 샘플 데이터를 다시 적용해본다. 출력이 맞게 나올 때까지 이 과정을 반복한다.

p.154, 155

다들 이런 경험을 가지고 있을 것 같다. 책에서는 이런 설계 방식을 ‘편의적’ 설계라고 부르는데, 이런 연구 결과를 토대로 다음과 같은 결론을 도출한다.

설계는 예측 가능한, 구조화할 수 있는, 규격화할 수 있는 프로세스와는 거리가 멀고, 너저분하고 시행착오적인 것임을 알 수 있다. 그리고 기억해야 할 것은, 이 연구결과는 최고의 설계자들을 조사해서 얻은 것이라는 점이다. 이보다 못한 설계자들은 훨씬 더 너저분한 프로세스로 작업할 것임은 쉽게 상상할 수 있다.

p.155

“너저분한 프로세스”에 가슴이 아프다. ^^;;

복잡한 프로세스로 인해 최적의 설계는 보통 불가능하므로, 우리는 ‘만족스러운’ 솔루션을 위해 노력해야 한다. 만족스러운(최적이 아니라) 솔루션은 훌륭한 설계에 대한 조건을 충분히 만족시켜, 그 접근방법을 선택해 작업을 계속 하는 데 따르는 위험을 감수할만한 가치가 있는 것을 의미한다(최적의 설계는 불가능하거나 비용대비 효율이 낮다는 전제하에)

p.156

현실과 적절하게 타협할 필요가 있다라는 말로 이해할 수 있는데, 나같이 “만족스러운 솔루션”을 만드는 것도 벅찬 사람에게는 해당되지 않는 얘기다.