더북(TheBook)

이제 목을 사용하지 않고도 프로그램을 테스트할 수 있다. 다음 코드는 buyDonuts 메서드를 테스트한다.

class DonutShopKtTest {
    @Test
    fun testBuyDonuts() {
        val creditCard = CreditCard()
        val purchase = buyDonuts(5, creditCard)
        assertEquals(Donut.price * 5, purchase.payment.amount)
        assertEquals(creditCard, purchase.payment.creditCard)
    }
}

참조 투명성을 사용해 코드를 리팩터링해서 얻을 수 있는 또 다른 이점은 프로그램을 합성하기 더 좋다는 점이다. 도넛 구입 프로그램의 최초 버전으로 누군가 여러 번 도넛을 사면 지급이 일어날 때마다 은행에 연결해야(그리고 그에 따른 수수료를 부담해야) 했다. 하지만 새 버전을 사용하면 구입이 일어난 즉시 청구할지, 같은 카드로 이뤄진 모든 지급을 한꺼번에 묶어 전체 금액을 단 한 번만 청구할지 선택할 수 있다. 여러 지급을 하나로 묶으려면 코틀린 List 클래스가 제공하는 함수가 몇 가지 더 필요하다.4

groupBy(f: (A) -> B): Map<B, List<A>> A 타입의 값을 B 타입의 값으로 반환하는 함수를 인자로 받아 키와 값의 쌍으로 이뤄진 맵을 반환한다. 맵에서 키의 타입은 B이고, 값의 타입은 List<A>다.

values: List<A> Map의 인스턴스 함수로, 맵에 들어 있는 모든 값의 리스트를 반환한다.

map(f: (A) -> B): List<B> List의 인스턴스 함수로, A 타입의 값을 B 타입의 값으로 반환하는 함수를 인자로 받아 A 타입 원소가 들어 있는 리스트의 각 원소에 적용한 결과로 생기는 B 타입 원소로 이뤄진 리스트를 반환한다.

reduce(f: (A, A) -> A): A List의 인스턴스 함수로, 리스트를 축약할 때 사용할 어떤 연산(f: (A, A) -> A라는 함수로 표현됨)을 받아 리스트를 한 값으로 축약한다. 연산이 덧셈인 경우, f(a, b) = a + b와 같은 함수를 뜻할 수 있다.

 

 


4 역주 저자는 각 함수를 설명하면서 타입을 명시했다. 코틀린 코어 라이브러리 등 코틀린으로 작성된 라이브러리의 API 문서를 볼 때는 항상 제일 먼저 메서드나 함수의 반환 타입과 어떤 타입의 함수를 인자로 받는지를 살펴봐야 한다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.