[Book] TDD, 켄트 벡 1부 화폐예제
테스트 주도 개발
테스트 주도 개발의 궁극적인 목표: 작동하는 깔끔한 코드
근거:
- 예측 가능한 개발 방법. 끊임없이 발생할 버그에 대해 걱정하지 않고, 일이 언제 마무리 될지 알 수 있다.
- 코드가 가르쳐주는 모든 교훈을 학습할 기회를 갖게 된다. 처음 생각나는 대로 후딱 완료해 버리면 두 번째 것, 더 나은 것 에 대해 생각할 기회를 읽게 만든다.
- 당신이 만든 소프트웨어는 사용자의 삶을 향상시켜 준다.
- 동료들이 당신을 존경할 수 있게 해주며, 당신 또한 동료들을 존경할 수 있게 된다.
- 작성하는 동안 기분이 좋다.
규칙:
- 오직 자동화된 테스트가 실패할 경우에만 새로운 코드를 작성한다.
- 중복을 제거한다.
책을 읽고나면:
- 단순하게 시작하고
- 자동화된 테스트를 만들고
- 새로운 설계 결정을 한 번에 하나씩 도입하기 위해 리팩토링을 할 준비가 될 것이다.
1부. 화폐 예제
TDD의 리듬
- 재빨리 테스트를 하나 추가한다.
- 모든 테스트를 실행하고 새로 추가한 것이 실패하는지 확인한다.
- 코드를 조금 바꾼다.
- 모든 테스트를 실행하고 전부 성공하는지 확인한다.
- 리팩토링을 통해 중복을 제거한다.
놀랄 포인트
- 각각의 테스트가 기능의 작은 증가분을 어떻게 커버하는지
- 새 테스트를 돌아가게 하기 위해 얼마나 작고 못생긴 변화가 가능한지
- 얼마나 자주 테스트를 실행하는지
- 얼마나 수 없이 작은 단계를 통해 리팩토링이 되어가는지
1장. 다중 통화를 지원하는 Money 객체
Money Class
종목 | 주 | 가격 | 합계 |
---|---|---|---|
IBM | 1000 | 25 | 25000 |
GE | 400 | 100 | 40000 |
합계 | 65000 |
다중 통화를 지원하는 Money Class
종목 | 주 | 가격 | 합계 |
---|---|---|---|
IBM | 1000 | 25USD | 25000USD |
GE | 400 | 150CHF | 60000CHF |
합계 | 65000USD |
환율 Class
기준 | 변환 | 환율 |
---|---|---|
CHF | USD | 1.5 |
필요한 테스트
- 통화가 다른 두 금액을 더해서 주어진 환율에 맞게 변한 금액을 결과로 얻을 수 있어야 한다.
- 어떤 금액(주가)을 어떤 수(주식의 수)에 곱한 금액을 결과로 얻을 수 있어야 한다.
할 일
$5 + 10CHF = $10 (환율이 2:1일 경우)
$5 x 2 = $10
amount를 private으로 만들기
Dollar 부작용?
Money 반올림?
Money Class 와 Test 생성
- Money Class
- MoneyTest
수행한 작업
- 우리가 알고 있는 작업해야 할 테스트 목록을 만들었다.
- 오퍼레이션이 외부에서 어떻게 보이길 원하는지 말해주는 이야기를 코드로 표현했다.
- JUnit에 대한 상세한 사항들을 잠시 무시
- 스텁 구현을 통해 테스트를 컴파일
- 돌아가는 코드에서 상수를 변수로 변경하여 점진적으로 일반화
- 새로운 할일을 처리하지 않고 항 일 목록에 추가하고 넘어갔다.
2장. 타락한 객체
일반적인 TDD 주기
- 테스트 작성. 이야기 만들기. 원하는 인터페이스를 개발. 올바른 답을 얻기 위해 필요한 이야기의 모든 요소를 포함
- 실행 가능하게 만든다. 빨리 초록막대 보기. 깔끔하고 단순한게 명백히 보이면 수행, 아니라면 일단 적어놓고 문제 해결.
- 올바르게 만든다. 죄악들을 수숩. 중복을 제거하고 초록막대로 되돌리기.
작동하고 깔끔한 코드 중 작동부분을 먼저 해결
할 일
$5 + 10CHF = $10 (환율이 2:1일 경우)
~~$5 x 2 = $10~~
amount를 private으로 만들기
Dollar 부작용?
Money 반올림?
- 가짜로 구현하기: 상수를 반환하게 만들고 진짜 코드를 얻을 때까지 단계적으로 상수를 변수로 바꾸어 간다.
- 명백한 구현 사용하기: 실제 구현을 입력한다.
3장. 모두를 위한 평등
할 일
$5 + 10CHF = $10 (환율이 2:1일 경우)
~~$5 x 2 = $10~~
amount를 private으로 만들기
~~Dollar 부작용?~~
Money 반올림?
**equals()**
hashCode()
Equal null
Equal object
초록막대를 보기 위한 전략 세번째:
- 삼각측량: 예제가 두개 이상있을 때, 비교를 통해 구성
4장. 프라이버시
임시 변수인 product를 없애면, 일련의 오퍼레이션이 아니라 참인 명제에 대한 단언들이므로 우리의 의도를 더 명확하게 이야기해준다.
Dollar의 amount 인스턴스 변수를 사용하는 코드는 Dollar 자신밖에 없게 됐다. 따라서 변수를 private으로 변경할 수 있다.
할 일
$5 + 10CHF = $10 (환율이 2:1일 경우)
$5 x 2 = $10
amount를 private으로 만들기
Dollar 부작용?
Money 반올림?
equals()
hashCode()
Equal null
Equal object
5장. Franc-ly Speaking
할 일
$5 + 10CHF = $10 (환율이 2:1일 경우)
$5 x 2 = $10
amount를 private으로 만들기
Dollar 부작용?
Money 반올림?
equals()
hashCode()
Equal null
Equal object
5CHF x 2 = 10CHF
$5 + 10CHF = $10 (환율이 2:1일 경우)에 접근하기 위해서 우선 Franc 클래스를 생성한다. Dollar 클래스를 복사해서 Franc 클래스를 만들면 해결.
6장. 돌아온 '모두를 위한 평등'
공용 equals
Dollar 와 Franc은 공통 기능을 갖는다. equals 기능을 상위클래스를 이용해 refactoring 하자.
- 공통된 코드를 Dollar에서 상위 클래스인 Money로 옮겼다.
- Franc도 Money의 하위클래스로 만들었다.
- 불필요한 구현을 제거하기 전에 두 eqauls()구현을 일치시켰다.
7장. 사과와 오렌지
Franc과 Dollar 비교하기
문제점: assertFalse(new Franc(5).equals(new Dollar(5)));
가 실패한다.
Dollar과 Franc의 차이점을 만들어야 한다.
&& getClass().equals(money.getClass());
equals에 클래스도 비교하는 조건을 추가한다.
- 화폐단위를 추가할 수 있지만, 동기가 모자라므로 아직 설계하지 않는다.
8장. 객체 만들기
Dollar/Franc 중복
두 times() 구현이 똑같다
class Money{
static Dollar dollar(int amount){
return new Dollar(amount);
}
static Franc franc(int amount){
return new Franc(amount);
}
}
- 동일한 times()의 두 변이형 메서드 서명부(Dollar, Franc -> Money)를 통일시켜 중복제거에 가까워짐
- 최소한 메서드 선언부만이라도 공통 상위 클래스로 옮겼다.
9장. 우리가 사는 시간
통화?
테스트 단위가 커서 오류가 생겼을 경우 줄일 수 있어야 한다.
class Money{
static Money dollar(int amount){
return new Dollar(amount, "USD");
}
}
class Dollar{
private String currency;
Dollar(int amount, String currency) {
this.amount = amount;
this.currency = currency;
}
Money times(int multiplier) {
return Money.dollar(amount * multiplier);
}
}
- 큰 설계 아이디어를 다루다가 문제가 생기면 작게 만들어라.
- 다른 부분들을 호출자로 옮김으로써 두 생성자를 일치시킴
- times()가 팩토리 메서드를 사용하도록 만들기 위해 리팩토링 중단
- 동일한 생성자들을 상위클래스로 옮김
10장. 흥미로운 시간
공용 times
Franc 과 Dollar에 구현되어있던 times() 메서드를 상위클래스로 옮기기 위해 생성자를 Money로 변경
eqauls에서 Class를 비교하지 않고 이제 currency를 비교하도록 설정.
11장. 모든 악의 근원
Dollar/Franc 중복
이제 Dollar, Franc 클래스는 생성자만 가지므로 삭제가능하다.
Money 클래스만 남기고 나머지를 삭제한다.
- 하위 클래스의 속을 들어내는 걸 완료, 하위 클래스 삭제
- 새로운 소스 구조에서 필요 없게된 테스트 삭제
12장. 드디어, 더하기
$5+$5 = $10
간단한 덧셈을 먼저 구현하기에 앞서, 계산에 필요한 비유를 신중히 고민.
테스트를 구현하기 위해 클래스를 생성하여 복잡하지만 직관적으로 해결
13장. 진짜로 만들기
$5+$5 = $10
- 모든 중복이 제거되기 전까지는 테스트를 통과한 것으로 치지 않는다
- Sum Class를 생성하기 위한 테스트를 작성하였다.
- 명시적인 클래스 테스트를 제거하기 위해 다형성 사용
14장. 바꾸기
Money에 대한 통화 변환을 수행하는 Reduce
- 코드와 테스트 사이에 있는 데이터 중복을 끄집어냈다.
- 별도의 테스트 없이 private helper class를 만들었다.
15장. 서로 다른 통화 더하기
$5 + 10CHF = $10 (환율이 2:1일 경우)
- 원하는 테스트를 작성하고, 한단계에 달성할 수 있도록 뒤로 물렀다.
- Expression fiveBuck로 변경 후, 그 영향을 받은 다른 부분들을 변경하기 위해 컴파일러의 지시를 따랐다.
16장. 드디어, 추상화
Expression.plus를 마치려면 Sum.plus를 구현해야하고 Expression.times()를 구현하면 완성된다.
17장. Money 회고
프로세스:
- 작은 테스트를 추가한다.
- 모든 테스트를 실행하고, 실패하는 것을 확인한다.
- 코드에 변화를 준다.
- 모든 테스트를 실행하고, 성공하는 것을 확인한다.
- 중복을 제거하기 위해 리팩토링한다.
Author And Source
이 문제에 관하여([Book] TDD, 켄트 벡 1부 화폐예제), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mohai2618/Book-Test-DrivenDevelopmentBy-Example-켄트-벡-1부-화폐예제저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)