[Java] 동작 파라미터화 적용해보기

이동엽·2022년 12월 22일
1

java

목록 보기
13/18

이전 포스팅에서 모던 자바 인 액션 2장(동작 파라미터화 코드 전달하기)을 학습한 내용을 정리하였다.

책에 주어진 예제를 눈으로 읽고, 따라치는 것만으로는 완전히 이해한 것이 아니라는 생각이 들었고,
기존에 만들어봤던 토이프로젝트에 학습한 내용을 적용해보기로 하였다!


💡 기존 구성

  • 회원가입
    • 사용자로부터 회원가입 요청이 컨트롤러에 들어오면, 컨트롤러는 이를 서비스에게 넘긴다.
    • 실질적인 유효성 검사(기존 회원과 id가 중복되는지를 판단) 및 회원가입 로직은 서비스에서 진행된다.
  • 로그인
    • 사용자로부터 로그인 요청이 컨트롤러에 들어오면, 컨트롤러는 이를 서비스에게 넘긴다.
    • 마찬가지로, 서비스에서는 기존 회원 목록들 중 요청과 함께 들어온 데이터와 일치하는 회원이 있는지 찾는다.

  • 위에서 말로 설명한 내용을 코드로 보면 아래와 같다.
    • src/auth/service/AuthService.java

/* 회원가입 로직 */
public void signUp(final SignUpDto signUpDto) throws SameIdException {
	List<UserEntity> userList = userRepository.getUserDB();
    
    if (hasSameIdCheck(signUpDto.getId(), userList) {
    	throw new SameIdException();
    }
    
    userRepository.add(new UserEntity(signUpDto.getId(), signUpDto.getPassword());
}

/* 로그인 로직 */
public boolean signIn(final SignInDto signInDto) {
    Iterator<UserEntity> iterator = userRepository.getUserDB().iterator();

	while(iterator.hasNext()) {
    	UserEntity temp = iterator.next();
        
        if (signInDto.getId().equals(temp.getId()) && signInDto.getPassword().equals(temp.getPassword()) {
        	return true;        
        }
    }
    
    throw new NotFoundException("일치하는 회원을 찾을 수 없습니다.");
}

/* id 중복 체크 로직 */
private boolean hasSameIdCheck(final String id, final List<UserEntity> userList) {
	Iterator<UserEntity> iterator = userList.iterator();
    
    while (iterator.hasNext()) {
    	UserEntity temp = iterator.next();
        
        if (id.equals(temp.getId()) {
        	return true;
        }
    }
    
    return false;
}

💡위 코드의 문제점

  • 회원가입 로직에서는 탐색을 hasSameIdCheck()에게 위임했지만, 로그인 로직에서는 탐색이 포함되어 있다.
    단일 책임 원칙(SRP) 위반!!
  • 회원가입 시 id 중복 체크를 위해 만든 hasSameIdCheck()다형성을 살려서, 로그인 경우에 일치하는 id를 찾는 기능으로 바꿀 수 있지 않을까?
    동작 파라미터화로 고쳐보자

💡 동작 파라미터화 적용하기

  1. 우선 Predicate 함수형 인터페이스를 이용해 탐색 결과를 boolean 으로 반환하려 한다.
public interface AuthPredicate {
    boolean test (String id, UserEntity userEntity);
}

  1. AuthPredicate를 구현하는 하위 Predicate 생성
/* AuthService의 내부 중첩 클래스로 작성 */
static class FilterSameIdPredicate implements AuthPredicate {
	
    @Override
    public boolean test(String id, UserEntity user) {
    	return id.equals(user.getId());
    }
}

static class FilterSamePasswordPredicate implements AuthPredicate {
	
    @Override
    public boolean test(String password, UserEntity user) {
    	return password.equals(user.getPassword());
    }
}

  1. 탐색 과정을 호출하는 filterPredicate() 메소드 정의
private static boolean filterPredicate(
	/* duplicatedData에는 id나 password가 들어올 수 있다.
       회원가입 로직에서는 id를 이용해 중복을 탐색하는 데에 쓰이고,
       로그인 로직에서는 id와 password를 각각 넣어 일치하는 정보가 있는지 탐색하는데 쓰인다. */
	final String duplicatedData, final List<UserEntity> userList, AuthPredicate p
) {
	for (UserEntity user : userList) {
    	if (p.test(duplicatedData, user)) {
        	return true;
        }
    }
    return false;
}

  1. 회원가입과 로그인 로직에서 filterPredicate() 메서드 호출하도록 적용하기
/* 회원가입 로직 */
public void signUp(final AuthDto authDto) throws SameIdException {
	List<UserEntity> userList = userRepository.getUserDB();

    if (filterPredicate(signUpId, userList, new FilterSameIdPredicate())) {
    	throw new SameIdException();
	}
    
    userRepository.add(new UserEntity(signUpId, signUpPassword));   
}

/* 로그인 로직 */
public boolean signIn(final AuthDto authDto) {
	List<UserEntity> userList = userRepository.getUserDB();

    if (filterPredicate(logInId, userList, new FilterSameIdPredicate()) &&
                filterPredicate(logInPassword, userList, new FilterSamePasswordPredicate())) {

         return true;
	}

    return false;
}

💡 마무리

  • 동작 파라미터화를 통해 동작을 전달할 수 있다.
  • 로그인 과정에서 탐색에 대한 책임을 filterPredicate()에게 위임하였다.
    • SRP(단일 책임 원칙)
  • 새로운 조건으로 탐색을 해야할 시 구현 클래스의 test() 메서드만 수정하면 된다.
    • 변화하는 요구사항에 대응할 수 있다!

추가로 개인적인 학습을 통한 정리이므로, 정답 코드가 아님을 전합니다.
아직 변수나 함수 이름을 짓는 데에 어려움이 있어, 피드백을 주시면 수정하겠습니다.

읽어주셔서 감사합니다.


참고 자료

profile
백엔드 개발자로 등 따숩고 배 부르게 되는 그 날까지

1개의 댓글

comment-user-thumbnail
2023년 5월 8일

최악이네요.

답글 달기