gradle 설정 변경하면 코끼리 눌러줘야한다. 아니면 reload 클릭.
비즈니스 요구 사항 설계
회원 도메인 설계
회원 도메인 요구사항
회원을 가입하고 조회할 수 있다.
회원은 일반과 VIP 두 가지 등급이 있다.
회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)
;까지 자동 완성 : ctrl + shift + enter
동작을 하면 클라이언트는 MemberServiceImpl 이라는 회원 서비스를 사용하게되고,
회원 서비스는 메모리 회원 저장소를 참조.
객체 다이어그램은 동적. 클래스 다이어그램은 동적.
psvm 치고 엔터하면
new Member(1L, "memberA", Grade.VIP);
ctrl + alt(option) + V 하면
Member memberA = new Member(1L, "memberA", Grade.VIP);
soutv 치면 자동으로 뜸
System.out.println("findMember = " + findMember);
회원 도메인 테스트
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);
}
}
assertions는 org.assertj.core.api를 사용한다.
회원 도메인 설계의 문제점 이 코드의 설계상 문제점은 무엇일까?
다른 저장소로 변경할 때 OCP 원칙을 잘 준수할까? DIP를 잘 지키고 있을까?
의존관계가 인터페이스 뿐만 아니라 구현까지 모두 의존하는 문제점이 있음
private final MemberRepository memberRepository = new MemoryMemberRepository();
MemberServiceImpl은 MemberRepository와 MemoryMemberRepository 둘 다에 의존한다.
->추상화에도 의존하고 구현체에도 의존하고 있는것 -> DIP 위배
주문과 할인 도메인
주문과 할인 도메인 설계
주문과 할인 정책
회원은 상품을 주문할 수 있다.
회원 등급에 따라 할인 정책을 적용할 수 있다.
할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용해달라. (나중에 변경 될 수 있다.) 할인 정책은 변경 가능성이 높다.
회사의 기본 할인 정책을 아직 정하지 못했고,
오픈 직전까지 고민을 미루고 싶다. 최악의 경우 할인을 적용하지 않을 수 도 있다. (미확정)
클라이언트는 main같은 코드, 스프링 mvc의 경우엔 controller가 된다.
역할과 구현을 분리해서 자유롭게 구현 객체를 조립할 수 있게 설계했다.
덕분에 회원 저장소는 물론이고, 할인 정책도 유연하게 변경할 수 있다.
*인터페이스 구현체가 하나면 Impl이라고 적는다
회원을 메모리에서 조회하고, 정액 할인 정책(고정 금액)을 지원해도 주문 서비스를 변경하지 않아도 된다. 역할들의 협력 관계를 그대로 재사용 할 수 있다
회원을 메모리가 아닌 실제 DB에서 조회하고,
정률 할인 정책(주문 금액에 따라 % 할인)을 지원해도 주문 서비스를 변경하지 않아도 된다.
협력 관계를 그대로 재사용 할 수 있다.
주문과 할인 도메인 개발
단축키 : F2누르면 오류 난데로 이동한다.
@Override
public String toString() {
return "Order{" +
"memberId=" + memberId +
", itemName='" + itemName + '\'' +
", itemPrice=" + itemPrice +
", discountprice=" + discountprice +
'}';
}
Order 객체를 출력할 때 toString()이 호출되는데, 그때 보기 쉽게
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);
}
주문 생성 요청이 오면, 회원 정보를 조회하고, 할인 정책을 적용한 다음 주문 객체를 생성해서 반환한다.
메인 메소드로 주문 할인 도메인 실행
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.calculatorPrice = " + order.calculatorPrice());
}
}
테스트 케이스로 실행
public class OrderServiceTest {
MemberService memberService = new MemberServiceImpl();
OrderService orderService = new OrderServiceImpl();
@Test
void createOrder() {
Long memberId = 1L;
Member member = new Member(memberId, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(memberId, "itemA", 10000);
Assertions.assertThat(order.getDiscountprice()).isEqualTo(1000);
}
}
'스프링 > 스프링 핵심원리' 카테고리의 다른 글
7/6 싱글톤 컨테이너 (0) | 2022.07.06 |
---|---|
7/5 싱글톤 (0) | 2022.07.05 |
7/5 스프링 컨테이너와 스프링 (0) | 2022.07.04 |
7/4 객체 지향 원리 적용 (0) | 2022.07.04 |
7/3 스프링이란 (0) | 2022.07.03 |