2.2 회원 도메인 설계 및 개발
회원 데이터, 할인정책 같은 부분은 변경가능성이 상당히 높다. -> 객체지향 설계 방법을 사용하여, 인터페이스를 만들고 구현체를 언제든지 갈아끼울 수 있도록 설계하자.
프로젝트 환경설정을 위해 스프링 부트를 사용했으나,
지금은 스프링 없이 순수한 JAVA로 프로젝트를 개발중이다.
회원 저장소 라는 역할(인터페이스)과 메모리 회원 저장소 / DB 회원 저장소 / 외부 연동 저장소 라는 구현(구현체) 미 확정 요소에 대하여 개발 이후 갈아끼울 수 있도록 역할과 구현을 분리
기획자들도 볼 수 있는 그림이다.
implements : 구현 이라는 뜻으로, 역할(interface)를 실제로 구현하는 것이다. interface에 대해서 구현체가 단 1개만 존재할 때, 'Impl' 을 붙이는 관행이 있다.
도메인 설계를 구체화 하여, 클래스 다이어그램을 만들어 낸다.
객체 간, 메모리간의 참조들이 어떠한 방식으로 그려지는지.
회원 서비스 : MemberServiceImpl / 메모리 회원 저장소 : MemoryMemberRepository(클래스)구현체
객체 다이어그램은 서버가 올라간 이후 (ex. new 해서 참조하는 것) 동적으로 정해지는 것들에 대한, new로 만들어진 인스턴스끼리의 참조
package hello.core.member;
public class Member {
private Long id;
private String name;
private Grade grade;
//작성 후 위에서 설정한 단축키
}
package hello.core.member;
public class Member {
private Long id;
private String name;
private Grade grade;
//생성자 및 getter/setter 자동 생성
public Member(Long id, String name, Grade grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
...
public void setName(String name) {
this.name = name;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
package hello.core.member;
public class MemberServiceImpl implements MemberService {
// 레파지토리 구현체 생성
private final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
// memberRepository 를 호출 하여도, 다형성에 의해서 MemoryMemberRepository 의 save 호출
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
✳단축키 psvm 후 enter 시 메인 생성 가능
package hello.core;
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
public class MemberApp {
//*단축키 psvm 후 enter 시 메인 생성 가능*
public static void main(String[] args) {
MemberService memberService = new MemberServiceImpl();
Member member = new Member(1L, "memberA", Grade.VIP);
memberService.join(member);
//가입 확인
Member findMember = memberService.findMember(1L);
System.out.println("new member = " + member.getName());
System.out.println("findMember = " + findMember.getName());
}
}
// 출력
new member = memberA
findMember = memberA
(기본 디펜던시에 포함)
package hello.core.member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
public class MemberServiceTest {
MemberService memberService = new MemberServiceImpl();
@Test
void join() {
//give (~한 환경에서)
Member member = new Member(1L, "memberA", Grade.VIP);
//when (~ 했을 때)
memberService.join(member);
Member findMember = memberService.findMember(1L);
//then (~ 결과가 나온다)
Assertions.assertThat(member).isEqualTo(findMember);
}
}
테스트 실행
통과
값 변경시 실패 확인 - memberId : 2L
private final MemberRepository memberRepository = new MemoryMemberRepository();
=> 추상화에도 의존하고 구체화에도 의존하고 있다. => DIP(의존관계역전원칙)를 위반하고 있다.