■ 비즈니스 요구사항과 설계
1) 회원
- 회원을 가입하고 조회할 수 있다.
- 회원의 등급은 일반과 VIP가 존재
- 회원 데이터의 저장소는 아직 확정되지 않음
- 클라이언트, 회원 서비스, 회원 저장소 역할을 하는 인터페이스가 필요
- 회원 서비스에서는 회원 가입과 조회 역할을 한다.
- 회원 저장소는 DB 저장소, 메모리 저장소 등 저장소의 종류에 따라 다양한 구현체를 개발 할 수 있다.
2) 주문과 할인 정책
- 회원은 상품 주문이 가능
- 회원 등급이 따라 할인 정책이 적용
- VIP 등급은 1,000원 할인(고정 할인 정책 적용)
- 할인 정책은 추후 변경될 수도 있다.
인터페이스를 만들고 구현체를 언제든지 갈아끼울 수 있도록 설계하는 것이 중요
■ 회원 도메인 개발(전체 코드가 아닌 중요한 코드만 삽입)
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
public class MemberApp {
public static void main(String[] args) {
MemberService memberService = new MemberServiceImpl();
Member member = new Member(1L, "memberA", Grade.VIP);
memberService.join(member);
Member member1 = memberService.findMember(1L);
System.out.println("new member = " + member.getName());
System.out.println("find member = " + member1.getName());
}
}
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
import java.util.HashMap;
import java.util.Map;
public class MemoryMemberRepository implements MemberRepository {
//동시성 이슈가 발생할 수 있다. 실무에서는 ConcurrentHashMap을 사용
private static Map<Long, Member> store = new HashMap<>();
@Override
public void save(Member member) {
store.put(member.getId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}
■ 회원 가입 테스트
JUnit을 이용해서 테스트
//given
//when
//then
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
public class MemberServiceTest {
MemberService memberService = new MemberServiceImpl();
@Test
void join(){
//given
Member member = new Member(1L, "memberA", Grade.VIP);
//when
memberService.join(member);
Member findMember = memberService.findMember(1L);
//then
Assertions.assertThat(member).isEqualTo(findMember);
}
}
■ 회원 도메인 설계의 문제점
의존관계가 인터페이스 뿐만 아니라 구현체에도 의존하고 있는 문제점이 있음
OCP와 DIP 원칙을 위배
■ 주문과 할인 도메인 개발(전체 코드가 아닌 중요한 코드만 삽입)
import soyeon.study.inflearn.member.Grade;
import soyeon.study.inflearn.member.Member;
import soyeon.study.inflearn.member.MemberService;
import soyeon.study.inflearn.member.MemberServiceImpl;
import soyeon.study.inflearn.order.Order;
import soyeon.study.inflearn.order.OrderService;
import soyeon.study.inflearn.order.OrderServiceImpl;
//주문 서비스 App
public class OrderApp {
public static void main(String[] args) {
MemberService memberService = new MemberServiceImpl();
OrderService orderService = new OrderServiceImpl();
Member member = new Member(1L, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(member.getMemberId(), "itemA", 10000);
System.out.println("할인 가격 = " + order.calculate());
}
}
import soyeon.study.inflearn.member.Member;
import soyeon.study.inflearn.member.MemberRepository;
import soyeon.study.inflearn.member.MemoryMemberRepository;
//OrderService의 구현체
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixedDiscountPolicy();
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member findMember = memberRepository.findByMemberId(memberId); //회원 조회
//조회된 회원 정보를 통해 할인금액 조회
int disCountPrice = discountPolicy.disCount(findMember);
return new Order(memberId, itemName, itemPrice, disCountPrice);
}
}
import soyeon.study.inflearn.member.Grade;
import soyeon.study.inflearn.member.Member;
//할인 정책의 구현체
public class FixedDiscountPolicy implements DiscountPolicy{
@Override
public int disCount(Member member) {
if(member.getGrade() == Grade.VIP){
return 1000;
}else{
return 0;
}
}
}
[출처 : 인프런 스프링 핵심 원리 기본편]
'Spring' 카테고리의 다른 글
[인프런 강의 복습] 스프링 핵심 원리 - 컨포넌트 스캔 (0) | 2022.02.04 |
---|---|
[인프런 강의 복습] 스프링 핵심 원리 - 싱글톤 컨테이너 (0) | 2022.02.03 |
[인프런 강의 복습] 스프링 핵심 원리 - 스프링 컨테이너와 스프링 빈 (0) | 2022.02.02 |
[인프런 강의 복습] 스프링 핵심 원리 - 객체 지향 원리 적용 (0) | 2022.01.27 |
[인프런 강의 복습] 스프링 핵심 원리 - 객체 지향 설계와 스프링 (0) | 2022.01.25 |