표현, 응용, 도메인, 인프라스트럭처는 아키텍처를 설계할때 출현하는 전형적인 영역이다.
이런 문제는 DIP 를 적용하여 해결할 수 있다.
DIP(Dependency Inversion Principle) 란?
고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 모두 추상화에 의존해야 한다. 이 원칙은 의존성 주입(Dependency Injection)과 같은 패턴을 통해 고수준 모듈과 저수준 모듈 사이의 결합을 줄이고 유연한 시스템을 구축하는 것을 목표로 한다.
- 고수준 모듈 : 어떤 의미 있는 단일 기능을 제공하는 모듈
(interface, 추상 클래스)- 저수준 모듈 : 고수준 모듈의 기능을 구현하기 위해 필요한 하위 기능의 실제 구현
(메인클래스, 객체)
즉 구현 클래스(구현체)가 아니라 인터페이스(역할)에 의존하라는 이야기이다.
저수준 모듈이 변경되더라도 고수준 모듈 수정없이 저수준 구현 객체 생성 코드만 변경하면된다.
저수준 모듈에 직접 의존했다면 실제 해당 모듈이 만들어지기전까지 테스트를 할 수 없지만 DIP가 지켜질 경우 대역 객체를 사용해 테스트를 할 수 있다.
DIP를 잘못 생각하면 단순히 인터페이스와 구현 클래스를 분리하는 정도로 받아들일 수 있다. DIP의 핵심은 고수준 모듈이 저수준 모듈에 의존하지 않도록 하기 위함인데 DIP를 적용한 결과 구조만 보고 아래 그림과 같이 저수준 모듈에서 인터페이스를 추출하는 경우가 있다.
이 구조는 잘못된 구조다. 이 구조에서 도메인 영역은 구현 기술을 다루는 인프라스트럭처 영역에 의존하고 있다. 즉, 여전히 고수준 모듈이 저수준 모듈에 의존하고 있는 것이다. DIP를 적용할 때 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출한다. 즉, '할인 금액 계산'을 추상화한 인터페이스는 저수준 모듈이 아닌 고수준 모듈에 위치한다.
인프라 스트럭처 계층이 가장 하단에 위치하는 계층형 구조와 달리 아키텍처에
DIP 를 적용하면 인프라스트럭처 영역이 응용 영역과 도메인 영역에 의존(상속)하는 구조가 된다.
그러므로 도메인과 응용 영역에 대한 영향을 최소화하여 구현 기술(인프라스트럭처)을 변경하는 것이 가능하다
DIP 를 항상 적용할 필요는 없다.
구현 기술에 따라 의존적인 코드를 도메인에 일부 포함하는것이 효과적일때도 있다.
무조건 DIP 를 적용하려 시도하지 말고 DIP 의 이점을 얻는 수준에서 적용 범위를 검토해보자.