SOLID - OOP design principle[5] - DIP
In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupled software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details.
Dependency inversion principle - Wikipedia
From Wikipedia, the free encyclopedia Software programming object-oriented design methodology In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupled software modules. When following this principle, the c
en.wikipedia.org
위키피디아를 참고하면 위와 같이 설명하고 있다.
설명을 보면 high-level module이 low-level module에 의존성을 가지는 전통적인 의존관계의 방향을 역전시켜라
정도로 설명하고 있다.
예시를 통해서 알아보자.
class Garage {
val carList = mutableListOf<Car>()
val motorcycleList = mutableListOf<Motorcycle>()
}
class Car {
fun park() {
println("자동차를 주차하였습니다.")
}
}
class Motorcycle {
fun park() {
println("오토바이를 주차하였습니다.")
}
}
위에서 차고 클래스는 자동차와 오토바이 클래스에 의존성을 가지고 있다.
위키에서 말하고 있는 low-level module에 high-level module이 의존성을 가지고 있는 모습을
간단한 예시로 만들어 보았다.
위와 같은 예시에서 차고에 헬기의 주차가 필요해진다고 가정하면 다음과 같이 작성해 주어야 할 것이다.
class Garage {
val carList = mutableListOf<Car>()
val motorcycleList = mutableListOf<Motorcycle>()
val helicopterList = mutableListOf<Helicopter>()
}
class Car {
fun park() {
println("자동차를 주차하였습니다.")
}
}
class Motorcycle {
fun park() {
println("오토바이를 주차하였습니다.")
}
}
class Helicopter {
fun park() {
println("헬기를 주차하였습니다.")
}
}
새로운 탈것이 등장할 때마다 위처럼 차고 클래스의 수정 수요가 발생할 것이다.
이를 다음과 같이 작성해 주자.
class Garage {
val vehicleList = mutableListOf<Vehicle>()
}
interface Vehicle {
fun park()
}
class Car: Vehicle {
override fun park() {
println("자동차를 주차하였습니다.")
}
}
class Motorcycle: Vehicle {
override fun park() {
println("오토바이를 주차하였습니다.")
}
}
class Helicopter: Vehicle {
override fun park() {
println("헬기를 주차하였습니다.")
}
}
fun main() {
val garage = Garage()
garage.vehicleList.add(Car())
garage.vehicleList.add(Motorcycle())
garage.vehicleList.add(Helicopter())
}
본래 코드와 수정된 코드의 관계도를 살펴보자.
위처럼 작성해 주면 의존관계가 많고 수정의 여지가 많은 클래스의 경우에 클래스를 직접적으로 수정하지 않고서
기능을 확장해 줄 수 있다는 장점이 있다.
클래스를 직접적으로 수정하지 않고서 기능을 확장한다는 SOLID의 2번째 open-closed principle와
정확히 일치한다.
그래서 OCP와 DIP는 같은 것이냐라고 묻는다면
OCP는 달성하고자 하는 목표를 말하는 것이고 DIP는 달성방법을 말하고 있다라고 할 수 있겠다.
마치 feature와 feature의 interface와의 관계 같다.
이렇게 해서 SOLID를 모두 알아보았다.
SOLID에 위배되지 않게 설계한다는 것은 구현하고자 하는 것에 대한 많은 관찰을 필요로 하는 것 같다.
구현하고자 하는 것을 위해 필요한 기능들을 고려하여 적당한 크기로 나눌 때
어느 정도의 크기로 어떻게 나눌 것인지와 이렇게 구현하였을 때 장점은 무엇이고 단점은 무엇인지
생각해 볼 수 있는 시간이었다.