회원 도메인 개발
Last updated
Last updated
public enum Grade {
BASIC,
VIP
}
public class Member {
private Long id;
private String name;
private Grade grade;
public Member(Long id, String name, Grade grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
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);
}
}
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
public class MemberServiceImpl implements MemberService {
// 인터페이스만 가지고 있으면 구현체가 없어서 NPE가 터진다.
// 따라서 구현 객체(MemoryMemberRepository)를 선택해줘야 한다.
private final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
이제 위의 다이어그램처럼 실제 객체를 참조하도록 만들어보자.
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 findMember = memberService.findMember(1L);
System.out.println("new member = " + member.getName());
System.out.println("findMember = " + findMember.getName());
}
}
new member = memberA
findMember = memberA
스프링 없이 순수 자바 코드로 만들었음에도 값이 제대로 나왔다.
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);
}
매번 메인 메서드에서 실행해볼 수 없으므로 테스트 코드를 구현해보자.
만약 다른 repository로 변경할 OCP 원칙을 준수할까?
DIP를 잘 지키고 있을까?
public class MemberServiceImpl implements MemberService {
// 추상화와 구현 모두에 의존하고 있다.
private final MemberRepository memberRepository = new MemoryMemberRepository();
}
의존 관계가 인터페이스 뿐만 아니라 구현까지 모두 의존하는 문제가 있다.