[스프링부트/김영한스프링_기본] 2. 인텔리제이 이용한 예제 코드 작성(회원 코드)

2023. 2. 8. 20:05IT/ServerSide

728x90
반응형

요구사항

 

회원 : 회원 가입/조회, 등급 일반/VIP, 데이터 저장소 미확정(자체 DB/외부 시스템)

할인: 등급에 따라 할인 적용, VIP 1000원 고정 금액 할인, 할인 정책 미확정 (최악의 경우 적용 없음)

주문: 회원 상품 주문, 

 

회원 설계

회원 도메인 협력 관계(기획자) 다이어그램

클라이언트 -> 회원 서비스 (회원가입, 회원조회 등 요구사항 내용) -> 회원 저장소 (객체: 메모리, DB, 외부 시스템 연동)

즉, 요구사항 내용에 대한 다이어그램

 

회원 클래스 다이어그램 (개발자가 구체화), 정적

<interface>MemberService <--MemberServiceImpl -> <interface> MemberRepository <--MemoryMemberRepository/DbMemberRepository/외부저장소

회원 객체 다이어그램 , 동적

클라이언트(인터페이스) -> 회원 서비스(Impl*) -> 메모리 회원 저장소

*인터페이스의 구현체가 하나일 경우 뒤에 Impl을 붙인다.

 

 

-일단 데이터는 메모리 저장소로 진행 (아주 기본적)

 

중요한 것.

역할과 구현이 잘 나누어져야 좋은 설계다.

전체를 Member/Discount/Order로 나누고,

클라이언트(인터페이스)/서비스(구현체)/저장소(인터페이스)-메모리 저장소(구현체)

각각의 역할과 구현을 잘 분할해야 한다.

 

강의에서 전체 요구사항과 설계 및 코드까지 다 짜주기 때문에 나는 매우 재미가 없다.

 

회원 도메인 개발

회원 엔티티 hello.core.member (member package)

  • 회원 등급 enum Grade
BASIC, VIP

*enum이 뭘까..

  • 회원 엔티티 class Member
private id, name, grade
생성자 Member(id, name, grade)
getter/setter

 

  • 회원 저장소 interface MemberRepository
void save(member)
Member findById(memberId)

 

  • 회원 저장소 구현체(메모리) class MemoryMemberRepository implememts MemberRepoository
private static Map<Long, Member> store = new HashMap<>(); *
//Map, HashMap 따로 공부하자..
//override, implements 빨간 줄, 오류 발생 시 : option + enter
@override
save(member) {
	store.put
}
@override
findById(memberId) {
	store.get
}
  • 회원 서비스 interface MemberService
void join(member)
Member findMember(memberId)
  • 회원 서비스 구현체 class MemberServiceImpl
//memberRepository 생성할 때,
MemberRepository memberRepository (인터페이스만 있으면 안된다) = new MemoryMemberRepository()
void join(member) {
	memberRepository.save(member)
}
//구현체가 없으면 nullpointer exception

 

<다형성!>

join이 save를 호출하면 MemoryMemberRepository의 save가 호출되는 것.

 

실행 및 테스트

  • hello.core > MemberApp class
//psvm + enter : public static void main 자동 생성 키맵
MemberService = new MemberServiceImpl
Member member = new Member //멤버 생성, command + option + v : 리팩터링(??)
memberService.join(member) //멤버 저장

Member findMember = memberService.findMember(id)

System.out.println(member.getName()) //생성, 삽입된 멤버
System.out.println(findMember.getName()) //저장된 멤버

 

여기까지는 순수 자바 코드를 눈으로 검증하는 방법이다.

이렇게 애플리케이션 로직(MemberApp)으로 테스트 하는 것은 좋은 방법이 아니다.

따라서 JUnit Test!

 

JUnit Test

  • test > java > hello.core > member package > class MemberServiceTest
MemberService memberService = new MemberServiceImpl();

@Test //import
void join() {
	//given 이런게 주어졌을 때,
    Member member = new Member(아이디, 이름, 등급); //멤버 생성
    
    //when 이렇게 하면
    memberService.join(member); //멤버 추가
    
    Member findMember = memberService.findMember(아이디); //멤버 찾기
    
    //then 이렇게 된다
    Assertions.assertThat(member).isEqualTo(findMember); //생성한 멤버와 찾은 멤버(저장소에서 꺼낸)가 같은지
    
    //Assertions : assertj.core로 선택하기.

오류 내용으로 검증 가능.

Test를 잘 작성하는 게 중요!

 

회원 도메인 설계의 문제점

OCP, DIP 원칙 위반.

의존 관계가 인터페이스 뿐만 아니라 구현까지 모두 의존 *

*예제 전부 작성 후 문제점과 해결 방안 설명

예를 들면,

//MemberServiceImpl에서,

private final MemberRepository memberRepository = new MemoryMemberRepository();

MemberRepository(Interface 의존), MemoryMemberRepository(실제 할당하는 이 부분의 구현체 의존)

즉 , 추상화/구체화 둘 다 의존하여 DIP 위반

728x90
반응형