https://github.com/nyoongoon/practical-enum-app
안녕하세요~ 고린내(goal-in-next)입니다.
이번 시간에는 레거시 코드들을 Enum Class을 사용하여 리팩토링 하는 시간을 가져볼까 합니다.
(그런데, Enum을 Class라고 봐도 될까요?)
기존을 하드코딩되어 배드 스멜 코드들을 Enum을 사용하여 클-린하게 바꿔볼 것인데요,
크게 두 부분을 봐볼까 합니다.
1. 로직단에서의 Enum 활용 (일치, 포함 분기 공통화)
2. JPA 엔티티에서의 활용 (@Converter 사용)
우선, 이번 게시물에서는 레거시 코드를 보면서 문제점이 되는 부분들을 찾아볼게요.
(아래 엔티티는 더 복잡한 상황을 가정하기 위해 복합키로 구성해보았습니다)
@Entity
@Table(name = "post")
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
@IdClass(PostId.class)
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Id // 심지어 복합키인 상황..!
@Column(name="some_code)
private String someCode;
@Column(name="title")
private String title;
@Column(name="content")
private String content;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "category_code")
private String categoryCode; // 코드 타입에 문자열 사용
@Column(name = "delete_type")
private String deleteType; // 코드 타입에 문자열 사용
@Column(name = "expenditure_code")
private String expenditureCode; // 코드 타입에 문자열 사용
@Column(name = "industry_code")
private String industryCode; // 코드 타입에 문자열 사용
@OneToMany(mappedBy = "post")
private List<Comment> commentsList;
// 엔티티 내부 값 변경 로직에 하드코딩 사용
public void deletePost(){
this.deleteType = "Y";
}
}
@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("잘못된 카테고리입니다");
}
}
// ..
}
@Service
@RequiredArgsConstructor
@Transactional
public class PostService {
private final PostRepository postRepository;
// ...
public void weirdBusinessLogic(PostForm postForm) {
validator.validateExpenditureCode(postForm);
Post post = postForm.toEntity();
// 하드코딩된 코드값 일치 판단 후, 하드코딩된 값으로 엔티티 업데이트
if (post.getExpenditureCode().equals("CD000001")) {
post.updateIndustryCode("IC000003");
}
postRepository.save(post);
}
// ...
}
문제점들이 보이시나요~?
이제 하나 하나 리팩토링 대상을 분석해봅시다.
1. 엔티티에서 코드값에 대한 필드가 String으로 타입 지정되어 있는 상황..
@Column(name = "category_code")
private String categoryCode; // 코드 타입에 문자열 사용
@Column(name = "expenditure_code")
private String expenditureCode; // 코드 타입에 문자열 사용
-> 위처럼 사용되고 있는 필드들은, 도메인 측면에서 보자면 일정한 값들을 가진 고정된 상수들만 쓰이는 상황이 대부분일 겁니다.
하지만 문자열 타입으로 지정되어 있기 때문에, 위의 코드만으로는 어떤 값이 들어갈지 감히 추측하기도 힘들고, 코드상에선 아무 값이나 받을 수 있게 됩니다.
특히 두 번째의 필드 같이 특정 도메인에서만 사용될 법한 코드들이라면 관리하기 더더욱 어려워지겠죠?
2. 분기 처리 시 여러 코드값 equals() 비교해야하는 상황..
if (categoryCode.equals("CT000001") ||
categoryCode.equals("CT000002") ||
categoryCode.equals("CT000003") ||
categoryCode.equals("CT000004")) {
// ...
}
-> 위 같은 상황에서 가독성 없는 문자열 코드만으로 로직을 처리하기 힘들어 보입니다..
위의 예시보다 더 복잡한 로직에서 일일히 숫자 값이 맞는지 DB를 뒤져가며 개발하는 건 이제 그만 ~
3. 하드코딩 때문에 도메인 로직이 보이지 않는 상황..
public void weirdBusinessLogic(PostForm postForm) {
validator.validateExpenditureCode(postForm);
Post post = postForm.toEntity();
// 하드코딩된 코드값 일치 판단 후, 하드코딩된 값으로 엔티티 업데이트
if (post.getExpenditureCode().equals("CD000001")) {
post.updateIndustryCode("IC000003");
}
postRepository.save(post);
}
-> 기획팀에서 이상한 비즈니스 로직을 기획해왔습니다.
가뜩이나 이상한 비즈니스 로직에, 이해할 수 없는 코드를 하드코딩하는 로직은
그 자체만으로는 도저히 어떤 작업인지 알 수가 없어 보입니다...
자, 다음 게시물부터 문제점을 하나씩 처리해 보실까요?
https://goalinnext.tistory.com/33
'백엔드 > Java' 카테고리의 다른 글
천사와 악마 사이 추상클래스... - 인터페이스 및 정적 유틸리티 클래스 비교 - 2 (5) | 2024.02.13 |
---|---|
천사와 악마 사이 추상클래스... - 인터페이스 및 정적 유틸리티 클래스 비교 - 1 (0) | 2024.02.01 |
이넘아 놀자 4 - 인터페이스 사용하여 Enum 공통화하기 (0) | 2023.09.03 |
이넘아 놀자 - 3. 코드값으로 되어있는 Enum의 경우 (0) | 2023.08.28 |
이넘아 놀자 - 2. 일단 만들까 이넘 (0) | 2023.08.28 |