Spring 객체지향 원리 적용(1) 새로운 할인 정책 개발

woohee·2024년 3월 30일

Spring 핵심원리

목록 보기
6/12
post-thumbnail

🔖지난에 정액할인정책을 구현하였다. 이번에는 정률할인정책을 구현해보자.


새로운 할인 정책 개발

고정할인금액으로 구현하였으나, 더 효율적으로 정률할인을 추가하고 싶다.
DiscountPolicy 인터페이스를 상속받는 RateDiscountPolicy를 구현해보자.

  • 할인 금액은 기존 금액 *0.1
public class RateDiscountPolicy implements DiscountPolicy {
    private int discountPercent = 10;
    @Override
    public int discount(Member member, int price) {
       if(member.getGrade()== Grade.VIP){
           return price *discountPercent/100;
       }else{
           return 0;
       }
    }
}

테스트 코드 실행

테스트 코드 단축키: ctrl+shift+t

class RateDiscountPolicyTest {
    RateDiscountPolicy discountPolicy = new RateDiscountPolicy();

    @Test
    @DisplayName("VIP는 10% 할인이 적용되어야 한다.")
    void vip_o(){
        //given
        Member member = new Member(1L,"memberVIP", Grade.VIP);
        //when
        int discount = discountPolicy.discount(member,10000);
        //then
        Assertions.assertThat(discount).isEqualTo(1000);
    }

    @Test
    @DisplayName("VIP가 아니면 할인이 적용되지 않아야 한다.")
    void vip_x(){
        //given
        Member member = new Member(1L,"memberBasic", Grade.BASIC);
        //when
        int discount = discountPolicy.discount(member,10000);
        //then
        Assertions.assertThat(discount).isEqualTo(1000);
    }
}

두 번째 테스트에선 X 가 나오고 예측값은 1000인데 실제값은 0이라고 뜬다.
두 번째 테스트를 통과하려면 다음과 같이 수정하면 된다.

  void vip_x(){
        //given
        Member member = new Member(1L,"memberBasic", Grade.BASIC);
        //when
        int discount = discountPolicy.discount(member,10000);
        //then
        Assertions.assertThat(discount).isEqualTo(0);
    }

예측값을 0으로 넣어주면 테스트가 정상적으로 실행된다.

새로운 할인 정책 적용과 문제점

문제점

  • 역할과 구현을 분리하였다.
  • 다형성을 활용하고 인터페이스와 구현 객체를 분리했다.
  • OCP. DIP 같은 객체지향 설계 원칙을 충실히 준수했다.
  • 주문 서비스 클라이언트는 DiscountPolicy 인터페이스에 의존하면서 DIP를 지킨 것 같지만
    추상 인터페이스 뿐만 아니라 구체 클래스에도 의존하고 있다. -> DIP 위반
  • 지금 코드는 기능을 확장해서 변경하면 클라이언트 코드에 영향을 준다 -> OCP 위반

문제 해결

  • 인터페이스에만 의존하도록 설계를 변경하자.
    즉, DiscountPolicy에만 의존하고 구체 클래스인 FixDiscountPolicy, RateDiscountPolicy를 삭제
public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private  DiscountPolicy discountPolicy;
    // private DiscountPolicy discountPolicy = new FixDiscountPolicy();
}
  • 인터페이스에만 의존하도록 변경 완료.
  • 구현체가 없는데 코드를 어떻게 실행할까?
  • 실행하게 되면 Null pointer exception이 발생

해결 방안

  • OrderServiceImpl에 DiscountPolicydml 구현 객체를 대신 생성하고 주입해주면 된다.

📜Summary

  • 잘 만들어진 설계를 순수 자바 코드로 구현해도 SOLID 법칙을 위배한다.
  • SOLID 법칙을 만족하는 구현 방법을 생각해야 한다.

0개의 댓글