Study/object

[엘레강트 오브젝트] 1-2장 생성자 하나를 주 생성자로 만드세요.

에디개발자 2021. 8. 11. 06:00
반응형

나를 닮았다고 한다...

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

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

 

토론하기

이 책의 방법론대로 클래스를 작성한다면 메서드 수보다 생성자 수가 많아질 것 입니다. 

Method Count < Construct Count

이 책에서 권장하는 메서드의 수는 2 ~ 3개이고 생성자는 5 ~ 10 개입니다.

 

예시를 통해서 자세히 살펴보겠습니다. 먼저 임의의 Cash 클래스를 생성합니다.

class Cash(
    private var dollars: Int
) {

}

 

생성자가 많아질수록 클래스를 더 유연하게 사용할 수 있습니다. 

Cash(30)
Cash("$29.5")
Cash(29.5f)
Cash(29.5, "USD")

 

메서드가 많아지면 클래스의 초점이 흐려지고 단일 책임 원칙(SRP)을 위반하게 될 것 입니다.

생성자의 주된 작업은 제공된 인자를 사용해서 캡슐화하고 있는 프로퍼티를 초기화하는 일입니다. 이런 초기화를 통해 부(secondary) 생성자가 단 하나의 생성자(Main)를 호출하도록 만듭니다.

class Cash(
    private var dollars: Int
) {
    constructor(dollars: Float): this(dollars.toInt())
    constructor(dollars: String): this(Cash.parse(dollars))
    
    companion object {
        fun parse(dollars: String): Int {
            // String to Int parse 로직 생략..
            return 0
        }
    }
}

  

이처럼 하나의 Main 생성자와 N개의 Secondary 생성자의 원칙의 핵심은 중복 코드를 방지하고 설계를 간결하게 만들기 때문에 유지보수성이 향상된다는 점입니다. 이 원칙을 따르지 않은 코드는 아래와 같습니다.

class CashBad {
    private var dollars: Int = 0
    constructor(dollars: Float) {  // Bad Case
        this.dollars = dollars.toInt()    
    }
    constructor(dollars: String) {  // Bad Case
        this.dollars = CashBad.parse(dollars)
    }

    companion object {
        fun parse(dollars: String): Int {
            return 0
        }
    }
}

 

이와 같이 작성하면 생성자 별로 유효성 검사로직을 일일이 작성해야하는 불편함이 있습니다. 

위 코드는 올바르지 않은 예를 작성하기 위해 억지로 작성한 코드입니다. 
코틀린에서는 클래스의 속성값을 지정하면 다른 생성자에서 this()를 강제로 상속받도록하여 위와 같은 문제는 발생하지 않습니다. 
아래 코드를 참조해주세요.

코틀린에서 클래스 속성값을 설정하면 다른 생성자에서 this를 호출하도록 강제한다.

 

요약

Secondary 생성자 모두 Main 생성자를 호출한다.

 

반응형