[SOLID] DIP : 의존성 역전 원칙

시나브로·2021년 7월 13일
0

SOLID

목록 보기
6/6
post-thumbnail

DIP : 의존성 역전 원칙


DIP에 대한 개념은 다음과 같다.

추상화에 의존해야 하며, 구체화에 의존하면 안 된다.

즉, 하위의 모듈이 상위 모듈에 정의한 추상 타입(인터페이스)에 의존해야 한다.

의존성 역전 원칙에서 말하는 "유연성이 극대화된 시스템"은 소스코드의 의존성이 추상(abstraction)에 의존하며 구체(concretion) 에는 의존하지 않는 시스템이다.

인터페이스나 추상 클래스와 같은 추상적인 선언을 참조하고, 구체적인 대상에는 절대로 의존하면 안된다는 이야기이다.

우리가 DIP를 통해 의존하지 않도록 피하고자 하는 것은 자주 변경될 수 밖에 없는 변동성이 큰(volatile) 구체적인 모듈이다.



안정된 추상화


추상 인터페이스에 변경이 생기면, 이를 구체화한 구현체들도 따라서 일괄 수정이 필요하다. 반대로 구체적인 구현체에 변경이 생기더라도 그 구현체가 구현하는 인터페이스는 대다수의 경우 변경될 필요가 없다. 따라서 인터페이스는 구현체보다 변경성이 낮다.

즉, 안정된 소프트웨어 아키텍처란 변동성이 큰 구현체에 의존하는 일은 지양하고, 안정된 추상 인터페이스를 선호하는 아키텍처라는 뜻이다.


DIP는 다음의 매우 구체적인 코딩실천법으로 요약 가능하다.


  • 변동성이 큰 구체 클래스를 참조하지 말라

    • 추상 인터페이스를 참조하라. 이는 또한 객체 생성 방식을 강하게 제약하며, 일반적으로 추상 팩토리를 사용하도록 강제한다.
  • 변동성이 큰 구체 클래스로부터 파생하지 말라

    • 상속은 소스 코드에 존재하는 모든 관계 중에서 가장 강력하고 동시에 뻣뻣해서 변경하기 어렵다. 따라서 신중에 신중을 거듭해야한다.
  • 구체 함수를 오버라이드 하지 말라

    • 대체로 구체 함수는 소스 코드 의존성을 필요로 한다. 따라서 구체 함수를 오버라이드하면 의존성을 제거할 수 없게 되며, 실제로는 그 의존성을 상속하게 된다. 이를 제거하려면 추상 함수로 선언하고 구현체들에서 각자의 용도에 맞게 구현해야한다.
  • 구체적이며 변동성이 크다면 절대로 그 이름을 언급하지 말라



팩토리


자바에서는 의존성을 처리할 때 추상 팩토리를 사용하곤 한다.



Application은 Service 인터페이스를 통해 ConcreateImpl을 사용하지만, 어떤 식으로든 ConcreteImpl 클래스의 인스턴스를 생성해야 한다.

이러한 코드 의존성을 만들지 않기 위해, ServiceFactory 인터페이스를 만들어 makeSvc 메서드를 호출하게 되고, 구체화 클래스인 ServiceFactoryImpl 클래스의 makeSvc를 통해 ConcreteImpl 인스턴스를 생성하여 전달하게 된다.

여기서 곡선은 아키텍처 경계를 뜻한다. 이는 구체적인 것으로부터 추상적인 것들을 분리한다. 소스 코드 의존성은 해당 곡선과 교차할 때 모두 추상적인 쪽으로 향한다.

또한 곡선은 시스템을 추상과 구체 컴포넌트로 분리한다.
추상 컴포넌트는 애플리케이션의 모든 고수준 업무 규칙을 포함하고, 구체 컴포넌트는 업무 규칙을 다루기 위해 필요한 모든 세부사항을 포함한다.

소스 코드 의존성은 제어흐름과는 반대 방향으로 역전된다. 이러한 이유로 이를 의존성 역전이라고 부른다.



결론


DIP 위배를 모두 없앨 수는 없다. 하지만 DIP를 위배하는 클래스들은 적은 수의 구체 컴포넌트 내부로 모을 수 있고, 이를 통해 시스템의 나머지 부분과는 분리할 수 있다.







참조


profile
Be More!

0개의 댓글