Study/object

[엘레강트 오브젝트] 2-9장 인터페이스를 짧게 유지하고 스마트(smart)를 사용하세요.

에디개발자 2021. 9. 7. 13:59
반응형

나를 닮았다고 한다...

이 글은 엘레강트 오브젝트 새로운 관점에서 바라본 객체지향 도서를 보며 스터디한 글입니다.

책에서 주장하는 내용을 정리하였으며 예제들은 모두 코틀린 코드로 변환하여 작성하였습니다.

 

목차

  1. 인터페이스를 정의하는 방법
  2. 스마트 클래스
  3. 나중에 배울 데코레이터

1. 인터페이스를 정의하는 방법

인터페이스는 구현자에게 너무 많은 것을 요구하면 안됩니다. 

// Bad interface..
interface Exchange {
    fun rate(target: String): Float
    fun rate(source: String, target: String): Float
}

위 코드는 나쁜 설계의 인터페이스입니다. 구현자에게 동일한 기능을 수행하는 rate() 메서드에서 속성값만 다르게 구현하라고 강요하고 있습니다. 이럴 경우 SRP( 단일 책임 원칙 )를 위반하는 클래스를 설계할 가능성을 높입니다. 

 

이 책에서는 위와 같이 설계를 하려면 인터페이스 안에 스마트 클래스를 추가하여 해결 방안을 제시합니다. 

 

2. 스마트 클래스

interface Exchange {
    fun rate(source: String, target: String): Float
    class Smart {  // smart class
        private lateinit var origin: Exchange
        fun toUsd(source: String) =
            this.origin.rate(source, "USD")
    }
}

스마트 클래스는 명확하고 공통적인 작업을 수행하는 많은 메서드를 다룰 수 있습니다. 위 Smart 클래스는 아래와 같이 사용할 수 있습니다. 

val rate = Exchange.Smart().toUsd("EUR")

 

하지만 위와 같은 코드를 사용하는 곳이 점점 많이진다면 "EUR" 코드를 계속 작성해줘야하는 단점이 생깁니다. 이 때 새로운 기능을 추가하려고 할때 Smart 클래스를 이용해서 추가할 수 있습니다. 

interface Exchange {
    fun rate(source: String, target: String): Float
    class Smart {
        private lateinit var origin: Exchange
        fun toUsd(source: String) =
            this.origin.rate(source, "USD")

        fun eurToUsd() = this.toUsd("EUR")  // 추가
    }
}

// use
val rate = Exchange.Smart().eurToUsd()

이처럼 많은 기능을 제공하려면 Smart 클래스의 크기는 점점 커질 것입니다. 하지만 interface는 적은 메서드만을 제공할 수 있습니다. 기본적으로 interface는 짧게 만들고 Smart 클래스를 인터페이스와 함께 배포함으로써 공통 기능을 추출하고 코드 중복을 피할 수 있습니다.

 

3. 나중에 배울 데코레이터

스마트 클래스는 객체에 새로운 메서드를 추가하지만 데코레이터는 이미 존재하는 메서드를 오버라이드하여 유연하게 사용할 수 있습니다.

interface Exchange {
    fun rate(origin: String, target: String): Float
    
    class Fast: Exchange {
        private lateinit var origin: Exchange
        override fun rate(source: String, target: String): Float {
            return if (source == target) 1.0f
            else origin.rate(source, target)
        }

        fun toUsd(source: String) = this.origin.rate(source, "USD")
    }
    
}

Fast 클래스는 데코레이터인 동시에 스마트 클래스입니다. Fast 클래스는 rate() 메서드를 오버라이드하여 유연하게 코드를 작성할 수 있습니다.  

반응형