Skip to content

Commit cb9d02f

Browse files
authored
refactor: 도서 도메인 리팩토링 (#37)
* [BOOK-131] refactor: apis - apis모듈 리팩토링 service 반환 DTO로 통일 (#34) * [BOOK-131] refactor: domain - domainservice 반환 VO로 통일 (#34) * [BOOK-131] refactor: apis - from 컨벤션에 맞게 수정 (#34) * [BOOK-131] refactor: apis - UserBookService 타입지정 (#34) * [BOOK-131] refactor: domain - VO init 검증코드 (#34) * [BOOK-131] refactor: domain - 빠진필드 추가 (#34) * [BOOK-131] refactor: apis - dto자체를 넘기는방식으로 변경 (#34)
1 parent 0f4758b commit cb9d02f

File tree

13 files changed

+228
-45
lines changed

13 files changed

+228
-45
lines changed

apis/src/main/kotlin/org/yapp/apis/book/dto/request/BookCreateRequest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package org.yapp.apis.book.dto.request
33
import jakarta.validation.constraints.NotBlank
44
import jakarta.validation.constraints.Size
55
import org.yapp.apis.book.dto.response.BookDetailResponse
6-
import org.yapp.domain.book.Book
76

87
data class BookCreateRequest private constructor(
98
@field:NotBlank(message = "ISBN은 필수입니다.")
@@ -32,7 +31,7 @@ data class BookCreateRequest private constructor(
3231

3332
companion object {
3433

35-
fun create(bookDetail: BookDetailResponse): BookCreateRequest {
34+
fun from(bookDetail: BookDetailResponse): BookCreateRequest {
3635
val finalIsbn = bookDetail.isbn ?: bookDetail.isbn13
3736
?: throw IllegalArgumentException("ISBN이 존재하지 않습니다.")
3837

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.yapp.apis.book.dto.request
2+
3+
import org.yapp.apis.book.dto.response.BookCreateResponse
4+
import org.yapp.apis.book.dto.response.UserBookResponse
5+
import org.yapp.domain.userbook.BookStatus
6+
import java.util.UUID
7+
8+
9+
data class UpsertUserBookRequest private constructor(
10+
val userId: UUID,
11+
val bookIsbn: String,
12+
val bookTitle: String,
13+
val bookAuthor: String,
14+
val bookPublisher: String,
15+
val bookCoverImageUrl: String,
16+
val status: BookStatus
17+
) {
18+
companion object {
19+
fun of(
20+
userId: UUID,
21+
bookCreateResponse: BookCreateResponse,
22+
status: BookStatus
23+
): UpsertUserBookRequest {
24+
return UpsertUserBookRequest(
25+
userId = userId,
26+
bookIsbn = bookCreateResponse.isbn,
27+
bookTitle = bookCreateResponse.title,
28+
bookAuthor = bookCreateResponse.author,
29+
bookPublisher = bookCreateResponse.publisher,
30+
bookCoverImageUrl = bookCreateResponse.coverImageUrl,
31+
status = status
32+
)
33+
}
34+
}
35+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.yapp.apis.book.dto.response
2+
3+
import org.yapp.domain.book.vo.BookVO
4+
5+
data class BookCreateResponse private constructor(
6+
val isbn: String,
7+
val title: String,
8+
val author: String,
9+
val publisher: String,
10+
val coverImageUrl: String
11+
) {
12+
companion object {
13+
fun from(bookVO: BookVO): BookCreateResponse {
14+
return BookCreateResponse(
15+
isbn = bookVO.isbn,
16+
title = bookVO.title,
17+
author = bookVO.author,
18+
publisher = bookVO.publisher,
19+
coverImageUrl = bookVO.coverImageUrl
20+
)
21+
}
22+
}
23+
}

apis/src/main/kotlin/org/yapp/apis/book/dto/response/BookDetailResponse.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ data class BookDetailResponse private constructor(
2929
) {
3030
companion object {
3131

32+
3233
fun from(response: AladinBookDetailResponse): BookDetailResponse {
3334
val bookItem = response.item?.firstOrNull()
3435
?: throw IllegalArgumentException("No book item found in detail response.")

apis/src/main/kotlin/org/yapp/apis/book/dto/response/UserBookResponse.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package org.yapp.apis.book.dto.response
22

33
import org.yapp.domain.userbook.BookStatus
4-
import org.yapp.domain.userbook.UserBook
4+
import org.yapp.domain.userbook.vo.UserBookVO
55
import java.time.format.DateTimeFormatter
6-
import java.util.*
6+
import java.util.UUID
77

88
data class UserBookResponse private constructor(
99
val userBookId: UUID,
@@ -20,7 +20,7 @@ data class UserBookResponse private constructor(
2020

2121
companion object {
2222
fun from(
23-
userBook: UserBook,
23+
userBook: UserBookVO,
2424
): UserBookResponse {
2525
return UserBookResponse(
2626
userBookId = userBook.id,

apis/src/main/kotlin/org/yapp/apis/book/service/BookManagementService.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ package org.yapp.apis.book.service
22

33
import org.springframework.stereotype.Service
44
import org.yapp.apis.book.dto.request.BookCreateRequest
5-
import org.yapp.domain.book.Book
5+
import org.yapp.apis.book.dto.response.BookCreateResponse
66
import org.yapp.domain.book.BookDomainService
77

88
@Service
99
class BookManagementService(
1010
private val bookDomainService: BookDomainService
1111
) {
12-
fun findOrCreateBook(request: BookCreateRequest): Book {
12+
fun findOrCreateBook(request: BookCreateRequest): BookCreateResponse {
1313
val isbn = request.validIsbn()
1414

15-
return bookDomainService.findByIsbn(isbn)
15+
val bookVO = bookDomainService.findByIsbn(isbn)
1616
?: bookDomainService.save(
1717
isbn = isbn,
1818
title = request.validTitle(),
@@ -22,6 +22,7 @@ class BookManagementService(
2222
publicationYear = request.publicationYear,
2323
description = request.description
2424
)
25+
return BookCreateResponse.from(bookVO)
2526
}
2627

2728
}
Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
11
package org.yapp.apis.book.service
22

33
import org.springframework.stereotype.Service
4+
import org.yapp.apis.book.dto.request.UpsertUserBookRequest
5+
import org.yapp.apis.book.dto.response.UserBookResponse
46
import org.yapp.domain.book.Book
57
import org.yapp.domain.userbook.UserBookDomainService
68
import org.yapp.domain.userbook.BookStatus
9+
import org.yapp.domain.userbook.vo.UserBookVO
710
import java.util.*
811

912
@Service
1013
class UserBookService(
1114
private val userBookDomainService: UserBookDomainService
1215
) {
13-
fun upsertUserBook(userId: UUID, book: Book, status: BookStatus) =
14-
userBookDomainService.upsertUserBook(userId, book, status)
16+
fun upsertUserBook(upsertUserBookRequest: UpsertUserBookRequest): UserBookResponse =
17+
UserBookResponse.from(
18+
userBookDomainService.upsertUserBook(
19+
upsertUserBookRequest.userId,
20+
upsertUserBookRequest.bookIsbn,
21+
upsertUserBookRequest.bookPublisher,
22+
upsertUserBookRequest.bookAuthor,
23+
upsertUserBookRequest.bookTitle,
24+
upsertUserBookRequest.bookCoverImageUrl,
25+
upsertUserBookRequest.status
26+
)
27+
)
1528

16-
fun findAllUserBooks(userId: UUID) =
17-
userBookDomainService.findAllUserBooks(userId)
29+
fun findAllUserBooks(userId: UUID): List<UserBookResponse> {
30+
val userBooks: List<UserBookVO> = userBookDomainService.findAllUserBooks(userId)
31+
return userBooks.map { userBook: UserBookVO ->
32+
UserBookResponse.from(userBook)
33+
}
34+
}
1835
}

apis/src/main/kotlin/org/yapp/apis/book/usecase/BookUseCase.kt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import org.yapp.apis.book.dto.response.BookDetailResponse
1111
import org.yapp.apis.book.dto.response.BookSearchResponse
1212
import org.yapp.apis.book.dto.response.UserBookResponse
1313
import org.yapp.apis.book.constant.BookQueryServiceQualifier
14+
import org.yapp.apis.book.dto.request.UpsertUserBookRequest
1415
import org.yapp.apis.book.service.BookManagementService
1516
import org.yapp.apis.book.service.BookQueryService
1617
import org.yapp.apis.book.service.UserBookService
@@ -20,10 +21,12 @@ import java.util.UUID
2021
@UseCase
2122
@Transactional(readOnly = true)
2223
class BookUseCase(
23-
private val userAuthService: UserAuthService,
24-
private val userBookService: UserBookService,
24+
2525
@Qualifier(BookQueryServiceQualifier.ALADIN)
2626
private val bookQueryService: BookQueryService,
27+
28+
private val userAuthService: UserAuthService,
29+
private val userBookService: UserBookService,
2730
private val bookManagementService: BookManagementService
2831
) {
2932
fun searchBooks(request: BookSearchRequest): BookSearchResponse {
@@ -38,20 +41,23 @@ class BookUseCase(
3841
fun upsertBookToMyLibrary(userId: UUID, request: UserBookRegisterRequest): UserBookResponse {
3942
userAuthService.validateUserExists(userId)
4043

41-
val detail = bookQueryService.getBookDetail(BookDetailRequest.of(request.validBookIsbn()))
42-
43-
val book = bookManagementService.findOrCreateBook(BookCreateRequest.create(detail))
44+
val bookDetailResponse = bookQueryService.getBookDetail(BookDetailRequest.of(request.validBookIsbn()))
4445

45-
val userBook = userBookService.upsertUserBook(userId, book, request.bookStatus)
46+
val bookCreateResponse = bookManagementService.findOrCreateBook(BookCreateRequest.from(bookDetailResponse))
47+
val upsertUserBookRequest = UpsertUserBookRequest.of(
48+
userId = userId,
49+
bookCreateResponse,
50+
status = request.bookStatus
51+
)
52+
val userBookResponse = userBookService.upsertUserBook(upsertUserBookRequest)
4653

47-
return UserBookResponse.from(userBook)
54+
return userBookResponse
4855
}
4956

5057

5158
fun getUserLibraryBooks(userId: UUID): List<UserBookResponse> {
5259
userAuthService.validateUserExists(userId)
5360

5461
return userBookService.findAllUserBooks(userId)
55-
.map(UserBookResponse::from)
5662
}
5763
}
Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package org.yapp.domain.book
22

3+
import org.yapp.domain.book.vo.BookVO
34
import org.yapp.globalutils.annotation.DomainService
45

56
@DomainService
67
class BookDomainService(
78
private val bookRepository: BookRepository
89
) {
9-
fun findByIsbn(isbn: String): Book? {
10-
return bookRepository.findByIsbn(isbn)
10+
fun findByIsbn(isbn: String): BookVO? {
11+
return bookRepository.findByIsbn(isbn)?.let { BookVO.newInstance(it) }
1112
}
1213

1314
fun save(
@@ -18,12 +19,8 @@ class BookDomainService(
1819
coverImageUrl: String,
1920
publicationYear: Int? = null,
2021
description: String? = null
21-
): Book {
22-
findByIsbn(isbn)?.let {
23-
return it
24-
}
25-
26-
val book = Book.create(
22+
): BookVO {
23+
val book = bookRepository.findByIsbn(isbn) ?: Book.create(
2724
isbn = isbn,
2825
title = title,
2926
author = author,
@@ -33,6 +30,7 @@ class BookDomainService(
3330
description = description
3431
)
3532

36-
return bookRepository.save(book)
33+
val savedBook = bookRepository.save(book)
34+
return BookVO.newInstance(savedBook)
3735
}
3836
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.yapp.domain.book.vo
2+
3+
import org.yapp.domain.book.Book
4+
5+
data class BookVO private constructor(
6+
val isbn: String,
7+
val title: String,
8+
val author: String,
9+
val publisher: String,
10+
val coverImageUrl: String,
11+
val publicationYear: Int?,
12+
val description: String?
13+
) {
14+
init {
15+
require(isbn.isNotBlank()) { "ISBN은 비어 있을 수 없습니다." }
16+
require(title.isNotBlank()) { "제목은 비어 있을 수 없습니다." }
17+
require(author.isNotBlank()) { "저자는 비어 있을 수 없습니다." }
18+
publicationYear?.let { require(it > 0) { "출판 연도는 0보다 커야 합니다." } }
19+
}
20+
21+
companion object {
22+
fun newInstance(
23+
book: Book
24+
): BookVO {
25+
return BookVO(
26+
book.isbn,
27+
book.title,
28+
book.author,
29+
book.publisher,
30+
book.coverImageUrl,
31+
book.publicationYear,
32+
book.description
33+
)
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)