카테고리 없음

[Test-Driven Development: By Example] 테스트 주도 개발-Money편_자세히

개래갱깽스타 2021. 5. 31. 12:32

1. 재빨리 테스트를 하나 추가한다.

2. 모든 테스트를 실행하고 새로 추가한 것이 실패하는 지 확인한다.

3. 코드를 조금 바꾼다.

4. 모든 테스트를 실행하고 전부 성공하는 지 확인한다.

5. 리팩토링을 통해 중복을 제거한다.

 

Chapter1. 다중 통화를 지원하는 Money 객체

 

참고) inteliJ unit test 추가하기

https://ildann.tistory.com/5

 

[삼각측량, triangulation]

- 설계상의 결함을 그 결함으로 인해 실패하는 테스트로 변환했다.

- 스텁 구현으로 빠르게 컴파일을 통과하도록 만들었다.

- 올바르다고 생각하는 코드를 입력하여 테스트를 통과했다.

 

Chapter3. 모두를 위한 평등

- 우리의 디자인 패턴(값 객체)이 하나의 또 다른 오퍼레이션을 암시한다는 걸 알아챘다.

- 해당 오퍼레이션을 테스트 했다.

- 해당 오퍼레이션을 간단히 구현했다.

- 곧장 리팩토링하는 대신 테스트를 조금 더 했다.

- 두 경우를 모두 수용할 수 있도록 리팩토링했다.

 

Chapter4. 프라이버시

- 오직 테스트를 향상시키기 위해서만 개발된 기능을 사용했다.

- 두 테스트가 동시에 실패하면 망한다는 점을 인식했따.

- 위험 요소가 있음에도 계속 진행했다.

- 테스트와 코드 사이의 결합도를 낮추기 위해, 테스트하는 개체의 새 기능을 사용했다.

 

Chapter5. 솔직히 말하자면

- 큰 테스트를 공략할 수 없다. 그래서 진전을 나타낼 수 있는 자그마한 테스트를 만들었다.

- 뻔뻔스럽게도 중복을 만들고 조금 고쳐서 테스트를 작성했따.

- 설상가상으로 중복을 만들고 조금 고쳐서 테스트를 작성했다.

- 중복이 사라지기 전에는 집에 가지 않겠다고 약속했다. 

 

Chapter 6. 돌아온 '모두를 위한 평등'

- 공통된 코드를 첫 번째 클래스(Dollar)에서 상위 클래스(Money)로 단계적으로 옮겼다.

- 두 번째 클래스(Franc)도 Money의 하위 클래스로 만들었다.

- 불필요한 구현을 제거하기 전에 두 equals() 구현을 일치시켰다.

 

Chapter7. 사과와 오렌지(You can't compare apples and oranges.)

- 우릴 괴롭히던 결함을 끄집어내어서 테스트에 담아냈다.

- 완벽하진 않지만 그럭저럭 봐줄 만한 방법(getClass())으로 테스트를 통과하게 만들었다.

- 더 많은 동기가 있기 전에는 더 많은 설계를 도입하지 않기로 했다.

 

Chapter8. 객체 만들기

- 동일한 메서드(times)의 두 변이형 메서드 서명부를 통일시킴으로써 중복 제거를 향해 한 단계 더 전진했다.

- 최소한 메서드 선언부만이라도 공통 상위 클래스(superclass)로 옮겼다.

- 팩토리 메서드를 도입하여 테스트 코드에서 콘크리트 하위 클래스의 존재 사실을 분리해냈다.

- 하위 클래스가 사라지면 몇몇 테스트는 불필요한 여분의 것이 된다는 것을 인식했다. 하지만 일단 그냥 뒀다.

 

Chpater 9. 우리가 사는 시간

- 큰 설계 아이디어를 다루다가 조금 곤경에 빠졌다. 그래서 좀 전에 주목했던 더 작은 작업을 수행했다.

- 다른 부분들을 호출자(팩토리 메서드)로 옮김으로써 두 생성자를 일치시켰다.

- times() 가 팩토리 메서드를 사용하도록 만들기 위해 리팩토링을 잠시 중단했다.

- 비슷한 리팩토링(Franc 에 했던 일을 Dollar에도 적용)을 한번의 큰 단계로 처리했다

- 동일한 생성자들을 상위 클래스로 올렸다.

 

Chpater10. 흥미로운 시간

- 두 times() 를 일치시키기 위해 그 메서드들이 호출하는 다른 메서드들을 인라인 시킨 후, 상수를 변수로 바꿔 주었다.

- 단지 디버깅을 위해 테스트 없이 toString() 을 작성했다.

- Franc 대신 Money 를 반환하는 변경을 시도한 뒤 그것이 잘 작동할지를 테스트가 말하도록 했다.

- 실험해본 결 뒤로 물리고 또 다른 테스트를 작성했다. 테스트를 작동했더니 실험도 제대로 작동했다.

 

Chapter11. 모든 악의 근원

- 하위 클래스의 속을 들어내는 걸 완료하고, 하위 클래스를 삭제했다.

- 기존의 소스 구조에서는 필요했지만 새로운 구조에서는 필요 없게 된 테스트를 제거했다.

 

Chapter12. 드디어, 더하기 $5 + 10CHF = $10 (환율이 2:1일 경우)

$5 + $5 = $10 부터

[Expression 생성]

- Expression 은 우리가 하려고 하는 일의 핵심에 해당한다. 나는 핵심이 되는 객체가 다른 부분에 대해서 될 수 있는 한 모르도록 노력한다. 그렇게 하면 핵심 객체가 가능한 오랫 동안 유연할 수 있다.(게다가 테스트하기에 쉬울 뿐 아니라, 재활용하거나 이해하기에 모두 쉬운 상태로 남아있을 수 있다.)

- Expression 과 관련이 있는 오퍼레이션이 많을 거라고 상상할 수 있다. 만약에 모든 오퍼레이션을 Expression 에만 추가한다면 Expression 은 무한히 커질 것이다.

---

- 큰 테스트를 작은 테스트($5 + 10CHF에서 $5 + $5로)로 줄여서 발전을 나타낼 수 있도록 했따.

- 우리에게 필요한 계산(computation)에 대한 가능한 메타포들을 신중히 생각해봤다.

- 새 메타포에 기반하여 기존의 테스트를 재작성했다.

- 테스트를 빠르게 컴파일했다.

- 그리고 테스트를 실행했다.

- 진짜 구현을 만들기 위해  필요한 리팩토링을 약간의 전율과 함께 기대했다.

 

Chapter13. 진짜로 만들기

- 모든 중복이 제거되기 전까지는 테스트를 통과한 것으로 치지 않았다.

- 구현하기 위해 역방향이 아닌 순방향으로 작업했다.

- 앞으로 필요할 것으로 예상되는 객체(Sum)의 생성을 강요하기 위한 테스트를 작성했다.

- 빠른 속도로 구현하기 시작했다.(Sum의 생성자)

- 일단 한 곳에 캐스팅을 이용해서 코드를 구현했다가, 테스트가 돌아가자 그 코드를 적당한 자리로 옮겼다.

- 명시적인 클래스 검사를 제거하기 위해 다형성을 사용했다.

 

Chapter14. 바꾸기

 

 

반응형