-
20221224 TIL enum으로 리팩토링!TIL 2022. 12. 24. 22:56
며칠 전 짝꿍님께서 올려주신 TIL에서 enum을 이용해서 리팩토링을 진행했다는 글을 보고,
나도 enum을 적용할 수 있는 부분이 있는 것 같아서 적용을 해보았다!
그렇지 않아도 작은 오타로 문제가 발생할 수 있을 것 같아서 리팩토링을 하는 게 좋지 않을까 생각해보고 있었는데,
짝꿍님의 도전으로 나도 용기를 내어 리팩토링을 시도해보았다.
enum은 인스턴스의 개수가 정해져있는 경우에 사용하게 된다.
대표적으로 상태 값을 사용할 때 유용한 것 같다.
내가 만든 VO 중에 질문 상태에 대한 VO가 있었고, 이 부분을 enum을 이용해서 리팩토링해보았다.
기존에는 아래와 같은 상태였다.
값 객체이기에 equals와 hashCode를 오버라이딩 해주었다.
// models/QuestionStatus.java @Embeddable public class QuestionStatus { private static final QuestionStatus OPEN = new QuestionStatus("open"); private static final QuestionStatus CLOSED = new QuestionStatus("closed"); @Column(name = "questionStatus") private String value; public QuestionStatus() { } public QuestionStatus(String value) { this.value = value; } public static QuestionStatus open() { return OPEN; } public static QuestionStatus closed() { return CLOSED; } public String value() { return value; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (other == null || getClass() != other.getClass()) { return false; } QuestionStatus otherQuestionStatus = (QuestionStatus) other; return Objects.equals(value, otherQuestionStatus.value); } @Override public int hashCode() { return Objects.hash(value); } }
enum을 사용하면, equals와 hashCode를 재정의해주지 않아도 되고, 아래와 같이 리팩토링 할 수 있다.
코드가 훨씬 간결해졌고, 실수가 발생할 확률이 낮아졌다.
// models/QuestionStatus.java public enum QuestionStatus { OPEN("open"), CLOSED("closed"); private static final Map<String, String> STATUS_MAP = Collections.unmodifiableMap( Stream.of(values()).collect(Collectors.toMap(QuestionStatus::value, QuestionStatus::name)) ); private String value; QuestionStatus() { } QuestionStatus(String value) { this.value = value; } public String value() { return value; } public static QuestionStatus of(final String value) { return QuestionStatus.valueOf(STATUS_MAP.get(value)); } }
질문의 상태에 따라서 필터링을 해야했기 때문에 위와 같이
"open", "closed" 등의 status를 받아서 enum 타입으로 반환하는 정적 팩토리 메서드도 만들어 보았다.
아래와 같은 테스트 코드를 통해 잘 작동하는지 검증해볼 수 있다.
class QuestionStatusTest { @Test void of() { String status = "open"; QuestionStatus questionStatus = QuestionStatus.of(status); assertThat(questionStatus.value()).isEqualTo(status); } }
그리고 enum타입을 사용하고 있는 @Entity에서 아래와 같이 @Enumerated(EnumType.STRING)을 붙여주면
DB에 enum의 name (내 코드에서는 OPEN 과 CLOSED)이 숫자형 대신 저장된다.
// models/Question.java @Enumerated(EnumType.STRING) private QuestionStatus status;
한 가지 걱정되는 부분은 Specification을 정의해둔 부분이었는데,
enum타입을 사용하는 경우에도 criteriaBuilder.equal이 잘 적용이 된다!
프로젝트를 하면서 다채로운 방법들을 익히고 있다!
에러를 해결하지 못하는 동안은 끝이 없는 터널을 걷는 기분이지만, 해결을 하고 나면 생각보다 별 것이 아닌 것 같다.
더 좋은 방식이 있다면 과감하게 시도를 해보자.
참고
'TIL' 카테고리의 다른 글
20221226 TIL 핵심 기능부터 작업을 해야한다 (0) 2022.12.26 20221225 TIL 외부 API 걸음마 떼기 (feat. github 소셜 로그인) (0) 2022.12.25 20221223 TIL 게시글 인기순으로 정렬하기 (0) 2022.12.23 20221222 TIL JPA에서 @Query를 이용한 사용자 정의 쿼리 날리기! (0) 2022.12.22 20221221 TIL 핸들링 해야하는 예외가 여러 개일 때 어떻게 하면 좋을까? (1) 2022.12.21