일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- nestjs typeorm
- TypeORM
- @Autowired
- 컴포넌트스캔
- @Component
- AWS
- 프로그래머스
- 해시
- 알고리즘
- 코테
- 시스템호출
- C언어
- python
- 스프링
- Nodejs
- 카카오 코테
- spring boot
- 카카오 알고리즘
- nestjs auth
- 가상면접사례로배우는대규모시스템설계기초
- 코딩테스트
- 카카오
- git
- 파이썬
- Spring
- nestJS
- 구조체배열
- C++
- OpenCV
- thymeleaf
- Today
- Total
공부 기록장 💻
[Spring] 회원 주문 서비스 예제 - 주문과 할인 도메인 설계 및 구현, 테스트 본문
[Spring] 회원 주문 서비스 예제 - 주문과 할인 도메인 설계 및 구현, 테스트
dream_for 2023. 1. 20. 13:43
회원 주문 서비스 예제의 회원 도메인을 설계하고 간단한 구현, 테스트를 해본 것에 이어
주문과 할인 도메인을 설계하여 구현해보자.
주문, 할인 도메인의 비즈니스 요구사항
회원
- 회원을 가입하고 조회할 수 있다.
- 회원에는 일반, VIP 두 등급이 있다.
- 회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)
주문과 할인 정책
- 회원은 상품을 주문할 수 있다.
- 회원 등급에 따라 할인 정책을 적용할 수 있다.
- 할인 정책은 모든 VIP에게는 1,000원을 할인해주는 고정 금액 할인을 적용한다. (나중에 변경 가능성 O)
- 할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루는 상황이다. 최악의 경우 할인을 적용하지 않을 수도 있다.
주문 도메인의 협력, 역할, 책임
1. 주문 생성: 클라이언트(Controller)는 주문 서비스에 주문 생성을 요청한다.
2. 회원 조회: 할인을 위해서는 회원 등급이 필요하다. 따라서 주문 서비스는 회원 저장소에서 회원을 조회한다.
3. 할인 적용: 주문 서비스는 조회한 회원 등급에 따른 할인 여부를 할인 정책에 위임한다.
4. 주문 결과 반환: 주문 서비스는 할인 결과를 포함한 주문 결과를 반환한다.
(예제를 단순화하기 위해, 상품 도메인, 객체를 따로 만들지 않고, 상품명과 상품 가격을 파라미터 방식으로 넘기도록 하자. 그리고 주문 데이터를 DB에 저장하는 과정은 생략하고, 주문 결과를 리턴하도록 설계하자.)
주문 도메인 전체
주문 도메인의 역할과 구현까지 포함한 바 전체를 표현하면 다음과 같다.
주문 서비스의 역할, 회원 저장소의 역할, 할인 정책의 역할에 대한 구현체가 추가되었다. 역할과 책임을 분리하였기 때문에, 상황에 따라 구현체를 달리 하여 적용할 수 있다.
할인 정책 역할의 구현체로는 고정 금액으로 할인을 책정하는 정액할인 정책 구현체와 비율로 할인을 책정하는 정률할인 정책 구현체가 있다.
주문 도메인 클래스 다이어그램
이제 주문 도메인을 객체 레벨로 구현하게 될 때의 클래스 다이어그램은 다음과 같다.
주문 서비스인 OrderService 인터페이스에 대한 구현 클래스 OrderServiceImpl와
회원 저장소를 나타내는 MemberRepository 인터페이스와 이에 대한 구현 클래스인 MemoryMemberRepository, DbMemberRepository,
그리고 마지막으로 할인 정책을 나타내는 DiscountPolicy 인터페이스와 이에 대한 고정 금액 정책인 FixDiscountPolicy 구현체, 정률 할인 정책인 RateDiscountPolicy 구현체가 있다.
주문 도메인 객체 다이어그램
실제 애플리케이션에서 동작하는 객체들의 동적인 연관 관계를 나타낸 주문 도메인의 객체 다이어그램은 다음과 같다.
회원 저장소와 할인 정책이 바뀐다 한들, 주문 서비스를 변경하지 않아도 된다.
즉, 역할들의 협력 관계를 그대로 재사용할 수 있음을 적절히 나타낸 다이어그램이라 할 수 있다.
주문, 할인 도메인 구현
이제 주문과 할인 정책의 도메인을 구현해보도록 하자.
hello.core 패키지 내에 discount, order 이름의 패키지를 다음과 같이 만들고, 순서대로 구현해 나가보도록 하자.
DiscountPolicy 인터페이스
우선 할인 정책의 역할을 하는 DiscountPolicy 인터페이스를 다음과 같이 작성하자.
discount() 메서드는 파라미터로 회원 객체와 주문 가격을 전달 받아, 최종 할인되는 금액을 반환하게 된다.
FixedDiscountPolicy 구현 클래스
DiscountPolicy의 구현체인, 고정 할인 정책 클래스인 FixedDiscountPolicy 는 다음과 같다.
우선 고정 금액 1,000원을 할인하는 요구 사항에 따라, discountFixedAmount 변수가 1000의 값을 갖는다.
discount() 구현 메소드는, 회원의 등급이 VIP 인 경우 고정 할인 금액을 반환하고, 아닌 경우는 0을 반환하도록 한다.
Order 클래스
다음으로 주문의 역할을 하는 Order 클래스는 다음과 같다.
간단하게 분석한 요구 사항에 따라, Order은 회원과 회원이 주문한 상품, 그리고 할인 금액의 정보를 반환하는 객체의 역할을 하게 된다.
memberId, itemName, itemPrice, discountPrice 변수를 통해 객체가 생성되며,
toString() 메서드를 통해 주문 결과를 형식에 맞추어 반환하게 된다.
이때, calculatePrice() 메서드를 추가하여 상품의 원가와 할인 정책에 따른 할인가의 차, 즉 실제 주문 금액이 반환되도록 구현하였다.
OrderService 인터페이스
주문 서비스의 역할을 하는 OrderService 인터페이스 내에 주문을 생성하는 createOrder() 메서드의 틀을 다음과 같이 작성하자.
OrderServiceImpl 구현 클래스
OrderService의 구현체 OrderServiceImpl 클래스는 다음과 같다.
현재, 내장 메모리를 사용하는 회원 저장소, 고정 할인 정책을 사용하는 할인 정책 객체를 각각 만들고,
객체를 통해 회원을 조회하고 할인 정책에 따른 할인 가격 정보를 얻어,
최종적으로 주문 정보를 반환하는 서비스를 나타낸 것이다.
주문, 할인 도메인 Test
이제 주문과 할인 도메인의 테스트를 만들어보자.
OrderServiceTest 테스트 클래스 내에 MemberService, OrderService 객체를 만들고,
주문 테스트() 메서드를 만들어보자.
회원 객체를 등록하고, 주문을 생성하여 getDiscountPrice(), calculatePrice() 로 얻은 값이 예상하고 있는 값과 같은지 junit 을 이용하여 테스트를 실행해보자.
테스트가 잘 통과한 것을 확인할 수 있다.