TemporaryPassword refactoring - leegwichan/StackOverFlow_Refactoring GitHub Wiki

◎ 기존 작성 방법

  • 코드에 필요한 요소들을 생각 나는대로 작성함
  • 기능 구현에만 초점을 맞춤

◎ 기존 작성 방법의 문제점

  • 변경을 하는 것이 어려움
    • method 하나에서 많은 기능을 수행하여 보기 힘듦
    • ex) 기존에 랜덤 문자에 대문자도 추가하려고 한다면, 코드의 전반적인 과정을 모두 이해하고 수정하여야 한다.
  • method가 실행 될 때마다 Random 객체 생성
  • return 값이 String[]으로 되어 있어 각각의 Array 칸이 어떤 역할을 하는지 한눈에 알 수 없다.

◎ Refactoring 중점 사항

  • method를 여러개로 나눔

    • method 하나에서 하나의 기능만을 하도록 구성함
    • method line을 15줄이 넘어가지 않도록 작성
  • Random 객체를 class 클래스 변수로 생성함

    • Random 객체를 한번만 생성하고 필요할 때마다 사용함
  • return 형식을 PasswordDto로 함

    • PasswordDto를 만들어 기본 password 정보와 암호화된 password 정보를 return함
    • getter를 통해 해당 정보를 가져올 수 있어 데이터를 명확하게 사용할 수 있다.

◎ Refactoring 효과

  • 변경에 매우 용이함

    • 임시 비밀번호의 글자 수를 바꾸고 싶다면 PASSWORD_LENGTH 수정
    • 임시 비밀번호에 들어가는 글자를 바꾸고 싶다면 createRandomLetter() 수정
  • return 형식을 PasswordDto로 하면서 외부에서 사용시 값을 명확하게 알 수 있다.

      @Override
      public void resetPasswordByEmail(String email) {
          Member findMember = findMemberByEmailExpectExist(email);
    
          PasswordDto newPassword = temporaryPassword.create();
          temporaryPasswordSender.send(email, newPassword.getDecodedPassword());
    
          findMember.updatePassword(newPassword.getEncodedPassword());
          memberRepository.save(findMember);
      }
    

◎ 변경 이후 코드

@Component
public class TemporaryPassword {

    private static final char START_LETTER = 'a';
    private static final char END_LETTER = 'z';
    private static final int PASSWORD_LENGTH = 10;

    private final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    private final Random random = new Random();

    public PasswordDto create(){
        String generatedPassword = createRandomPassword();
        String encodedPassword = encoder.encode(generatedPassword);

        return new PasswordDto(generatedPassword, encodedPassword);
    }

    private String createRandomPassword() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < PASSWORD_LENGTH; i++) {
            sb.append(createRandomLetter());
        }
        return sb.toString();
    }

    private char createRandomLetter() {
        int randomASCIICode = START_LETTER + random.nextInt(END_LETTER - START_LETTER);
        char randomLetter = (char) randomASCIICode;
        return randomLetter;
    }
}

@AllArgsConstructor
@Getter
public class PasswordDto {

    private String decodedPassword;
    private String encodedPassword;
}

◎ 변경 이전 코드

@Component
@RequiredArgsConstructor
public class TemporaryPassword {

    private final BCryptPasswordEncoder encoder;

    public String[] create(){

        int leftLimit = 97; // letter 'a'
        int rightLimit = 122; // letter 'z'
        int targetStringLength = 10;
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < targetStringLength; i++) {
            int randomLimitedInt = leftLimit + (int)
                    (random.nextFloat() * (rightLimit - leftLimit + 1));
            sb.append((char) randomLimitedInt);
        }

        String generatedString = sb.toString();
        String encodeString = encoder.encode(generatedString);

        return new String[]{generatedString, encodeString};
    }
}