회원 서비스는 회원 리포지토리와 도메인을 활용해서 실제 비즈니스 로직을 작성합니다.
service 패키지를 만들고 MemberService 클래스를 만듭니다.
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import java.util.Optional;
public class MemberService {
//...1
private final MemberRepository memberRepository = new MemoryMemberRepository();
/**
* 회원 가입
*/
public long join(Member member) {
//같은 이름이 있는 중복 회원X
validateDuplicateMember(member); //중복 회원 검증 //...3
//...2
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
}
Member member1 = result.get();
<aside> 🌟 [TIP]
Optional을 쓸 때 팁!
Optional을 바로 반환하는게 별로 좋지 않습니다. 일단 이쁘지 않습니다.
변경 전)
Optional<Member> result = memberRepository.findByName(member.getName());
result.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
그래서 권장하는 방법은 메서드 체이닝을 쓰는 것 입니다.
memberRepository.findByName(member.getName())의 반환 값은 Optional 입니다. 그래서 아래처럼 바꿀 수 있습니다.
변경 후)
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
</aside>
<aside> 🌟 [TIP]
위와 같은 경우에는 메서드로 뽑는게 좋습니다.
Ctrl + T
: 리펙토링과 관련된 여러가지 것들이 나옵니다.
거기서 Extract Method...가 있습니다. 정확한 단축키는 Command + Option + M
굉장히 자주 쓰는 단축키입니다.
원하는 부분을 드래그 해서 사용하면 됩니다.
→ 자세히
변경 전)
/**
* 회원 가입
*/
public long join(Member member) {
//같은 이름이 있는 중복 회원X
memberRepository.findByName(member.getName()) //중복 회원 검증
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
memberRepository.save(member);
return member.getId();
}
변경 후)
/**
* 회원 가입
*/
public long join(Member member) {
//같은 이름이 있는 중복 회원X
validateDuplicateMember(member); //중복 회원 검증
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
</aside>
그래서 여기까지 코드를 작성하니 join을 하면 중복 회원 검증을 하고 통과하면 저장한다고 바로 이해할 수 있습니다.
이제 전체 회원을 조회하는 기능도 만듭니다.
/**
* 전체 회원 조회
*/
public List<Member> findMembers() {
return memberRepository.findAll();
}
리포지토리 클래스인 MemoryMemberRepository의 save, findById, findByName, findAll의 네이밍이 단순히 저장소에 넣었다 빼는 느낌이 있습니다.
하지만 서비스 클래스인 MemberService의 join, findMembers의 네이밍은 좀 더 비즈니스에 가깝습니다.
보통 서비스 클래스는 비즈니스에 가까운 용어를 써야합니다. 개발자나 기획자가 와서 회원가입 로직이 이상하다고 하면 join을 살펴볼 수 있게 매칭이 됩니다.
서비스는 비즈니스에 의존적으로 네이밍을 하고 리포지토리는 단순히 기계적으로 개발스럽게 네이밍을 선택합니다.