|
실용주의 프로그래머 2장 실용주의 접근법에 대해 발표할 22기 최준형입니다.
실용주의 프로그래머란 책이 어떤 책 라는 것은 다들 기억할 것이라고 생각하고, 2장에 내용에 대해 잠깐 말씀 드리자면,
소프트웨어 개발의 모든 차원에 적용가능한 팁과 요령이 있고, 일반적인 진리와 같은 아이디어들이나 사실상 보편화된 프로세스들이 있습니다.
하지만, 이러한 이런 접근법들은 문서로 만들어진 경우는 극히 드물다고 할 수 있습니다. 2장에서는 이런 아이디어들과 프로세스들을 한데 모아서 보려고 합니다.
잘 이해가 안가시죠? 뒤에 더 자세히 설명해 드리겠습니다.
목차로 보면 중복과 해약
직교성
가역성
예광탄
프로토타입과 포스트잇
추정
이렇게 6가지가 있는데, 이번 장에도 역시 이해가 잘 가지 않으시죠?
다음 슬라이드를 보시면서, 차근차근 설명해 드리겠습니다.
프로그래머로서 우리는 지식을 수집하고, 조직하고, 유지하며, 통제합니다.
불행히도 지식은 고정적이지 않고 계속적으로 변화합니다.
이러한 모든 불안정성은 우리가 유지 보수 모드에서 지식을 재조직하고 재 표현하는데 대부분의 시간을 보내게 된다는 것을 의미 합니다.
우리가 이해하고 있는 것이 날마다 바뀌거나 설계를 하거나 코딩 하는 도중에 새로운 요구 사항이 도착하는 것에 대한 유지 보수를 하게 됩니다.
대부분의 사람들은 유지 보수가 버그를 고치고 기능을 개선 하는 것을 의미 하기 때문에, 애플리케이션이 출시 되었을 때 비로소 유지 보수가 시작 된다고 알고 있는데, 프로그래머들 은 늘 유지 보수 모드에 있습니다 우리가 이해 하고 있는 것은 날마다 바꾸고. 설계를 하거나 코딩을 하는 중에 새로운 요구 사항이나 환경이 변할 수도 있습니다. 이유가 무엇이건 간에, 유지 보수는 별개의 활동이 아니며, 전체 개발 과정의 일상적인 부분 입니다. 유지 보수를 하려면 사물의 표현 방식, 즉 애플리케이션에 들어 있는 지식의 캡슐들을 찾아내고, 또 바꿔야 합니다.
문제는 정확한 정의와 프로세스 그리고 프로그램을 개발하는 중에 지식을 중복해 넣기 쉽다는 것입니다. 따라서 이런 소프트웨어를 신뢰성 높게 개발하고 개발을 이해하고 유지 보수 하기 쉽게 만드는 유일한 길은 우리가 DRY원칙이라고 부르는 것을 따르는 것이라 생각합니다.
서론이 좀 길었다고 생각합니다. 단적으로 생각해서 DRY원칙이 지켜 지지 않으면, 만약 하나를 바꾼다면, 나머지 것들도 싹다 바꿔야 함을 기억해야 합니다.
어떠한 프로그램을 만드는데, 자주 쓰는 내용을 함수로 따로 빼는 것도, DRY원칙이라고 생각할 수도 있습니다. C로 예를 들면, main문에 자주 쓰는 내용을 계속 반복해서 쓰면, 만약 그 자주 쓰는 내용에 오류가 생겼을 때, 일일이 다 고쳐야 하는데, 함수로 따로 빼놓으면 그 함수만 수정하면 되기 때문에, 유지 보수 하는데 훨씬 쉬울 것이라고 생각합니다. 다음 슬라이드에서 간단한 코드로 예를 보여 드리겠습니다.
아마 여기 있는 분들은 센스가 있기 때문에 이 코드가 무엇이 잘못되었는지 한번에 보일 것입니다. 똑같은 문장이 계속 반복되고 있다는 것을 알고 계실 겁니다.
다음 그림은 좀 더 간단히 코드를 만든 것입니다. 첫 번째 그림에서 더하기를 빼기로 바꾸려면 4번이나 코드를 수정해야 하지만, 두 번째 그림에서는 한번만 수정해 주면 됩니다. 한번에 눈에 들어오라고 진짜 많이 쉬운 코드를 만들었습니다.
중복이 생기는 이유에는 위와 같이 5가지 경우가 있습니다.
가장 먼저 강요된 중복이란? 개발자들은 다른 선택이 없다고 느낍니다. 환경이 중복을 요구하는 것처럼 보입니다. 우리는 자신의 코드에 주석을 달도록 교육받습니다. 훌륭한 코드에는 주석이 많다고 배우지만, 우리들은 코드에 왜 주석이 필요한지는 배우지 않습니다. 나쁜 코드야말로 많은 주석을 필요로 합니다. DRY 원칙은 낮은 차원의 지식은 그것이 속하는 코드에 놔두고, 주석은 다른 높은 차원의 설명을 아껴 두라고 말합니다. 그러지 않으면 지식을 중복하게 되며, 변경할 때마다 매번 코드와 주석 모두를 바꿔야 합니다. 주석은 낡게 될 것이고, 믿을 수 없는 주석은 주석이 전혀 없는 것보다 더 심각한 문제를 만들어 내게 됩니다.
두 번째로는 개발자들의 부주의로 생기는 중복입니다. 자신이 중복을 하고 있다는 것을 깨닫지 못하고 사용하면서 생기는 것입니다. 더 자세한 설명은 뒤에서 퀴즈로 설명해 드리겠습니다.
세 번째로 모든 프로젝트는 시간의 압박을 받게 되는데 이것으로 인해 결국 지름길을 택하게 되어서 복사하여 약간만 바꾸면서 중복이 발생하게 됩니다. 이 중복은 발견하기도 쉽고 다루기도 쉬운 형태지만 나중의 고통을 피하기 위해서는 훈련이 필요 합니다. '돌아가는 길이 지름길이라'라는 진부한 격언을 기억하십시오.
네 번째는 개발자간의 중복입니다. 이것을 막기 위해서는 다른 사람의 소스 코드와 문서를 읽어 보는 것이 좋습니다. 또 개발자간에 적극적이고 빈번한 소통을 장려하는 것입니다.
직교성이란? 기하학에서 빌려 온 용어로, 그래프의 축과 같이 두 직선이 직각으로 만나는 경우 직교한다고 말합니다. 벡터의 입장에서 보면, 두 개의 선은 ‘독립적’입니다. 두 선 가운데 하나의 방향으로 움직여도 나머지 선 위로 투영된 여러분의 위치는 변하지 않습니다.
관련 없는 것들 간에 서로 영향이 없도록 하라!
하나의 예를 들어 보려고 합니다. 우리가 난방 설비를 감시하고 제어하는 복잡한 시스템을 구현한다고 가정해 봅시다. 원래의 요구 사랑은 그래픽 사용자의 인터페이스만을 필요로 했지만, 전화 버튼을 통해 설비를 제어하고 음성 응답을 들을 수 있도록 하는 기능이 추가되었습니다. 직교적으로 설계된 시스템이라면 사용자 인터페이스와 연관된 모듈만 수정해 추가된 요구 사항을 수용할 수 있습니다. 설비를 제어하는 로직은 바꿀 필요가 없습니다. 시스템을 주의 깊게 설계했다면 같은 제어 로직 코드를 이용해 전화 버튼을 통해 설비를 제어하는 것과, 그래픽 유저 인터페이스 모두 지원할 수 있을 것입니다.
직교성은 생산성 향상에 도움이 될 수도 있습니다. 변화가 줄어들어 개발 시간과 테스트 시간이 줄어들 수 있습니다. 상대적으로 작고, 독립적으로 되어 있는 컴포넌트(s/w개발을 마치 레고 블록을 쌓듯이 쉽게 할 수 있는 기술, 모듈(구성 단위)를 미리 만든 뒤 필요한 기술을 개발 후 조립)를 작성하는 것이 하나의 커다란 코드 덩어리를 만드는 것이 더 쉽습니다. 그리고 재사용을 촉진할 수 있습니다. 컴포넌트들이 명확하고 잘 정의된 책임이 할당되어 있다면 애초의 구현자들이 생각지도 못한 방법으로 컴포넌트를 결합 할 수 있습니다.
직교성은 리스크 감소에 도움을 줍니다. 감염된 코드는 격리되게 됩니다. 여기서 감염된 코드란, 어떠한 오류나 로직이 잘못된 코드들을 말합니다. 어떤 모듈이 병에 걸렸다 해도 시스템의 나머지 부분으로 증상이 전파될 확률이 낮습니다. 게다가 그 부분만 도려내고 새롭고 건강한 놈으로 이식해 넣기도 쉽습니다.
프로젝트 팀 주도 직교성 있게 구성하여야 효율적으로 짰다고 할 수 있습니다. 팀 내 업무가 겹치는 영역이 많다면 구성원들은 책임 영역에 대해 혼동하게 되고 뭘 하나 바꾸려면 그들 중 누구라도 영향을 받을 수 있기 떄문에 전체 팀원이 모여야 하는데 직교성있게 짰다면 개별 변화에 대한 토론에 참여하기 위해 팀원 전체가 모이는 일이 없게 됩니다. 강사님이 말씀하셨듯이 팀 전체 미팅 시간을 최소화 할 수 있고, 필요한 사람들 끼리만 모여 미팅 시간을 짧게 할 수 있습니다.
가역성이란 시간이 흐르는 동안 물체의 운동이 변화했을 때 시간을 거꾸로 되돌린다면 처음의 물체 상태로 되돌아갈 수 있는 성질을 말합니다.
이것은 프로젝트 초기에 내린 결정대로 진행하다가 도중에 막히거나, 다른 더 좋은 방법이 있으면 처음으로 돌아가 다른 방법 이나,더 좋은 방법으로 프로젝트의 방향을 바꿀 수 있다는 말과 같다고 생각합니다. 완벽한 것, 최종 결정이라는 것은 없습니다. 우리는 소프트웨어를 개발하는 속도는 요구 사항, 사용자, 하드웨어의 변화를 앞지를 수 없습니다. 누구도 미래에 대해서는 알 수 없으며, 우리라고 예외는 아닙니다.
책대로의 목차로는 여러분들도 들어 보신 예광탄이 먼저 나오는데, 저는 프로토타입과 포스트잇부터 말씀 드리려고 합니다.
예광탄은 많이 여러분들도 많이 들어 보시고 강사님께서도 예광탄을 쏘신 적이 있기 때문에, 먼저 지금 미니 프로젝트 하면서 다들 하고 있는 프로토 타입부터 말씀 드리겠습니다.
먼저 프로토 타이핑을 예를 들어 설명해 드리겠습니다. 자동차 제조 업계에서는 신차 디자인을 위해 다양한 프로토타입읠 만들어 봅니다. 이때 각 프로토 타입은 공기 역학, 스타일, 구조적 특성 등 자동차의 특정 측면을 테스트하기 위해 설계됩니다. 디자인 부서라면 나무와 테이프만으로도 충분히 프로토 타입을 만들 수 있습니다. 어떤 회사는 한발 더 나아가 모델링의 상당 부분을 컴퓨터를 이용하여 작업하고, 이를 통해 비용을 획기적으로 줄이고 있습니다. 위험 요소나 불확실한 요소를 실제 제품을 만들어 보지 않고도 제거할 수 있는 것입니다.
프로토 타이핑은 학습 경험이며, 프로토 타입의 가치는 생성된 코드에 있는 것이 아니라 이를 통해 배우게 되는 교훈이 있습니다. 이것이 프로토 타이핑의 진정한 핵심입니다.
프로토 타입을 통해 조사할 대상은 무엇이 있을까요? 위험을 수반하는 모든 것이 됩니다. 또한 이전에 해본 적이 없는 것, 최종 시스템에 매우 중요한 것 등이 프로토 타입의 대상이 됩니다. 증명되지 않았거나, 실험적이거나, 의심이 가는 것, 심적으로 편하지 않은 것 모두가 프로토 타이핑의 대상이 될 수 있습니다.
프로토 타입은 세부 사항을 생략하고 시스템의 특정 측면에 초점을 맞추기 때문에, 미리 선정한 입력 데이터와 한가지 메뉴 항목에서만 작동하면 되기 때문에, 제한된 기능만을 제공하기도 합니다. 그리고, 프로토 타입의 에러 검사는 불완전 할 수 있고, 때론 완전히 무시될 수도 있습니다. 미리 정의된 방법대로 실행시키지 않는다면 와장창 망가지고 불꽃놀이처럼 타 버릴 수도 있지만, 충분이 가치가 있는 것입니다.
많은 프로토 타입들이 고려 중인 전체 시스템을 모델링 하기 위해 만들어 집니다. 예광탄과는 달리 프로토 타입 시스템의 모듈이 꼭 기능을 가져야 하는 것은 아닙니다. 사실 아키텍처 프로토 타이핑을 할 때 코드를 작성하지 않고, 화이트 보드, 포스트일 등을 사용해도 됩니다. 전체적으로 시스템이 어떻게 동작할지에 대한 감을 잡는 것 입니다.
프로토 타입을 코드로 만들 때는 시작하기 전에 항상 모든 사람에게 여러분이 폐기 처분할 코드를 작성하고 있다는 사실을 이해시켜야 합니다. 프로토 타입은 그것이 프로토 타입임을 모르는 사람들에게는 매우 매력적일 수 있기 때문에, 코드는 폐기할 것이고, 불완전하며 완성할 수 없다는 사실을 분명이
주지시켜 줘야 합니다. 그들에게 나무와 테이프로 멋진 자동차를 만들 수는 있지만, 나무 자동차를 타고 러시아워에 운전할 수는 없다는 사실을 인지 시켜 줘야 합니다.
예광탄이란 말을 강사님께 많이 들어 보셨을 것 입니다. 남자분들은 예광탄이 무엇인지 다 알고 계실 것이라고 믿고, 그래도 다른 분들을 위해 잠깐 예광탄에 대해 설명하자면, 예광탄은 어둠에서 사격 시, 그 안에 든 인 성분이 발화하여 총알을 맞은 것과 총 사이에 빛의 궤적을 남기게 됩니다.
이제 예광탄에 대해서 조금 이해를 하셨다면, 예광탄이 우리한테 주는 것이 무엇인지를 알아보도록 합시다.
예광탄 코드는 앞에서 말했던 프로토 타입과는 달리 버리려고 만드는 것이 아닙니다. 그것은 계속 사용할 코드입니다. 예광탄 코드에도 상용 코드와 마찬가지로 모든 에러 검사, 구조화, 문서화, 자기 검사가 포함됩니다. 단지 예광탄 코드에는 아직 완전한 기능이 들어 있지 않을 뿐입니다. 하지만 시스템을 구성하는 요소를 모두 연결해 놓은 후라면 목표물에 얼마나 가까이 다가섰는지를 확인할 수 있으며, 필요하다면 조정도 할 수 있습니다. 그렇게 해서 일단 목표물을 맞춘다면 기능 추가하는 일은 좀 더 쉬울 것 입니다.
예광탄은 지금 맞추고 있는 것이 무엇인지를 보여 주긴 하지만, 그것이 꼭 목표물이라는 보장은 없습니다. 그럴 경우 목표물이 맞을 때까지 조준을 옮겨야 하는 게 핵심입니다. 예광탄 코드도 마찬가지인데, 일이 어떻게 될지 100% 확신할 수 없는 상황에서 사용됩니다. 그러므로 처음 몇 번 시도 때 목표에 맞지 않더라도 놀랄 필요가 없습니다. 사용자들이 원하던 게 아닐 수도 있고 있습니다. 지금 있는 것을 목표물에 가까이 가져가려면 어떻게 바꾸어야 할지 생각하는 것에 감사해야 합니다.
아마 예광탄 코드라는 개념은 좀 더 공격적인 이름이 붙었을 뿐 프로토 타이핑과 다를 바 없다고 생각하는 사람도 있을 것입니다. 그러나 확실히 다른 점이 있습니다. 프로토 타입은 최종 시스템의 어떤 특정한 측면을 탐사해 보는 것이 목표입니다. 진짜 프로토 타입 방식을 따른다면, 어떤 개념을 구현해 보려고 시도할 때 대충 끼워 맞춘 것들을 모두 버린 다음, 실험 과정에서 얻은 교훈을 바탕으로 다시 코드를 만들어야 할 것입니다.
한번 정리해 보자면, 프로토 타입은 나중에 버릴 수 있는 코드를 만들고, 예광탄 코드는 기능은 별로 없지만 완결된 코드이며, 최종 시스템의 골격이 되는 것 입니다. 프로토 타입을 예광탄이 하나라도 발사되기 전에 먼저 일어나는 정찰과 정보 수집으로 생각하면 될 것입니다.
얼마나 정확한 것이 충분히 정확한 것인가?
-> 어떤 의미에서 모든 답은 추정치 입니다. 단지 누가 남보다 좀 더 정확한지가 다들 뿐입니다. 그러므로 누군가 추정치를 물었을 때, 질문자가 매우 높은 정확도의 답을 요구하는지, 아니면 단순히 큰 그림만을 요구하는지를 알아봐야 할 것입니다. 추정에서 한 가지 재미있는 사실은 사용하는 단위가 결과의 해석에 차이를 가져온다는 것입니다. 만약 무언가를 끝내는데 130일 정도의 근무일 동안 일해야 한다고 말한다면, 듣는 사람은 상당히 가까운 시일 내에 끝날 것이라 생각하며 정확한 기대하게 됩니다. 하지만 대략 6달 정도 걸리게 된다고 말하면, 지금부터 5~7달 사이 언젠가 끝날 것이라 생각 할 것입니다. 두 숫자는 같은 기간을 이야기하지만, 130일은 여러분이 느끼는 것보다 더 높은 정확성을 내포합니다.
-> 추정에 대해서 조금 알아봤으니, 프로젝트 일정 추정하기를 알아보겠습니다.
요구 사항 체크
위험 분석하기
설계, 구현, 통합
사용자와 함께 검증하기
이것들을 하다 보면 프로젝트의 일정을 정할 수 있는 유일한 방법은 진행되는 해당 프로젝트를 경험하는 것뿐이란 사실을 알게 됩니다. 그러므로 코드와 함께 일정도 반복하며 조정하여야 합니다. 구현하면서 얻는 경험을 이용해서 프로젝트의 시간 척도를 세밀히 조정해야 합니다. 프로젝트 초기에는 얼마나 많은 반복이 필요할지에 대해 막연히 생각 할 수 밖에 없을 것입니다.
어떤 방법론은 반복 횟수를 초기 계획의 일부로 포함 시킵니다. 하지만 소규모 프로젝트가 아니라면 이는 오히려 실수가 될 수 있습니다. 전에 같은 팀원에 같은 기술을 사용하여 비슷한 애플리케이션을 만들어 본 경험이 없다면 단순한 추측에 불과합니다. 그러므로 초기 기능의 구현과 테스트를 마친 후 이를 첫 번째 반복의 끝으로 삼아야 합니다. 이 경험에 기반해 반복의 횟수와 각 반복에서 무엇을 할지에 대한 초기 추측을 다듬을 수 있습니다.
여기까지 제 발표는 여기까지입니다. 질문있으신분은 질문 하시길 바랍니다.