일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- resultMap
- 싱글톤
- 스프링 빈
- 스프링 프레임워크
- 스프링 컨테이너
- DIP
- 스프링부트
- assertThrows
- java
- jdbc
- 생성자 주입
- 스프링 부트
- kafka
- @Configuration
- sqld
- mybatis
- JPA
- SQL
- springboot
- DI
- Effective Java
- 필드 주입
- 스프링 부트 기본
- thymeleaf
- assertThat
- spring
- Javascript
- 스프링
- db
- 스프링 부트 입문
- Today
- Total
선 조치 후 분석
[Spring] Spring Framework - 핵심 원리 (7)- 주문과 할인 도메인 설계 + 역할과 구현 + 테스트 코드 사용 본문
[Spring] Spring Framework - 핵심 원리 (7)- 주문과 할인 도메인 설계 + 역할과 구현 + 테스트 코드 사용
JB1104 2022. 1. 11. 23:35주문과 할인 도메인 설계 + 역할과 구현 + 테스트 코드 사용
주문과 할인 정책
- 회원 은상 품을 주문할 수 있다.
- 회원 등급에 따라 할인 정책을 적용할 수 있다. 할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용해달라.
(나중에 변경될 수 있다.) - 할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루고 싶다.
최악의 경우 할인을 적용하지 않을 수도 있다. (미확정)
- 주문생성: 클라이언트는 주문 서비스에 주문생성을 요청한다.
* 여기서 '클라이언트'는 'Main' or 'Controller'가 될 수 있다. - 회원 조회: 할인을 위해서는 회원 등급이 필요하다. 그래서 주문 서비스는 회원 저장소에서 회원을 조회한다.
- 할인 적용: 주문 서비스는 회원 등급에 따른 할인 여부를 할인 정책에 위임한다.
- 주문 결과 반환: 주문 서비스는 할인 결과를 포함한 주문 결과를 반환한다.
역할과 구현을 분리해서 자유롭게 구현 객체를 조립할 수 있게 설계했다. 덕분에 회원 저장소는 물론이고,
할인 정책도 유연하게 변경할 수 있다.
'MemberRepository', 'DiscountPolicy' 각각의 방법을 생각하면 아래처럼 '객체 다이어그램'이 만들어진다.
그리고 'MemberRepository'와 'DiscountPolicy'가 바뀌어도 '주문 서비스 구현체'는 변경하지 않아도 된다.
즉, 역할들의 협력 관계를 그대로 재사용할 수 있다.
주문과 할인 도메인 개발
1. 'DiscountPolicy - 인터페이스' 및 'FixDiscountPolicy - 구현체' 생성
public interface DiscountPolicy {
/**
* @return 할인 대상 금액
*/
int discount(Member member, int price);
}
public class FixDiscountPolicy implements DiscountPolicy{
private int discountFixAmount = 1000; //1000원 할인
@Override
public int discount(Member member, int price) {
if (member.getGrade() == Grade.VIP) { // 'ENUM'은 '=='을 사용해서 확인한다.
return discountFixAmount;
}else {
return 0;
}
}
}
2. 'Order - 주문서' 및 'OrderService - 인터페이스', 'OrderServiceImpl - 구현체' 생성
'OrderServiceImpl'의 순서는 아래와 같다.
1. 주문 생성 요청이 오면, 회원정보를 먼저 조회한다.
2. 할인 정책에다가 회원을 넘긴다. (grade만 넘길지, Member 자체를 넘길지는 프로젝트 상황에 맞게 정하면 된다.)
public class Order {
private Long memberId;
private String itemName;
private int itemPrice;
private int discountPrice;
public int calculatePrice() { // 계산 기능 추가
return itemPrice - discountPrice;
}
... 생성자 및 Getter & Setter 생략
}
public interface OrderService {
Order createOrder(Long memberId, String itemName, int itemPrice);
}
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
@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); // 최종 생성된 주문 반환
}
}
toString 쓰는 이유 : 보통 System.out.println("order = " + order); 을 호출하게 되면, 객체 그 자체를 호출하게 된다. 하지만 'toString'을 'Overriding'해서 깔끔하고 원하는 정보를 볼 수 있도록 도와준다.
@Override
public String toString() {
return "Order [
memberId=" + memberId + ",
itemName=" + itemName + ",
itemPrice=" + itemPrice + ",
discountPrice=" + discountPrice + "]";
}
주문과 할인 도메인 실행과 테스트 - 순수 Java
1. 주문과 할인 정책 실행
public class OrderApp {
public static void main(String[] args) {
MemberService memberService = new MemberServiceImpl();
OrderService orderService = new OrderServiceImpl();
// 멤버 생성
Long memberId = 1L; // 아이디 지정
Member member = new Member(memberId, "memberA", Grade.VIP);
memberService.join(member);
// 멤버를 저장소에 넣는다.
// 오더 생성
Order order = orderService.createOrder(memberId, "itemA", 10000);
System.out.println("order : " + order);
System.out.println("order.caculatePrice : " + order.calculatePrice());
}
}
주문과 할인 도메인 실행과 테스트 - JUnit
1. 주문과 할인 정책 실행
Long & long 차이 : Long을 쓰면 'null'값이 DB에 들어갈 수 있지만, long을 사용하면 DB 'null'값이 들어갈 수 없게 된다.
이게 무슨 말이냐면, Long의 값이 null일 때, long에 Long값을 대입하면 '형 변환'이 되지 않아 에러가 발생한다.
public class OrderServiceTest {
MemberService memberService = new MemberServiceImpl();
OrderService orderService = new OrderServiceImpl();
@Test
void createOrder() {
// given
Long memberId = 1L;
Member member = new Member(memberId, "memberA", Grade.VIP);
// when
memberService.join(member);
Order order = orderService.createOrder(memberId, "itemA", 10000);
// then
Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
// 할인금액이 의도한대로 나오는지 확인한다.
}
}
테스트를 연습하자!!!