당니의 개발자 스토리

새로운 할인 정책 개발 본문

스프링/스프링 핵심 원리 - 기본편

새로운 할인 정책 개발

clainy 2024. 1. 18. 01:40

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

기존에 작성했던 코드에다가 좋은 객체 지향의 원리들을 적용하는 시간을 가져보겠습니다.

이번 시간은 기획자가 나타나서 새로운 할인 정책을 추가해 달라고 요구를 할 거에요.

그래서 이제 새로운 할인 정책을 추가를 할 건데, 막상 새로운 할인을 적용해보면 문제점이 생겨요. 이전부터 얘기해왔던 DIP, OCP를 못 지키는 문제가 실제 발생을 하게 되구요. 이 문제를 해결하기 위해서 여러 과정을 거치게 돼요.

여기있는 여러 과정들을 거치면서, 자연스럽게 스프링의 핵심 기능인 스프링 컨테이너가 왜 탄생했는지 알게 됩니다.

그리고 제일 마지막에는 실제 여러분이 만든 순수한 Java 코드스프링 컨테이너에서 동작하도록 간단하게 바꿔볼 거에요.


새로운 할인 정책 개발을 해봅시다.

새로운 할인 정책을 확장 해봅시다.

이제 여러분이 열심히 개발을 하고 있는데, 갑자기 요구사항을 자주 변경하는 악덕 기획자가 와서 서비스 오픈 직전에 말하는 겁니다.

"지금처럼 할인 정책을 무조건 VIP는 1,000원 할인 해주는 고정 할인은 좀 별로인 거 같네요. 좀 더 합리적인 주문 금액당 퍼센트로, 그러니까 10% 할인 이렇게 정률 할인으로 해야겠어요." 이러는 겁니다.

하지만 우린 걱정할 필요가 없죠. 왜냐? 우리는 이미 유연한 설계가 가능하도록 객체 지향 설계 원칙을 준수해서 개발했습니다. 분명히 역할과 구현을 나눠서 개발했죠.


참고로 애자일 소프트웨어 선언은 한번 읽어보시면 좋습니다.


자 그래서 이 순진한 개발자가 정말 객체 지향의 원칙을 잘 준수했는지 확인을 해봅시다. 우리가 이전에 짰던 개발 코드가 객체 지향의 원칙을 잘 준수했는지 확인해보는 겁니다.

그래서 이번에는 주문한 금액의 퍼센트를 할인해주는 새로운 정률 할인 정책을 추가해볼게요.

추가하는 건 간단하죠.

DiscountPolicy 라는 인터페이스가 있는데, 전에 FixDiscountPolicy를 만들었으니까, 이번에는 RateDiscountPolicy추가하면 됩니다.

추가하면 이런 그림이 완성될 것입니다.


RateDiscountPolicy추가해봅시다.

클래스를 만들고, implements 합니다.

그 다음에 얘는 discountPercent를 10% 할인 하겠대요.

그리고 이제 discount 를 할 건데, discount 메서드는 할인 금액을 반환하므로, 만약에 회원의 grade가 VIP 이면, 주어진 가격에 0.1만큼 곱한 값을 반환합니다.

이 로직이 과연 맞는가는 꼭 테스트를 해봐야 합니다. 이렇게 완성한 다음에 테스트를 작성하는 거에요.

원래는

이 hello.core 에다가 discount 패키지를 만들어서, 이 안에서 테스트 클래스를 만들어야 되는데, cmd + shift + T 하면,

Create New Test 선택하고,

Ok 하면, 테스트 클래스를 만들어줍니다. discount 패키지도 자동 생성해주는 걸 알 수 있습니다.

이제 뭘 테스트를 할거냐면,

RateDiscountPolicy가 정말로 10% 할인이 되는지를 볼겁니다.

@Test를 적어주고, Junit 5에는 DisplayName 이라고 해서, 한글로 이름을 쓸 수가 있습니다.

이렇게 테스트를 만들 거고요. VIP는 잘 적용되어야 된다는 의미에서 vip_o 메서드를 만들겁니다. 그리고 given, when, then 문법을 적고,

given은 어떠한 데이터를 기반으로 테스트 하는지 이므로, Member를 먼저 만들어줍니다.

그리고 when은 뭘 검증할 건지, 어떤 걸 실행했을 때! 이므로,

discount를 했을 때, 할인 금액은 1000원이 나와야 될 것입니다.

그래서 1000원이 맞게 잘 나왔는지 결과인 then에서 확인을 해줍니다.

assertj의 Assertions를 import 해서,

1000이 나왔는지 확인합니다.

실행을 해보면,

녹색불이 뜨는 걸 확인할 수 있습니다. junit 5부터 지원하는 DisplayName도 잘 뜨는 걸 볼 수 있습니다.


테스트를 할 때는 성공 테스트도 중요하지만, 반드시 실패 테스트도 만들어봐야 합니다.

member가 VIP가 아닌 경우의 테스트도 필요할 겁니다.

그래서 이번엔 vip가 아닌 경우니까, vip_x 메서드를 만들어줍니다.

VIP가 아닌 일반회원은 할인 금액이 0원이죠. 그런데 한번 1000원으로 실행을 해보겠습니다.

이렇게 바꿔보고 돌리면,

에러가 뜨는 걸 볼 수 있습니다. 메시지가 기가 막힙니다.

기대했던 건 1000원인데, 실제 값은 0원임을 알려주고 있습니다. 다시 0으로 고치고 돌리면 녹색불이 뜹니다.

참고로,

Assertionsstatic import 하는게 좋습니다.

option + enter 하고 이걸 누르면,

Assertions 가 사라진 걸 볼 수 있습니다. 훨씬 간결하죠.


자 이렇게 해서 할인 정책을 추가하고 테스트까지 완료했죠.

우리가 개발할 때 이런 로직이 불안한단 말이에요.

특히 이런 돈 관련된 거는 실제 실무에서 테스트를 엄청 많이 만들고 돌려봅니다. 근데 지금 설계가 잘 됐기 때문에 이런 좋은 테스트를 할 수 있는 거예요.

지금 보면, 할인과 관련된 부분은 할인과 관련된 것만 테스트하는 거잖아요.

그러니까 할인과 관련된 부분은 별도로 떼서 잘 만들어놨기 때문에 이렇게 쉽게 테스트를 할 수가 있는 거에요.


다음 시간에는 이 RateDiscountPolicy를 주문 서비스에 실제 적용해보도록 하겠습니다.