의존성 역전 원칙에서 말하는 '유연성이 극대화된 시스템'이란 소스 코드 의존성이 추상(abstraction)에 의존하며 구체(concretion)에는 의존하지 않는 시스템이다.
- 자바와 같은 정적 타입 언어에서 이 말은 use, import, include 구문은 오직 인터페이스나 추상 클래스 같은 추상적인 선언만을 참조해야 한다는 뜻이다. 구체적인 대상에는 절대로 의존해서는 안 된다.
- 이 아이디어를 규칙으로 보기는 확실히 비현실적이다. 소프트웨어 시스템이라면 구체적인 많은 장치에 반드시 의존하기 때문이다.
- Java - String은 구체 클래스이며, 추상 클래스로 만드려는 시도는 현실성이 없다.
- 그러나 String 클래스는 매우 안정적이다.
- String 클래스가 변경되는 일은 거의 없으며, 있더라도 엄격하게 통제된다.
- 따라서 DIP를 논할 때 운영체제나 플랫폼 같이 안정성이 보장된 환경에 대해서는 무시하는 편이다.
- 우리가 의존하지 않도록 피하고자 하는 것은 바로 변동성이 큰(volatile) 구체적인 요소다.
- 이 구체적인 요소는 우리가 열심히 개발하는 중이라 자주 변경될 수밖에 없는 모듈들이다.
안정된 추상화
- 안정된 소프트웨어 아키텍처란 변동성이 큰 구현체에 의존하는 일은 지양하고, 안정된 추상 인터페이스를 선호하는 아키텍처이다. DIP 원칙은 아래와 같은 구체적인 코딩 실천법으로 생각할 수 있다.
- 변동성이 큰 구체 클래스를 참조하지 말라 대신 추상 인터페이스를 참조하라.
- 또한 이 규칙은 객체 생성 방식을 강하게 제약하며, 일반적으로 추상 팩토리(Abstract Factory)를 사용하도록 강제한다.
- 변동성이 큰 구체 클래스로부터 파생하지 말라
- 정적 언어 타입에서 상속은 소스 코드에 존재하는 모든 관계 중에서 가장 강력한 동시에 변경하기 어렵다. 따라서 상속은 아주 신중하게 사용해야 한다.
- 구체 함수를 오버라이드 하지 말라
- 대체로 구체 함수는 소스 코드 의존성을 필요로 한다. 따라서 함수를 오버라이드 하면 이러한 의존성을 제거할 수 없게 되며, 실제로는 그 의존성을 상속하게 된다.
- 이러한 의존성을 제거하려면, 차라리 추상 함수로 선언하고 구현체들에서 각자의 용도에 맞게 구현해야 한다.
- 구체적이며 변동성이 크다면 절대로 그 이름을 언급하지 말라
팩토리
- 사실상 모든 언어에서 객체를 생성하려면 해당 객체를 구체적으로 정의한 코드에 대해 소스 코드 의존성이 발생한다.
- 자바 등 대다수의 객체 지향 언어에서는 바람직하지 못한 의존성을 처리할 때 추상 팩토리를 사용한다.
이미지 출처 : https://wedonttalknemore.tistory.com/18?category=967824