본문 바로가기
개인/[java] 스프링 핵심 원리 학습

새로운 할인 정책 추가 (객체 지향 원리 적용, 문제점···)

by hyeley5 2023. 8. 28.

이전에 Fix 로 개발해 놨으니 Rate 정책을 추가하자.

 

 

 

discount 패키지에 RateDiscountPolicy.java 를 추가한다

 

command + shft + T

 

테스트 자동으로 생성!

 

 

성공도 있다면 실패도 만들어야 한다!

 

VIP가 아닌 BASIC으로 적용하면 (할인 안 됨)

기대했던 것은 1000원인데 결과는 0이라고 실패한 것을 볼 수 있다.

 

인텔리제이의 좋은 점! 성공한 테스트와 실패한 테스트가 이런 식으로 표시가 된다!_!

 

 

 

Assertions 에서..

 import로 해주는 것이 더 좋다! 

 

assertThat(discount).isEqualTo(1000);

import static으로 바뀌며 이렇게 사용할 수 있다.

 

 

이렇게 돈 관련된 로직은 실무에선 정말 어렵다.!

설계를 이미 잘 해놨기 때문에 별도로 잘 떼어서 했기 때문에 이렇게 쉽게 테스트를 할 수 있는 것!

 


그리고 나서 

클라이언트인 OrderServiceImpl 에서

기존에 있던  FIx에서 Rate로 변경하면 된다!

 

 

하지만.. 문제점을 발견

    • 우리는 역할과 구현을 충실하게 분리했다. O
    • 다형성도 활용하고, 인터페이스와 구현 객체를 분리했다. O
    • OCP, DIP 같은 객체지향 설계 원칙을 충실히 준수했다 (?)
      • 그렇게 보이지만 사실이 아니였다!
    • 추상(인터페이스) 의존: DiscountPolicy
    • 구체(구현) 클래스: FixDiscountPolicy   ,   RateDiscountPolicy

 

기대했던 의존 관계!

 

하지만

실제 의존 관계는

 

 

잘보면 클라이언트인 OrderServiceImpl DiscountPolicy 인터페이스 뿐만 아니라
FixDiscountPolicy 구체 클래스도 함께 의존하고 있다. 실제 코드를 보면 의존하고 있다!  -->  DIP 위반 

 

 

위에서 Fix 에서 Rate로 변경하기 위해 OrderServiceImpl 소스코드를 변경했다. 하지만 이건 --->  OCP 위반 

  • OCP: 변경하지 않고 확장할 수 있다고 했는데!
    지금 코드는 기능을 확장해서 변경하면, 클라이언트 코드에 영향을 준다! 그래서 위반.

 

 

 

그렇다면 어떻게 해결이 될까?

 

 

클라이언트 코드인 OrderServiceImpl 은  DiscountPolicy 의 인터페이스 뿐만 아니라 구체 클래스도 함께 의존한다.
그래서 구체 클래스를 변경할 때 클라이언트 코드도 함께 변경해야 한다.
하지만 DIP 위반! 추상에만 의존하도록 변경(인터페이스에만 의존) 

DIP 위반하지 않도록 인터페이스에만 의존하도록 의존관계를 변경하도록 한다.

//    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    // 할인 정책 변경
//    private final DiscountPolicy discountPolicy = new RateDiscountPolicy(); DIP 위반

    // 변경
    private DiscountPolicy discountPolicy;

인터페이스에만 의존하도록 변경했다.

 

실행하면?

당연히 NullPointerException 오류가 뜬다

 

 

또 어떻게 해결해야 하는가?

  • 이 문제를 해결하려면 누군가가 클라이언트인 OrderServiceImpl 에 DiscountPolicy의 구현 객체를 대신 생성하고 주입해주어야야 한다.

 

 

DIP는 지켰지만 실행이 되지 않음! 

 

다음 게시글에 이어서 작성한다.

 

댓글