클린코드 3장 함수에서 다룬 추상화 수준을 적용해 한 가지 일을 하는 함수로 가꿉니다.
책에서는 한 가지 일을 하는 함수에 대한 기준으로 추상화 수준
을 언급했습니다.
저는 위 이유 중 1번이 특히 공감이 되었습니다. 다음은 회원가입을 구현한 메서드입니다.
public void signup(String uid, String nickname) {
// 이미 존재하는 유저인 경우 예외처리
if (userRepository.existsByUid(uid)) {
throw new CustomException(CommonCode.ALREADY_EXIST_USER);
}
// 이미 존재하는 닉네임인 경우 예외처리
if (userRepository.existsByNickname(nickname)) {
throw new CustomException(CommonCode.ALREADY_EXIST_NICKNAME);
}
User savedUser = userRepository.save(new User(uid, nickname));
authorityRepository.save(new Authority(savedUser, ROLE_USER));
}
public void signup(String uid, String nickname) {
validateUserForSignup(uid, nickname);
User savedUser = userRepository.save(new User(uid, nickname));
authorityRepository.save(new Authority(savedUser, ROLE_USER));
}
private void validateUserForSignup(String uid, String nickname) {
checkAndThrowIfUserAlreadyExists(uid);
checkAndThrowIfNicknameAlreadyExists(nickname);
}
private void checkAndThrowIfUserAlreadyExists(String uid) {
// 이미 존재하는 유저인 경우 예외처리
if (userRepository.existsByUid(uid)) {
throw new CustomException(CommonCode.ALREADY_EXIST_USER);
}
}
private void checkAndThrowIfNicknameAlreadyExists(String nickname) {
// 이미 존재하는 닉네임인 경우 예외처리
if (userRepository.existsByNickname(nickname)) {
throw new CustomException(CommonCode.ALREADY_EXIST_NICKNAME);
}
}
⇒ 확실히 추상화 수준을 신경씀으로써 회원가입 로직의 흐름을 명확히 전달할 수 있었고, 이에 따라 가독성이 눈에 띄게 개선되었다고 느꼈습니다.
하지만, 하기의 경우는 추상화 수준을 올바르게 적용한 것인지 의문이 들었습니다.
public ReadUserTestingStats readAnotherTestingStats(Long targetUserId, Long myUserId) {
User targetUser = userRepository.findById(targetUserId)
.orElseThrow(() -> new CustomException(CommonCode.NONEXISTENT_USER));
long interactionCounts = userInteractionStatusRepository.countUserInteractionStatusByUserId(myUserId,
targetUserId);
return readUserTestingStats(targetUser, interactionCounts);
}
public ReadUserTestingStats readAnotherTestingStats(Long targetUserId, Long myUserId) {
User targetUser = findUserByIdOrThrowIfNonexistentUser(targetUserId);
long interactionCounts = getInteractionCountBy(targetUserId, myUserId);
return readUserTestingStats(targetUser, interactionCounts);
}
private User findUserByIdOrThrowIfNonexistentUser(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new CustomException(CommonCode.NONEXISTENT_USER));
}
private long getInteractionCountBy(Long targetUserId, Long myUserId) {
return userInteractionStatusRepository.countUserInteractionStatusByUserId(myUserId, targetUserId);
}
리팩토링을 진행해보니, 추상화 수준을 고려하며 코드를 생산하는 과정의 필요성을 체감할 수 있었습니다.
이를 지키며 개발을 하게되면 명확하게 핵심만 전달할 수 있기에 가독성 측면에서 많은 이점을 지닌다는 것을 느꼈습니다.
그렇지만 어느정도 깊이까지 이를 엄격히 지켜야 하는지 판단하는 것은 아직까진 어렵고, 미숙하다는 것을 느낍니다.
피드백은 언제나 환영입니다! 🙇🏻♂️