테스트 주도 개발의 궁극적인 목표는 작동하는 깔끔한 코드(clean code that works) 이다.
작동하는 깔끔한 코드가 훌륭한 목표임을 말해주는 이유에는
그럼 어떻게 하면 작동하는 깔끔한 코드를 얻을 수 있을까?
자동화된 테스트로 개발을 이끌어 나가는 방식을 테스트 주도 개발 이라고 한다. 이 TDD에서는 아래와 같은 단순한 두가지의 규칙만을 따른다.
하지만 이 단순한 규칙이 가지는 의미들로 인해 집단 차원의 복잡한 행동패턴이 만들어 진다.
그리고 위의 두가지 규칙에 의해 프로그래밍 순서가 다음과 같이 결정된다.
1. 빨강 - 실패하는 작은 테스트를 작성한다. 처음에는 컴파일 조차 안될 수 있다.
2. 초록 - 빨리 테스트가 통과하게끔 만든다. 이를 위해 어떤 ‘죄악’ 을 저질러도 좋다.
3. 리팩토링 - 일단 테스트를 통과하게만 하는 와중에 생겨난 모든 중복을 제거한다.
이런식으로 프로그래밍하는게 가능하고, 코드의 결함률을 극적으로 낮추는 것과 코드가 정말로 깔끔해져서 팀원 누구나 코드를 쉽게 알아볼 수 있게 해줄 정도로 이 모든게 가능하다면, 실패하는 테스트를 통과시키기 위해 필요한 만큼만 코딩하는 것은 다음과 같은 사회적 함의도 갖게 된다.
왜 소프트웨어 엔지니어가 자동화된 테스트를 만드느라 추가 작업을 해야하는 걸까? 왜 엄청나게 복잡한 설계를 머릿속에서 그려낼 수 있는 소프트웨어 엔지니어들마저 작은 단계를 종종걸음으로 밟아나가야만 하는가?
이를 이 책에서는 용기 때문이라고 표현한다.
TDD는 개발하면서 나타나는 두려움을 관리하는 방법이다.
여기서 말하는 두려움이란 정말 어려운 문제라서 시작 단계인 지금은 어떻게 마무리될지 모르는 상황 의 두려움을 말한다.
이 상태에서 두려움은 우리를
1. 망설이게 만들고
2. 커뮤니케이션을 덜 하게 만들고
3. 피드백 받는 것을 피하도록 만들고
4. 까다롭게 만든다.
이중 어떠한 것도 프로그래밍에 도움이 되지 않는다. 특히 어려운 코드를 짤 때에는 더더욱.
그래서 문제는 우리가 어려운 상황에 어떻게 맞설 것인지이다.
TDD를 배우는 대다수의 사람들은 자신의 프로그래밍 방법이 영원히 바뀐다는 경험을 한다곤 한다. 이 방법을 배운다면 원래의 우리보다 더 많은 테스트를 더 일찍 작성하고, 또 더 작은 단계로 작업하고 있는 자신을 볼 수 있을 것이다.
또 한편 몇몇의 소프트웨어 엔지니어들은 TDD를 배운 후에 다시 원래 습관으로 돌아가서 작업하다가 기존의 습관으로는 일이 진척되지 않을 때에만 TDD를 사용하기도 한다.
물론 보안 소프트웨어나 동시성(concurrency) 같이 순수하게 TDD로만 풀어낼 수는 없는 프로그래밍 작업들이 분명히 있다.
그래도 이 책을 끝까지 읽고 나면
본격적으로 TDD 예제를 다루기 전에 money 예제의 배경에 대해서 다뤄 볼 것이다.
WyCash라는 채권 포트폴리오 관리 시스템은 워드 커닝엄이라는 프로그래머와 그의 팀에 의해 개발된 프로그램이다. 이 만들어진 프로그램을 잠재 고객한테 선보이는 자리에서 달러 말고 다른 화폐로 채권을 다루는 것을 원한다고 한다. 과연 다른 화폐로 채권을 다룰 수 있도록 시스템을 수정할 수 있을까?
이 와이캐시는 객체와 객체 DB를 사용해서 쭉 개발되어 왔고. 계산의 근본적인 추상적 대상이라고 할 수 있는 Dollar 객체는 포맷팅과 계산 작업에 대한 책임을 모두 가지고 있었다.
그리고 지난 6개월동안 워드와 나머지 팀원들은 느릿느릿 Dollar 에서 그 책임들을 분리하여 Dollar에는 별 책임이 나아있지 않았다.
그래서 워드는 가중평균같은 복잡한 알고리즘(함수) 가 Dollar 객체 말고도 일반적인 Currency 객체로 계산이 가능하다는 것을 확인할 수 있었고, 이미 작동하던 것을 하나도 망가뜨리지 않고 새로운 기능을 넣어 작동시킬 수 있었다.
이렇게 함으로서 이틀만에 잠재적 시장이 몇 곱절이나 커졌고, 덕분에 와이캐시의 가치 역시 몇 배 늘어났다. 이렇게 많은 비즈니스 가치를 만들어 내는 능력에 요소들은 아래와 같다.
방법 : 워드와 와이캐시 팀은 시스템의 설계를 조금씩 성장시키는 지속적 경험이 필요했다. 그래서 탈바꿈의 기술을 훌륭히 수련했다.
동기 : 워드와 그의 팀은 와이캐시를 다중통화로 만드는 것의 비즈니스적 중요성을 분명히 이해하고, 외적으로 불가능해 보이는 작업을 시작할 용기가 있어야 했다.
기회 : 포괄적이고 자신감을 만들어 내는 테스트들, 잘 리팩토링된 프로그램, 설계 결정을 분리할 수 있는 프로그래밍 언어 등의 조합을 통해 에러의 요인이 거의 없었고, 설사 있더라도 에러를 손쉽게 파악할 수 있었다.
위의 3 요소 중 자기 프로젝트의 가치를 기술적인 마술을 이용해서 몇배로 늘릴 수 있는 동기를 갖는다는 것은 스스로 제어할 수 없는 문제이지만, 방법과 기회는 제어가 가능하다. 워드와 그의 팀은 탁월한 재능, 경험, 수양의 조합을 통해 방법과 기회를 만들어 냈다.
우리가 평범한 기술을 가진 소프트웨어 엔지니어이고 압력이 커지면 때로 굴복하고 지름길을 택한다고 하더라도, 위에 예시같이 마술처럼 프로젝트가 잘 되도록 할 수 있다.
TDD는 소프트웨어 엔지니어 누구라도 따를 수 있는 기술로, 단순한 설계와 확신을 불어넣는 테스트슈트를 만들도록 격려한다. 우리가 천재이거나 멍청이라면 이런 방식이 도움이 되지 않겠지만, 그 사이에 존재하는 대다수의 사람들로 다음과 같은 두가지 단순한 방식을 따름으로 잠재력을 발휘할 수 있을 것이다.
이 TDD 책은 얼마나 이 두가지 방식을 정확히 지킬지, 얼마나 적용시킬지 등을 다루게 된다. 또한 앞서 말했던 워드가 영감을 받은 시기에 창조해낸 객체, 다중통화(Currency) 를 가지고 설명을 시작해보겠다.