오늘은 계산기 만들기 과제를 하다가 과제 요구사항에
의존성 역전 원칙을 지켜 코드를 작성해 보라는 것이 있어서 조금 정리를 해볼까 한다.
의존성 역전 원칙(DIP)이란?
의존성 역전 원칙은 객체 지향 설계의 SOLID 원칙 중 다섯 번째 원칙이다. 객체에서 어떤 Class를 참조해서 사용해야하는 상황이 생긴다면, 그 Class를 직접 참조하는 것이 아니라 그대상의 상위 요소(추상 클래스 or 인터페이스)로 참조하라는 원칙이다.
잘못된 예제부터 봅시다.
class Light {
func turnOn() {
print("Light is on")
}
}
class Switch {
private let light = Light()
func operate() {
light.turnOn()
}
}
Switch 클래스는 Light 클래스에 직접 의존한다. 이는 Light 클래스가 변경되면 Switch 클래스도 영향을 받는 구조다.
다음은 올바른 예제이다.
protocol Switchable {
func turnOn()
}
class Light: Switchable {
func turnOn() {
print("Light is on")
}
}
class Switch {
private let device: Switchable
init(device: Switchable) {
self.device = device
}
func operate() {
device.turnOn()
}
}
// 사용 예시
let light = Light()
let switchControl = Switch(device: light)
switchControl.operate() // "Light is on" 출력
Switch 클래스는 Switchable 프로토콜에 의존하고, Light 클래스는 Switchable 프로토콜을 구현한다.. 이를 통해 Switch 클래스는 Light 클래스의 변경에 영향을 받지 않고, 다양한 Switchable 구현체를 사용할 수 있다.
DIP를 준수함으로써 얻을 수 있는 장점
- 유연성: 고수준 모듈과 저수준 모듈 간의 결합도를 낮춰 변경에 더 유연해집니다.
- 테스트 용이성: 프로토콜을 통해 모의 객체(mock objects)를 사용하여 테스트할 수 있어 테스트가 용이해집니다.
- 유지보수성: 시스템의 한 부분을 변경하더라도 다른 부분에 미치는 영향을 최소화할 수 있어 유지보수가 용이합니다.