반응형
이 글은 엘레강트 오브젝트 새로운 관점에서 바라본 객체지향 도서를 보며 스터디한 글입니다.
책에서 주장하는 내용을 정리하였으며 예제들은 모두 코틀린 코드로 변환하여 작성하였습니다.
목차
- 잘못된 의존성 주입
- 올바른 의존성 주입
- 정리
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. 정리
객체가 필요한 의존성을 직접 생성하는 것이 아니라 생성자를 통해 의존성을 주입해야합니다.
반응형
'Study > object' 카테고리의 다른 글
[엘레강트 오브젝트] 4-1장 절대 NULL을 반환하지 마세요 (0) | 2021.10.05 |
---|---|
[엘레강트 오브젝트] 3-7장 인트로스펙션과 캐스팅을 피하세요 (0) | 2021.09.27 |
[엘레강트 오브젝트] 3-5장 절대 getter와 setter를 사용하지 마세요 (0) | 2021.09.25 |
[엘레강트 오브젝트] 3-4장 충성스러우면서 불변이거나, 아니면 상수이거나 (0) | 2021.09.18 |
[엘레강트 오브젝트] 3-3장 인자의 값으로 NULL을 절대 허용하지 마세요. (0) | 2021.09.17 |