https://github.com/nyoongoon/practical-enum-app
안녕하세요~ 고린내(goal-in-next)입니다.
이전 게시물에선 자체로 의미를 가진 경우에 대하여 간단한 Enum 클래스를 적용해보았습니다.
이번에 리팩토링할 대상은, 값 자체로는 특정한 도메인 의미를 갖지 않는 코드값들에 대한 처리입니다.
일단 작성한 Enum 클래스들을 확인해볼까요?
@Getter
@AllArgsConstructor
public enum CategoryCode {
CUSTOMER_INQUIRY("CT000001"),
FREE_BOARD("CT000002"),
REFUND_INQUIRY("CT000003"),
//...
private String code;
}
위의 Enum클래스를 보시면, 상수명과 코드값이 명시적으로 일치하지 않는 상황인 것을 알 수 있습니다.
그렇기 때문에 Enum처리가 되어 있지 않았던 예전 코드에선
코드를 통해 어떠한 비즈니스 로직이라는 것을 유추해내기 무척 어려웠습니다..
@Component
public class Validator {
public void validateCategory(PostForm postForm) {
String categoryCode = postForm.categoryCode();
if (categoryCode.equals("CT000001") || // 무슨 카테고리인거 같긴 한데..
categoryCode.equals("CT000002") ||
categoryCode.equals("CT000003") ||
categoryCode.equals("CT000004")) {
throw new IllegalArgumentException("잘못된 카테고리입니다");
}
if(categoryCode.equals("CT000005")){
throw new IllegalStateException("이상한 카테고리입니다");
}
}
}
아래는 Enum을 적용하는 과정입니다.
인텔리제이에서 친절하게도 상수명에 해당하는 코드값도 보여주므로
게비스콘 한 봉을 비운 것처럼 시-원하게 코드를 작성할 수 있습니다.
@Component
public class Validator {
public void validateCategory(PostForm postForm) {
String categoryCode = postForm.categoryCode();
if (categoryCode.equals(CategoryCode.CUSTOMER_INQUIRY.getCode()) ||
categoryCode.equals(CategoryCode.FREE_BOARD.getCode()) ||
categoryCode.equals(CategoryCode.REFUND_INQUIRY.getCode()) ||
categoryCode.equals(CategoryCode.TECH_SUPPORT.getCode())) {
throw new IllegalArgumentException("잘못된 카테고리입니다");
}
if(categoryCode.equals(CategoryCode.PRODUCT_REVIEWS.getCode())){
throw new IllegalStateException("이상한 카테고리입니다");
}
}
}
Enum을 적용한 결과 코드입니다 !
Enum을 적용하기 전에는 코드만으로 비즈니스를 이해할 수 없었는데
이제는 해당 로직이 어떠한 행위를 하는가하는 충분히 유추해볼만한 가독성이 생겼습니다 !!
여기에 CategoryCode 이늄 클래스를 static으로 import하면 좀 더 깔끔하게 코드를 정리해볼 수도 있습니다.
import static goal.in.next.demo.constant.CategoryCode.*;
@Component
public class Validator {
public void validateCategory(PostForm postForm) {
String categoryCode = postForm.categoryCode();
if (categoryCode.equals(CUSTOMER_INQUIRY.getCode()) ||
categoryCode.equals(FREE_BOARD.getCode()) ||
categoryCode.equals(REFUND_INQUIRY.getCode()) ||
categoryCode.equals(TECH_SUPPORT.getCode())) {
throw new IllegalArgumentException("잘못된 카테고리입니다");
}
if(categoryCode.equals(PRODUCT_REVIEWS.getCode())){
throw new IllegalStateException("이상한 카테고리입니다");
}
}
}
그런데, 아직도 눈에 띄는 중복 코드가 많이 보이는 것 같습니다.
equals()를 하는 반복적인 or 조건문을 깔끔하게 처리해볼까요?
public void validateCategory(PostForm postForm) {
CategoryCode categoryCode = postForm.categoryCode();
if (CategoryCode.hasCode(
List.of(CUSTOMER_INQUIRY, REFUND_INQUIRY, TECH_SUPPORT), categoryCode)) {
throw new IllegalArgumentException("잘못된 카테고리입니다");
}
if(CategoryCode.isEqual(PRODUCT_REVIEWS, categoryCode)){
throw new IllegalStateException("이상한 카테고리입니다");
}
}
-> 짠~ 처음과 비교했을 때 코드가 훨~씬 깔끔해진것 같죠?
서비스 단에서 비즈니스 로직에만 집중하기 위해서 Enum에 정의했던 getCode()나 equals() 까지 명시하지 않아도 되도록 메소드를 사용했습니다. 아래는 Enum 내부에 작성한 메소드입니다
@Getter
@AllArgsConstructor
public enum CategoryCode {
CUSTOMER_INQUIRY("CT000001"),
FREE_BOARD("CT000002"),
REFUND_INQUIRY("CT000003"),
TECH_SUPPORT("CT000004"),
PRODUCT_REVIEWS("CT000005"),
DISCUSSIONS("CT000006"),
USER_MANUALS("CT000007");
private String code;
public static boolean hasCode(List<CategoryCode> codeList, CategoryCode code){
return codeList.stream()
.anyMatch(x -> x.getCode().equals(code.getCode()));
}
public static boolean isEqual(CategoryCode categoryCode, CategoryCode code){
return categoryCode.getCode().equals(code.getCode());
}
}
위와 같은 메소드를 사용하여 코드를 훨씬 가독성있게 해줄 수 있었습니다.
그런데, 불편한 점이 아직 남아있죠?
프로젝트엔 많은 Enum 클래스들이 있을텐데, 각 Enum마다 저런 메소드를 일일히 작성해줘야할까요~?
다음 게시물에선 인터페이스를 사용하여 Enum 클래스들을 공통화 시키는 것을 해봅시다!
'백엔드 > Java' 카테고리의 다른 글
천사와 악마 사이 추상클래스... - 인터페이스 및 정적 유틸리티 클래스 비교 - 2 (5) | 2024.02.13 |
---|---|
천사와 악마 사이 추상클래스... - 인터페이스 및 정적 유틸리티 클래스 비교 - 1 (0) | 2024.02.01 |
이넘아 놀자 4 - 인터페이스 사용하여 Enum 공통화하기 (0) | 2023.09.03 |
이넘아 놀자 - 2. 일단 만들까 이넘 (0) | 2023.08.28 |
이넘아 놀자 - 1. 기존 하드코딩되어 있던 코드 문제점 분석 (0) | 2023.08.27 |