DIP

log.yunsik·2023년 1월 4일
0

네 개의 영역

표현, 응용, 도메인, 인프라스트럭처 네 가지 영역이다.
네 영역을 구성할 때 많이 사용하는 아키텍처가 아래와 같은 계층 구조이다.

계층 구조 특성상 상위 계층에서 하위 계층으로의 의존만 존재하고 하위 계층은 상위 계층에 의존하지 않는다.
계층 구조를 엄격하게 적용한다면 상위 계층은 바로 아래의 계층에만 의존을 가져야 하지만 구현의 편리함을 위해 유연하게 적용하기도 한다.

ex)

도메인과 응용 계층은 룰 엔진과 DB 연동을 위해 그림과 같이 인프라 스트럭처 모듈에 의존하게 된다.

상위 계층이 하위 계층에 의존하게 된다면 표현, 응용, 도메인 계층이 상세한 구현 기술을 다루는 인프라스트럭처 계층에 종속된다는 점이다.

문제점

  • 상위 계층만을 테스트 하기 어렵다. 상위 계층을 테스트하기 위해서는 하위 계층의 구현이 완벽하게 동작해야 한다.
  • 구현 방식을 변경하기 어렵다.

DIP

DIP는 이 문제를 해결하기 위해 추상화한 인터페이스로 저수준 모듈이 고수준 모듈에 의존하도록 바꾼다.

고수준 모듈이 저수준 모듈을 사용하려면 고수준 모듈이 저수준 모듈에 의존해야 하는데 반대로 저수준 모듈이 고수준 모듈에 의존한다고 해서 이를 DIP 의존 역전 원칙이라 부른다.

DIP를 적용하면 고수준이 저수준에 의존할 때 발생했던 구현 교체가 어렵다, 테스트가 어려운 문제를 해소할 수 있다.

구현 교체 문제 해결

고수준 모듈은 더 이상 저수준 모듈에 의존하지 않고 구현을 추상화한 인터페이스에 의존한다.
실제 사용할 저수준 구현 객체는 의존 주입을 이용해서 전달받을 수 있다.
구현 기술을 변경하더라도 수정할 필요가 없다.

// 사용할 저수준 객체 생성
RuleDiscounter ruleDiscounter = new DroolsRuleDiscounter();

// 생성자 방식으로 주입
CalculateDiscountService disService = new CalculateDiscountService(ruleDiscounter);

// 사용할 저수준 구현 객체 변경
RuleDiscounter ruleDiscounter = new SimpleRuleDiscounter();

// 저수준 모듈을 변경해도 고수준 모듈을 수정할 필요가 없다.
CalculateDiscountService disService = new CalculateDiscountService(ruleDiscounter);

테스트 문제 해결

고수준 모듈이 저수준 모듈에 직접 의존했다면 저수준 모듈이 만들어지기 전까지 테스트를 할 수 없었겠지만 인터페이스이므로 대역 객체를 사용해서 테스트를 진행할 수 있다.
실제 구현 없이 테스트 할 수 있는 이유는 DIP를 적용해서 고수준 모듈이 저수준 모듈에 의존하지 않도록 했기 때문이다.
구현 클래스가 없어도 테스트 대역을 이용해 거의 모든 기능을 테스트할 수 있다.

DIP 주의사항

DIP 핵심은 고수준이 저수준에 의존하지 않도록 하기 위함이다.

위 그림은 잘못된 구조이다. RuleEngine이라는 인터페이스는 고수준 모듈인 도메인 관점이 아니라 룰 엔진이라는 저수준 모듈 관점에서 도출한 것이다.
DIP를 적용할 때 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출한다.
추상화한 인터페이스는 저수준 모듈이 아닌 고수준 모듈에 위치한다.


위 그림과 같은 구조로 설계가 이루어져야 한다.

0개의 댓글