스프링 핵심 원리 이해2 - 객체 지향 원리 적용

2023. 1. 28. 01:11·BackEnd/스프링 핵심 원리 - 기본편

새로운 할인 정책 개발

저번 예제에서는 고정 할인을 해주었다. 하지만 기획자가 새로운 할인 정책을 해달라고 했다고 가정해보자.

고정 할인이 아닌 10% 할인이다.

차분하게 생각해보면 구현채만 바꾸면 된다.

 

RateDiscountPolicy 구현

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;
        }
    }
}

간단하게 Test 해보기

public class RateDiscountPolicyTest {

    RateDiscountPolicy discountPolicy = new RateDiscountPolicy();

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

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

둘다 통가된 모습을 볼 수 있다.

 

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

할인 정책을 바꿀려면 어떻게 해야 할까?

저번시간에 구현한 OrderServiceImpl에서 FixDiscountPolicy()를 RadteDiscountPolicy()로 변경하면 된다.

public class OrderServiceImpl implements OrderService {
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    // private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

즉, 할인 정책을 변경하려면 클라이언트인 OrderServiceImpl 코드를 고쳐야 한다.

 

문제점

OCP, DIP 같은 객체지향 설계 원칙을 충실히 준수하지 못했다.

  • DIP 부분은 주문서비스 클라이언트( OrderServiceImpl )는 DiscountPolicy 인터페이스에 의존하면서 DIP를 지킨 것 같아 보인다. 하지만 클래스 의존관계를 분석해보면 답이 나온다. 인터페이스 뿐만 아니라 구현 클레스에도 의존하고 있다. -> FixDiscountPolicy , RateDiscountPolicy
  • OCP는 변경하지 않고 확장할 수 있다고 했다. 하지만 지금 코드는 변경하려면 클라이언트 코드에 영향을 준다.

결국 지금 까지 구현했던 코드들은 위의 그림처럼 구현체에도 의존을 하고 있다. DIP와 OCP를 위반하고 있다.

 

어떻게 문제를 해결할 수 있을까?

간단하게 이렇게 바꾸면 된다. 즉 인터페이스에만 의존하도록 코드를 변경하면 된다.

public class OrderServiceImpl implements OrderService {
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    // private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private DiscountPolicy discountPolicy;
    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

이렇게 바꾸고 코드를 실행하면 당연히 NPE(null pointer exception)이 발생한다. 

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

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

'BackEnd > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글

좋은 객체 지향 설계의 5가지 원칙의 적용  (0) 2023.01.28
관심사의 분리  (1) 2023.01.28
스프링 핵심 원리 이해 1 - 예제 만들  (0) 2023.01.28
좋은 객체 지향 설계의 5가지 원칙(SOLID)  (0) 2023.01.27
좋은 객체 지향 프로그래밍이란?  (0) 2023.01.27
'BackEnd/스프링 핵심 원리 - 기본편' 카테고리의 다른 글
  • 좋은 객체 지향 설계의 5가지 원칙의 적용
  • 관심사의 분리
  • 스프링 핵심 원리 이해 1 - 예제 만들
  • 좋은 객체 지향 설계의 5가지 원칙(SOLID)
인프라 감자
인프라 감자
  • 인프라 감자
    삶은 인프라
    인프라 감자
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 클라우드&인프라 (28)
        • 인프라 공부 (4)
        • AWS 구조와 서비스 (18)
        • 클라우드 공부 (4)
        • Terraform (2)
      • AWS Cloud School (13)
        • project (5)
        • Linux, Network (6)
        • Docker (2)
      • BackEnd (162)
        • JAVA 공부 (15)
        • 알고리즘 공부 (71)
        • MySQL 문제 풀기 (8)
        • 스프링 핵심 원리 - 기본편 (18)
        • 스프링 MVC 1편 (4)
        • 자바 ORM 표준 JPA 프로그래밍 (21)
        • 실전! 스프링 부트와 JPA 활용1 (8)
        • 실전! 스프링 부트와 JPA 활용2 (5)
        • 스프링 데이터 JPA (8)
        • Querydsl (4)
      • 혼자하는 프로젝트 (32)
        • 배달의 민족 클론코딩 (7)
        • 나만의 프로젝트 (10)
        • 스프링 부트로 구현한 웹 (15)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Email
    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    중첩 선언
    유니온 파인드
    이것이 자바다
    자동 배포
    스프링 핵심 원리-기본편
    querydsl
    dp
    자바
    다이나믹 프로그래밍
    VPN
    상속
    linux
    백트래킹
    완전탐색
    정렬
    쿼드 압축
    조합
    프로그래머스
    네트워크 기본 용어
    디팬스 게임
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
인프라 감자
스프링 핵심 원리 이해2 - 객체 지향 원리 적용
상단으로

티스토리툴바