Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

회원 도메인 개발 및 테스트 본문

인프런/[인프런] Spring 핵심원리 이해

회원 도메인 개발 및 테스트

Seung__ 2021. 7. 24. 22:08

요구사항 및 클래스 다이어 그램은 이전 글 참고

 

비즈니스 요구사항 & 설계

스프링 부트는 환경설정을 위해서만 사용. 스프링 없이 순수 자바로만 진행! 회원 회원을 가입하고 조회할 수 있다. 회원은 일반과 VIP 두 가지 등급이 있다. 회원 데이터는 자체 DB를 구축할 수

bsh-developer.tistory.com

 

1. Member class


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;
    }


}

 

2. Grade enum


  • enum은 일종의 상수
public enum Grade {

    BASIC,
    VIP
}

 

3. MemberRepository Interface


  • 다형성을 활용하기 위해 Repository를 Interface 생성
public interface MemberRepository {

    void save(Member member);

    Member findById(Long memberId);

}

 

4. MemoryMemberRepository class


  • MemberRepository의 구현체
  • interface에서 선언한 method를 override하여 구현.
public class MemoryMemberRepository implements  MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();
    //실무에서는 동시성 문제로 concurrentHashMap사용

    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}

 

5. MemberService Interface


  • 추후에 service가 변경될 수 있기 때문에 다형성을 활용하기 위해 interface로 생성.
public interface MemberService {

    void join(Member member);

    Member findMember(Long memberId);

}

 

 

6. MemberServiceImpl class


  • MemberService interface에 대한 구현체
  • 선언된 method를 override하여 구현.
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);
    }
}

 

7. Test


1) MemberApp class

  • 작성한 코드가 실제로 잘 동작하는지 test를 해보자
  • test를 위해 MemberApp class를 만들었다.
  • 신규 회원을 생성하고 메모리에 저장한다
  • findMember로 다시 검색한 결과와 생성한 회원의 이름이 일치하는지 확인하자.
public class MemberApp {

    public static void main(String[] args) {
        MemberService memberService = new MemberServiceImpl();

        Member member = new Member(1L, "A", Grade.VIP);
        memberService.join(member);

        Member findMember = memberService.findMember(1L);
        System.out.println("new Member = " + member.getName());
        System.out.println("findMember = " + findMember.getName());

    }
}

 

결과가 잘 나오긴 하지만, main 메서드로 매 번 테스트 하는 것은 바람직 하지 않다.

new Member = A
findMember = A

 

 

2) Junit을 활용하여 test 코드 작성

  • test코드를 작성시 given, when, then으로 구분하여 작성하면 
  • 누가봐도 이해하기 쉽고 명확하다.
  • Assertions를 사용하면 일일히 프린트를 찍지 않고 결과를 에상 값과 비교할 수 있다.

 

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);
    }

}

test 통과

  • test가 실패하면 아래와 같이 에러가 발생한다.


8. 현제 도메인 설계의 문제점


  • 저장소를 변경하다고 생각해 보자.

    - 현재 service 구현체에서 MemeryMemberRepository를 의존하고 있다.
    - 따라서 저장소를 변경 할 경우 Service의 코드까지 변경해야 한다. 
    - 즉, 저장소를 변경하면 client에 영향을 미친다. 
  • OCP, DIP를 잘 지키고 있나?
    - DIP : interface에 의존해야 하는데 구현체에 의존하고 있다. 못지치고 있다
    - OCP : 확장하기 위해서는 변경이 필요하다. 못지키고 있다.
  • 문제는 의존관계가 인터페이스 만 아니라 구현까지 모두 의존하고 있는 것이다.

 

 

9. GitHub : 210725, Junit


 

 

GitHub - bsh6463/SpringCoreFunction

Contribute to bsh6463/SpringCoreFunction development by creating an account on GitHub.

github.com

 

Comments