본문 바로가기

IT Book Summary/TDD

4-6장

4장. 프라이버시

 

Dollar.times() 연산은

호출을 받은 객체의 값 * 인자로 받은 곱수 

를 갖는 Dollar를 반환해야 함.

 

public void testMultiplication() {
    Dollar five = new Dollar(5);
    Dollar product = five.times(2);
    assertEquals(10, product.amount);
    product = five.times(3);
    assertEquals(15, product.amount);
}

// 첫번째와 두번째 단언 assertion을 Dollar와 Dollar를 비교하는것으로 재작성
public void testMultiplication() {
    Dollar five = new Dollar(5);
    Dollar product = five.times(2);
    assertEquals(new Dollar(10), product.amount);
    product = five.times(3);
    assertEquals(new Dollar(15), product.amount);
}

// 임시변수인 product는 쓸모없으니 인라인시키자.
public void testMultiplication() {
    Dollar five = new Dollar(5);
    assertEquals(new Dollar(10), five.times(2));
    assertEquals(new Dollar(15), five.times(3));
}

 

 

이 테스트는 일련의 오퍼레이션이 아니라 참인 명제에 대한 단언들.

 

이제 Dollar의 amount 인스턴스 변수를 사용하는 코드는 Dollar 자신 밖에 없으므로

변수를 private 으로 변경가능.

 

할일목록 삭제 가능 amount를 private으로 만들자

 

  • 오직 테스트를 향상시키기 위해서만 개발된 기능을 사용
  • 두 테스트가 동시에 실패하면 망한다는 것을 인식
  • 위험요소가 있음에도 계속 진행
  • 테스트와 코드 사이의 결합도를 낮추기 위해, 테스트하는 객체의 새 기능을 사용.

 


5장. 솔직히 말하자면 Franc-ly Speaking

 

달러 대신 Franc을 표현할 수 있는 객체가 필요하다.

 

Dollar테스트를 복사한 후 수정해보자

 

public void testFrancMultiplication() {
    Franc five = new Franc(5);
    assertEquals(new Franc(10), five.times(2));
    assertEquals(new Franc(15), five.times(3));
}

 

1. 테스트 작성.

2. 컴파일되게 하기.

3. 실패하는지 확인하기 위해 실행

4. 실행하게 만듦.

5. 중복 제거.

 

새 기능이 포함되면 속도를 위해

처음의 네 단계를 쉽게 뛰어넘도록 이미 진행된 것의 복붙을 용인할 것이다.

 

class Franc {
    private int amount;
    
    Franc(int amount) {
        this.amount = amount;
    }
    
    Franc times(int multiplier) {
        return new Franc(amount*multiplier);
    }
    
    public boolean equals(Object object) {
        Franc franc = (Franc) object;
        return amount == franc.amount;
    }
}

 

중복이 많으므로 다음테스트 전에 이것을 제거해야한다.

할일 목록에 적어두자.

 

$5 + 10CHF = $10(환율이 2:1일 경우)

$5 x 2 = $10

amount를 private으로 만들기

Dollar 부작용(side effect)?

Money 반올림?

equals()

hashCode()

Equal null

Equal object

5CHF x 2 = 10CHF

Dollar/Franc 중복

공용 equals

공용 times

 

  • 큰 테스트보다 진전을 나타내는 작은 테스트를 했다.
  • 중복을 만들고 조금 고쳐 테스트를 작성함
  • 일단 모델코드까지 복사 수정하여 테스트를 통과하게 했다.
  • 이제 중복을 모두 고쳐야한다.

 


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

 

공동의 상위 클래스를 찾아내자

 

Dollar 와 Franc 상위로 Money 클래스를 만들고 공통의 equals 코드를 가지게 하자.

 

class Money{
    protected int amount;
    public boolean equals(Object object) {
        Money money = (Money) object; // 변경
        return amount == money.amount;
    }
}

class Dollar extends Money{
    
}

 

적절한 테스트를 갖지 못한 코드에서 TDD를 해야 하는 경우가 종종 있을 것이다.(적어도 향후 십년정도는)

-> 이 부분에서 작가는 단순 테스트와 TDD하는것은 다르게 생각한다고 느꼈다.

 

public void testEquality() {
    assertTrue(new Dollar(5).equals(new Dollar(5)));
    assertFalse(new Dollar(5).equals(new Dollar(6)));
    assertTrue(new Franc(5).equals(new Franc(5)));
    assertFalse(new Franc(5).equals(new Franc(6)));
}

 

실제 통과할 테스트 부분을 위해 코드 리펙토링이 이루어지게 되는데

적절한 테스트가 아니면 테스트가 통과하더라도 리펙토링이 덜 이루어지게 되는것이다.

적절한 테스트를 잘 골라 작성하는것이 좋은 리펙토링 결과를 얻게 된다.

어떻게 하면 적절한 테스트를 잘 작성할 수 있을까?

 

Franc도 Dollar와 같이 고칠 수 있다.

 

$5 + 10CHF = $10(환율이 2:1일 경우)

$5 x 2 = $10

amount를 private으로 만들기

Dollar 부작용(side effect)?

Money 반올림?

equals()

hashCode()

Equal null

Equal object

5CHF x 2 = 10CHF

Dollar/Franc 중복

공용 equals

공용 times

Franc 과 Dollar 비교하기

 

  • 공통된 코드를 첫 번째 클래스(Dollar)에서 상위 클래스(Money)로 단게적으로 옮김
  • 두번째 클래스(Franc)도 Money 의 하위 클래스로 만듬.
  • 불필요한 구현을 제거하기전에 두 equals() 구현을 일치시킴

'IT Book Summary > TDD' 카테고리의 다른 글

18장-20장 xUnit  (0) 2020.03.24
13-17장  (0) 2020.03.18
10-12장  (0) 2020.03.10
7-10장  (0) 2020.03.09
1-3장  (0) 2020.02.25