Study/object

[엘레강트 오브젝트] 1-1장 -er로 끝나는 이름을 사용하지 마세요.

에디개발자 2021. 8. 10. 07:00
반응형

나를 닮았다고 한다...

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

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

 

토론하기

클래스

먼저 클래스에 대해서 간략하게 알아봅니다.

  • 일반적으로 클래스가 객체를 인스턴스화합니다.
  • 클래스를 객체의 템플릿으로 설명하지만 잘못된 설명입니다. 클래스는 객체의 팩토리이다. 클래스는 객체를 꺼내거나 반환할 수 있는 위치이기 떄문에 클래스를 저장소 또는 웨어하우스라고 불러야 합니다.
  • 객체가 살아있는 생명체라면 클래스는 객체의 어머니

 

본론

클래스 명 짓기에 대해 살펴보겠습니다.

class CashFormatter(
    val dollars: Int
) {
    fun format(): String {
        return String.format("$.d", this.dollars)
    }
}

클래스의 객체에서는 포멧팅을 하는 일을 합니다. 그래서 포멧터로 클래스명을 정하면 잘못한 것입니다. 클래스의 이름은 객체 기준으로 작성하면 안됩니다. 클래스는 무엇을 하는지가 아니라 무엇인지에 기반해야합니다. 클래스명을 변경해보겠습니다.

 

class Cash(
    val dollars: Int
) {
    fun usd(): String {
        return String.format("$.d", this.dollars)
    }
}

 

객체는 그의 역량으로 지어져야합니다. 어떤 사람인지는 키, 몸무게, 피부색과 같은 속성이 아니라, 할 수 있는 일로 설명해야합니다. 즉 가장 많이 실수하는 것이 클래스명에 -er, -or를 붙히는 것입니다. 마치 클래스가 무엇인가를 하는 인격화를 시키기 때문입니다. 

 

객체는 객체의 외부 세계와 내부 세계를 이어주는 연결장치가 아닙니다. 객체는 내부에 캡슐화된 데이터를 다루기 위해 요청할 수 있는 절차의 집합이 아닙니다. 객체는 캡슐화된 데이터의 대표자입니다. 

연결장치 정보를 수정하거나 스스로 어떤 일을 수행할 만큼 똑똑하지 못하기 때문에 단순히 정보를 전달하는 용도
대표자 스스로 결정을 내리고 행동할 수 있는 자립적인 엔티티

클래스의 이름이 '-er', '-or'로 끝난다면, 이 클래스의 인스턴스는 실제로는 객체가 아니라 어떤 데이터를 다루는 절차들의 집합일 뿐이다. 

 

예시

하나의 예시로 들어보겠습니다. 임의의 숫자 리스트가 존재하고 이 리스트의 요소 중에서 짝수를 찾는 알고리즘을 만드는 클래스가 있다고 가정합니다.

잘못된 예 - 무엇을 하는지 관점

**
 * 소수 숫자 조회
 * @param origin IntArray
 * @param primes IntArray
 * @param size Int
 */
fun findPrimeNumbers(origin: IntArray, primes: IntArray, size: Int) {
    var i = 0
    while (i < size) {
        primes[0] = isPrime(origin[i])
            i++
    }
}

/**
 * 소수 체크 여부
 * @param x Int
 * @return Int
 */
fun isPrime(x: Int): Int {
    return 0
}

findPrimeNumbers는 두 개의 정수 배열을 인자로 취하는 프로시저일 뿐 입니다. 이 메서드에는 어떤 객체도 관여하고 있지 않습니다. 이것은 순수하게 절차적인 방식이며 올바르지 못한 방법입니다.  

 

올바른 예 - 무엇인지 관점

/**
 * 소수 값만 리턴하는 클래스
 * @property origin IntArray
 * @constructor
 */
class PrimeNumbers(val origin: IntArray) {
    /**
     * 소수 값 filter
     */
    fun filterPrime() {
        origin.filter { isPrime(it) }
    }

    /**
     * 소수 체크 여부
     * @param x Int
     * @return Boolean
     */
    private fun isPrime(x: Int): Boolean {
        // 소수 체크
        return true
    }
}

클래스 PrimeNumbers는 숫자들의 리스트처럼 행동하지만 오직 소수만 반환합니다. 

 

요약

 

 

이 책의 내용이나 제 생각과 다른 의견이 있으시면 댓글을 달아주세요. :)
반응형