-
Spring 기본3 - 객체 지향 원리 적용, OCP,DIP 위반의 문제FrameWork/Spring&Spring-boot 2023. 11. 9. 11:21
객체 지향 원리 적용3
새로운 할인 정책 개발
*새로운 할인 정책을 확장해 보자*
https://agilemanifesto.org/iso/ko/manifesto.html
RateDiscountPolicy추가
새로운 할인 정책 적용과 문제점
*방금 추가한 할인 정책을 적용해 보자
할인 정책을 어플리케이션에 적용해보자
할인 정책을 변경하려면 클라이언트인 OrderServiceImpl 코드를 수정해야 한다.
public class OrderServiceImpl implements OrderService{ // private final MemberRepository memberRepository = new MemoryMemberRepository(); private final DiscountPolicy discountPolicy = new FixDiscountPolicy(); ... }
*문제점 발견*
- 역활과 구현을 충실하게 분리했다 → OK
- 다형성도 활용하고, 인터페이스와 구현 객체를 분리 했다. → OK
- OCP, DIP 같은 객체지향 설계 원칙을 충실히 준수 했다.
- → 그렇게 보이지만 사실은 아니다.
- DIP : 주문서비스 클라이언트 (OrderServiceImpl)는 DiscountPolicy 인터페이스에 의준하면서 DIP를 지킨거 같아 보인다 과연 그럴까?
- DiscountPolicy discountPolicy = new FixDiscountPolicy(); 와 같은 인스턴스 생성을 보면 추상(인터페이스) 뿐만 아니라 구체(구현)클래스에도 의존 하고 있다는것을 확인할 수 있다.
- 추상(인터페이스) 의존 : DiscountPolicy
- 구체(구현)클래스 : FixDiscountPolicy, RateDiscountPolicy
- OCP : 변경하지 않고 확장할 수 있어야 한다.
- → 지금 코드는 기능을 확장해서 변경하면, 클라이언트 코드에 영향을 준다. 따라서 OCP를 위반 한것이다.
왜 클라이언트 코드를 변경해야 할까?
클래스 다이어그램으로 의존관계를 분석해보자
*기대 했던 의존관계*
지금까지 단순히 DiscountPolicy인터페이스만 의존한다고 생각했다.
*실제 의존관계*
//private final DiscountPolicy discountPolicy = new FixDiscountPolicy(); private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
잘보면 클라이언트 OrderServiceImpl이 DiscountPolicy 인터페이스 뿐만 아니라 FixDiscountPolicy인 구체 클래스도 함께 의존하고 있다. 실제 코드를 보면 의존하고 있음을 부인할 수없다.(DIP 위반)
*정책 변경*
중요! : 그래서 FixDiscountPolicy를 RateDiscountPolicy 로 변경하는 순간 OrderServieceImpl의 소스코드도 함께 변경해야 한다. (OCP위반)
어떻게 문제를 해결할 수 있을까?
- 클라이언트 코드인 OrderServiceImpl은 DiscountPolicy의 인터페이스 뿐만 아니라 구체 클래스도 함께 의존한다.
- 그래서 구체 클래스를 변경할 때 클라이언트 코드도 함께 변경한다.
- DIP 위반 → 추상에만 의존하도록 변경(인터페이스에만 의존)
- DIP를 위반하지 않도록 인터페이스에만 의존하도록 의존관계를 변경하면 된다.
*인터페이스에만 의존하도록 설계를 변경하자*
*인터페이스에만 의존하도록 코드 변경*
public class OrderServiceImpl implements OrderService{ private DiscountPolicy discountPolicy; }
- 인터페이스에만 의존하도록 코드를 변경했다.
- 그런데 구현체가 없는데 어떻게 코드를 실행할 수 있을까?
- 실제로 실행을 해보면 NPE(null pointer exeception)가 발생한다.
*해결방안*
- 이 문제를 해결하려면 누군가가 클라이언트인 OrderServiceImpl 에 DiscountPolicy의 구현 객체를 대신 생성하고 주입해야한다.
[출처 - 스프링 핵심 원리 - 기본편]
'FrameWork > Spring&Spring-boot' 카테고리의 다른 글
Spring 기본5 - AppConfig 리팩토링 (0) 2023.11.09 Spring 기본 4 - 관심사의 분리 (1) 2023.11.09 Spring 기본2 - 주문 할인 도메인 설계 (1) 2023.11.07 Spring 기본1 - 회원 도메인 설계, SOLID 원칙 (0) 2023.11.07 @Configuration과 싱글톤 (0) 2022.01.11