728x90
String 클래스 단점
- 클라이언트에서 들어오는 type 필드에 무엇이 들어올지 모른다(서버에서 검증 로직을 작성해 줄 수 있지만, 코드를 추가 작성해야 하는 부담이 있다)
- 코드만 보았을 때, Book 테이블의 type 필드에 어떤 값들이 있는지 알 수 없다.
- type과 관련한 새로운 로직을 작성해야 할 때, 분기 로직이 들어간다.
예를 들어 type에 따라 점수를 주는 로직을 작성해야 한다면 아래와 같은 로직이 들어갈 것이다.
fun getEventScore(): Int {
return when (type) {
"COMPUTER" -> 10
"ECONOMY" -> 8
"SOCIETY", "LANGUAGE", "SCIENCE" -> 5
else -> throw IllegalArgumentException("잘못된 타입입니다")
}
}
- switch을 분기문이 들어가므로 타입이 추가될 때 실수로 추가하지 않거나, 누락되는 문제가 발생할 수 있다.
- else 문 같은경우 절대 동작될 수 없지만, 추가해야 되는 단점이 있다.
이러한 단점을 해결하기 위해서는 Enum 클래스를 적극 활용하자
Enum 클래스
BookType 클래스
enum class BookType {
COMPUTER,
ECONOMY,
SOCIETY,
LANGUAGE,
SCIENCE,
}
Book
@Entity
class Book(
val name: String,
@Enumerated(EnumType.STRING)
val type: BookType, //책 타입 추가
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
) {
//기본 생성자가 없는 오류가 발생(플러그인을 받으면 오류 해결)
init { // 초기화 블록
if (name.isBlank()) {
throw IllegalArgumentException("이름은 비어 있을 수 없습니다")
}
}
companion object{ //동반객체가 가장 아래 들어가는게 컨벤션
//Object Mother 패턴
fun fixture(
name: String="책 이름",
type: BookType = BookType.COMPUTER,
id:Long? = null,
): Book{
return Book(
name = name,
type = type,
id = id,
)
}
}
}
BookRequest
data class BookRequest(
val name: String,
val type: BookType,
)
BookServiceTest
@Test
@DisplayName("책 등록이 정상 동작한다")
fun saveBookTest() {
//given
val request = BookRequest("이상한 나라의 엘리스", BookType.COMPUTER)
//when
bookService.saveBook(request)
//then
val books = bookRepository.findAll()
assertThat(books).hasSize(1)
assertThat(books[0].name).isEqualTo("이상한 나라의 엘리스")
assertThat(books[0].type).isEqualTo(BookType.COMPUTER)
}
- Enum 클래스 같은 경우 패키지 위치를 3가지에 둘 수 있다 -> 큰 장단점이 있지 않으므로, 팀 컨벤션을 지키자.
- 엔티티 파일에 같이 두기
- 도메인 하위 패키지에 두기
- type/도메인 패키지에 두기
- fixture를 호출하여 테스트 코드를 작성했기 때문에 오류가 발생하지 않는다.
- 기존에 발생한 문제들이 모두 해결이 되었다.
- 클라이언트에서 들어오는 type 필드에 무엇이 들어올지 모른다 -> 존재하지 않는 값을 넣으면, 400 에러로 서버에서 Enum을 확인해 자동으로 막아준다.
- 코드만 보았을때 Book 테이블의 type 필드에 어떤 값들이 있는지 알 수 없다 -> Enum 코드만 보면, 바로 알 수 있으며, 주석을 활용하면 코드의 유지보수를 용이하게 할 수도 있다.
- type과 관련한 새로운 로직을 작성할 때, 분기로직이 발생한다 -> 더 이상 분기 로직이 아닌 Enum 타입을 생성자에 점수를 미리 넣어 프로퍼티처럼 바로 가지고 올 수 있다(유지보수성 용이)
enum class BookType(val score: Int) {
COMPUTER(10),
ECONOMY(8),
SOCIETY(5),
LANGUAGE(5),
SCIENCE(5) }
fun getEventScore(): Int {
return this.type.score
}
- @Enumerated(EnumType.STRING) 애노테이션을 사용해 DB에도 숫자가 아닌 String이 들어가도록해야한다.
- 숫자가 들어가면 값이 추가, 삭제되면 데이터의 적합성이 깨지는 단점이 있기 때문에 반드시 String값을 저장해야 한다.
728x90
'실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기' 카테고리의 다른 글
| Ch03. 요구사항 추가(type, 대출현황) - 도서 대출 현황 요구사항 추가 (0) | 2022.11.06 |
|---|---|
| Ch03. 요구사항 추가(type, 대출현황) - UserLoanHistory의 isReturn을 Enum으로 변경하기 (0) | 2022.11.05 |
| Ch03. 요구사항 추가(type, 대출현황) - Java 서버를 Kotlin 서버로 리팩토링하자 - 책의 분야 추가하기 (0) | 2022.11.05 |
| Ch02. Java 서버를 Kotlin 서버로 리팩토링하자 - DTO,Controller를 Kotlin으로 변경하기 (0) | 2022.11.01 |
| Ch02. Java 서버를 Kotlin 서버로 리팩토링하자 - 서비스 계층 Kotlin으로 변경하기 (0) | 2022.11.01 |