Study/object
[엘레강트 오브젝트] 3-6장 부 ctor 밖에서는 new를 사용하지 마세요
에디개발자
2021. 9. 26. 07:00
반응형
이 글은 엘레강트 오브젝트 새로운 관점에서 바라본 객체지향 도서를 보며 스터디한 글입니다.
책에서 주장하는 내용을 정리하였으며 예제들은 모두 코틀린 코드로 변환하여 작성하였습니다.
목차
- 잘못된 의존성 주입
- 올바른 의존성 주입
- 정리
1. 잘못된 의존성 주입
잘못된 의존성 주입은 종종 치명적인 결과를 초래합니다. 코드로 살펴보겠습니다.
class Cash(
private val dollars: Int
) {
fun euro() =
Exchange().rate("USD", "EUR") * this.dollars
}
euro() 메서드 안에서 Excahnge 인스턴스를 생성하고 있습니다. 이 코드의 문제는 '하드코딩된 의존성'입니다. Cash 클래스는 Exchange 클래스에 직업 연결되어 있기 때문에, 의존성을 끊기 위해서는 Cash 클래스의 내부 코드를 변경해야만 합니다.
fun test() {
val five = Cash(5)
println("$5 equals to ${five.euro()}")
}
이 코드는 의존성 문제가 되는 클래스를 사용하여 테스트 코드를 작성한 것입니다. 만약에 Exchange 객체의 rate() 메서드에서 외부 연동을 진행한다고 하면 테스트 코드를 실행할 때마다 외부와 연동을 진행해야 합니다. 이 경우 외부 연동을 반드시 진행할 수 밖에 없습니다.
2. 올바른 의존성 주입
객체 생성자의 인자로 Exchange를 전달 받아 private 프로퍼티 안에 캡슐화하여 작성해보겠습니다.
class Cash(
private val dollars: Int,
private val exchange: Exchange
) {
fun euro() =
this.exchange.rate("USD", "EUR") * this.dollars
}
위 코드를 테스트하는 올바른 코드도 작성해보겠습니다.
fun test() {
val five = Cash(5, FakeExchange())
println("$5 equals to ${five.euro()}")
}
이처럼 작성한다면 외부통신을 진행하지 않고도 테스트를 진행할 수 있습니다.
편의를 위해 부 생성자를 여러개 추가할 수 있습니다.
class Cash(
private val dollars: Int,
private val exchange: Exchange
) {
// 부 생성자
constructor(): this(0)
// 부 생성자
constructor(dollars: Int): this(dollars, Exchange())
fun euro() =
this.exchange.rate("USD", "EUR") * this.dollars
}
이와 같이 작성한다면 주 생성자에서는 Exchange의 의존성을 주입할 수 있고, 부 생성자에서는 new 생성자를 통해 Exchange 의존성을 주입할 수 있습니다. 즉, 우리 스스로가 의존성 주입을 완전히 제어가 가능합니다.
3. 정리
객체가 필요한 의존성을 직접 생성하는 것이 아니라 생성자를 통해 의존성을 주입해야합니다.
반응형