Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔀 :: (#16) 전체 코드 리팩토링 #52

Merged
merged 10 commits into from
Apr 17, 2023
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
package com.xquare.v1servicepoint.point.api

import com.xquare.v1servicepoint.point.api.dto.request.DomainUpdatePointRoleRequest
import com.xquare.v1servicepoint.point.api.dto.request.DomainSavePointRoleRequest
import com.xquare.v1servicepoint.point.api.dto.request.DomainUpdatePointRoleRequest
import com.xquare.v1servicepoint.point.api.dto.response.PointRuleListResponse
import com.xquare.v1servicepoint.point.api.dto.response.PointStatusResponse
import com.xquare.v1servicepoint.point.api.dto.response.PointStudentStatusResponse
import java.util.UUID

interface PointApi {

suspend fun queryPointStatus(userId: UUID): PointStatusResponse

suspend fun updatePointRole(pointId: UUID, request: DomainUpdatePointRoleRequest)

suspend fun deletePointRole(pointId: UUID)

suspend fun savePointRole(request: DomainSavePointRoleRequest)

suspend fun queryPointRoleList(type: Boolean): PointRuleListResponse

suspend fun queryStudentStatus(name: String?, penaltyLevel: Int?): PointStudentStatusResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,5 @@ interface PointHistoryApi {

suspend fun queryUserPointHistoryForStudent(userId: UUID, type: String): PointHistoryListStudentResponse

suspend fun savePointStatus(userId: UUID)

suspend fun queryUserPointHistoryExcel(): ExportUserPointStatusResponse

suspend fun saveUserPenaltyEducationComplete(userId: UUID)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.xquare.v1servicepoint.point.api

import com.xquare.v1servicepoint.point.api.dto.response.PointStatusResponse
import com.xquare.v1servicepoint.point.api.dto.response.PointStudentStatusResponse
import java.util.UUID

interface PointStatusApi {

suspend fun saveUserPenaltyEducationComplete(userId: UUID)

suspend fun savePointStatus(userId: UUID)

suspend fun queryUserPointStatus(userId: UUID): PointStatusResponse

suspend fun queryStudentStatus(name: String?, penaltyLevel: Int?): PointStudentStatusResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,25 @@ import com.xquare.v1servicepoint.point.api.PointApi
import com.xquare.v1servicepoint.point.api.dto.request.DomainSavePointRoleRequest
import com.xquare.v1servicepoint.point.api.dto.request.DomainUpdatePointRoleRequest
import com.xquare.v1servicepoint.point.api.dto.response.PointRuleListResponse
import com.xquare.v1servicepoint.point.api.dto.response.PointStatusResponse
import com.xquare.v1servicepoint.point.api.dto.response.PointStudentStatusElement
import com.xquare.v1servicepoint.point.api.dto.response.PointStudentStatusResponse
import com.xquare.v1servicepoint.point.exception.PointNotFoundException
import com.xquare.v1servicepoint.point.exception.PointStatusNotFoundException
import com.xquare.v1servicepoint.point.exception.UserNotFoundException
import com.xquare.v1servicepoint.point.spi.PointHistorySpi
import com.xquare.v1servicepoint.point.spi.PointSpi
import com.xquare.v1servicepoint.point.spi.PointStatusSpi
import com.xquare.v1servicepoint.point.spi.UserSpi
import com.xquare.v1servicepoint.point.spi.point.CommandPointSpi
import com.xquare.v1servicepoint.point.spi.point.QueryPointSpi
import com.xquare.v1servicepoint.point.spi.pointhistory.QueryPointHistorySpi
import com.xquare.v1servicepoint.point.spi.pointstatus.CommandPointStatusSpi
import com.xquare.v1servicepoint.point.spi.pointstatus.QueryPointStatusSpi
import java.util.UUID

@UseCase
class PointApiImpl(
private val pointStatusSpi: PointStatusSpi,
private val pointSpi: PointSpi,
private val pointHistorySpi: PointHistorySpi,
private val userSpi: UserSpi,
private val queryPointSpi: QueryPointSpi,
private val commandPointSpi: CommandPointSpi,
private val queryPointHistorySpi: QueryPointHistorySpi,
private val queryPointStatusSpi: QueryPointStatusSpi,
private val commandPointStatusSpi: CommandPointStatusSpi,
) : PointApi {

override suspend fun queryPointStatus(userId: UUID): PointStatusResponse {
val getUserPointStatus = pointStatusSpi.findByUserId(userId)
?: throw UserNotFoundException(UserNotFoundException.USER_ID_NOT_FOUND)

return PointStatusResponse(
goodPoint = getUserPointStatus.goodPoint,
badPoint = getUserPointStatus.badPoint,
)
}

override suspend fun updatePointRole(pointId: UUID, request: DomainUpdatePointRoleRequest) {
val point = pointSpi.findByPointId(pointId)
val point = queryPointSpi.findByPointId(pointId)
?: throw PointNotFoundException(PointNotFoundException.POINT_NOT_FOUND)

val updatedPoint = point.updatePointRole(
Expand All @@ -46,31 +33,31 @@ class PointApiImpl(
point = request.point,
)

pointSpi.applyPointChanges(updatedPoint)
commandPointSpi.applyPointChanges(updatedPoint)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

command / query 나눈건 CQRS 구현한거야?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

이부분 보고 수정했는데 코멘트 달아주실거 있을까요?

Copy link
Member

@jhhong0509 jhhong0509 Apr 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CQRS를 사용한 이유는?

Copy link
Member Author

@lyutvs lyutvs Apr 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제 의도는 command와 query의 책임을 분리한다 라는 생각을 가지고 적용 해봤던것 같습니다.
interface와 구현체 모두 두가의 성격을 모두 가지고 있어 서로 다른 성격을 가지는 부분을 한부분에서 관리 한다는건 포괄적으로 관리 하는것 같아 분리했습니다.
근데 할거면 query 모델 command 모델을 따로 놔둔 상태에서 적용시켜야 했고 위에서 말했듯이 구현체도 함께 구분 했어야 했는데 그부분은 빼먹었던것 같아요

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CQRS가 정말 필요한거야?
모든 Query 거의 동일한 모델을 쓰고 있고, 복잡하지도 않아보여서

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굳이 필요하진 않은것 같아요. interface만 분리해서 사용하는걸 고려하고 있어요

}

override suspend fun deletePointRole(pointId: UUID) {
val point = pointSpi.findByPointId(pointId)
val point = queryPointSpi.findByPointId(pointId)
?: throw PointNotFoundException(PointNotFoundException.POINT_NOT_FOUND)
val userPointHistory = pointHistorySpi.findAllByPointId(point.id)
val userPointHistory = queryPointHistorySpi.findAllByPointId(point.id)

userPointHistory.forEach {
val pointStatus = pointStatusSpi.findByUserId(it.userId)
pointHistorySpi.deleteByIdAndUserId(it)
val pointStatus = queryPointStatusSpi.findByUserId(it.userId)
queryPointHistorySpi.deleteByIdAndUserId(it)

when (point.type) {
true -> {
val minusGoodPoint = pointStatus?.minusGoodPoint(point.point)
pointStatusSpi.applyPointStatusChanges(minusGoodPoint!!)
commandPointStatusSpi.applyPointStatusChanges(minusGoodPoint!!)
}

false -> {
val minusBadPoint = pointStatus?.minusBadPoint(point.point)
pointStatusSpi.applyPointStatusChanges(minusBadPoint!!)
commandPointStatusSpi.applyPointStatusChanges(minusBadPoint!!)
}
}
}
pointSpi.deletePointRole(point.id)
commandPointSpi.deletePointRole(point.id)
}

override suspend fun savePointRole(request: DomainSavePointRoleRequest) {
Expand All @@ -80,35 +67,11 @@ class PointApiImpl(
type = request.type,
point = request.point,
)
pointSpi.savePointRole(point)
commandPointSpi.savePointRole(point)
}

override suspend fun queryPointRoleList(type: Boolean): PointRuleListResponse {
val pointList = pointSpi.findAllByType(type)
val pointList = queryPointSpi.findAllByType(type)
return PointRuleListResponse(pointList)
}

override suspend fun queryStudentStatus(name: String?, penaltyLevel: Int?): PointStudentStatusResponse {
val pointStatusList = pointStatusSpi.findAllByPenaltyLevel(penaltyLevel)
val users = userSpi.getStudent()
val students = users
.filter {
name?.let { name -> it.name.contains(name) } ?: true
}.map {
val status = pointStatusList.find { pointStatus -> pointStatus.userId == it.id }
?: throw PointStatusNotFoundException(PointStatusNotFoundException.POINT_STATUS_NOT_FOUND)

PointStudentStatusElement(
id = it.id,
name = it.name,
num = "${it.grade}${it.classNum}${it.num.toString().padStart(2, '0')}",
goodPoint = status.goodPoint,
badPoint = status.badPoint,
penaltyLevel = status.penaltyLevel,
isPenaltyRequired = status.isPenaltyRequired,
)
}.sortedBy { it.num }

return PointStudentStatusResponse(students)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,24 @@ import com.xquare.v1servicepoint.point.api.dto.response.PointHistoryListResponse
import com.xquare.v1servicepoint.point.api.dto.response.PointHistoryListStudentResponse
import com.xquare.v1servicepoint.point.exception.PointHistoryNotFoundException
import com.xquare.v1servicepoint.point.exception.PointNotFoundException
import com.xquare.v1servicepoint.point.exception.UserExistException
import com.xquare.v1servicepoint.point.exception.UserNotFoundException
import com.xquare.v1servicepoint.point.exception.UserPenaltyExistException
import com.xquare.v1servicepoint.point.spi.ExcelSpi
import com.xquare.v1servicepoint.point.spi.PointHistorySpi
import com.xquare.v1servicepoint.point.spi.PointSpi
import com.xquare.v1servicepoint.point.spi.PointStatusSpi
import com.xquare.v1servicepoint.point.spi.point.QueryPointSpi
import com.xquare.v1servicepoint.point.spi.pointhistory.CommandPointHistorySpi
import com.xquare.v1servicepoint.point.spi.pointhistory.QueryPointHistorySpi
import com.xquare.v1servicepoint.point.spi.pointstatus.CommandPointStatusSpi
import com.xquare.v1servicepoint.point.spi.pointstatus.QueryPointStatusSpi
import java.nio.charset.Charset
import java.time.LocalDate
import java.util.UUID

@UseCase
class PointHistoryApiImpl(
private val pointHistorySpi: PointHistorySpi,
private val pointSpi: PointSpi,
private val pointStatusSpi: PointStatusSpi,
private val queryPointSpi: QueryPointSpi,
private val commandPointStatusSpi: CommandPointStatusSpi,
private val queryPointStatusSpi: QueryPointStatusSpi,
private val queryPointHistorySpi: QueryPointHistorySpi,
private val commandPointHistorySpi: CommandPointHistorySpi,
private val excelSpi: ExcelSpi,
) : PointHistoryApi {

Expand All @@ -35,110 +37,65 @@ class PointHistoryApiImpl(
}

override suspend fun saveUserPoint(userId: UUID, givePointUserRequest: DomainGivePointUserRequest) {
val getPointByPointId: Point = pointSpi.findByPointId(givePointUserRequest.pointId)
val getPointByPointId: Point = queryPointSpi.findByPointId(givePointUserRequest.pointId)
?: throw PointNotFoundException(PointNotFoundException.POINT_NOT_FOUND)

val pointStatus: PointStatus = pointStatusSpi.findByUserId(userId)
val pointStatus: PointStatus = queryPointStatusSpi.findByUserId(userId)
?: throw UserNotFoundException(UserNotFoundException.USER_ID_NOT_FOUND)
when (getPointByPointId.type) {
true -> {
val addGoodPoint = pointStatus.addGoodPoint(getPointByPointId.point)
pointStatusSpi.applyPointStatusChanges(addGoodPoint)
commandPointStatusSpi.applyPointStatusChanges(addGoodPoint)
}

false -> {
val addBadPoint = pointStatus.addBadPoint(getPointByPointId.point)
if (!addBadPoint.isPenaltyRequired && addBadPoint.badPoint >= PENALTY_LEVEL_LIST[addBadPoint.penaltyLevel]) {
val penaltyLevel = addBadPoint.penaltyEducationStart().penaltyLevelUp()
pointStatusSpi.applyPointStatusChanges(penaltyLevel)
commandPointStatusSpi.applyPointStatusChanges(penaltyLevel)
} else {
pointStatusSpi.applyPointStatusChanges(addBadPoint)
commandPointStatusSpi.applyPointStatusChanges(addBadPoint)
}
}
}
pointHistorySpi.saveUserPointHistory(userId, getPointByPointId.id)
}

override suspend fun saveUserPenaltyEducationComplete(userId: UUID) {
val userPointStatus = pointStatusSpi.findByUserId(userId)
?: throw UserNotFoundException(UserNotFoundException.USER_ID_NOT_FOUND)

if (!userPointStatus.isPenaltyRequired) {
throw UserPenaltyExistException(UserPenaltyExistException.USER_PENALTY_EXIST)
}

val point = pointSpi.findAllByReason(POINT_REASON)

if (userPointStatus.penaltyLevel >= 4) {
val penaltyEducationComplete = applyOutPenaltyStatusChange(userPointStatus)
val penaltyStart = calculatePenaltyStart(penaltyEducationComplete)
pointStatusSpi.applyPointStatusChanges(penaltyStart)
pointHistorySpi.saveUserListPointHistory(userId, point)
return
}

val penaltyEducationComplete = applyPenaltyStatusChanges(userPointStatus)
val penaltyStart = calculatePenaltyStart(penaltyEducationComplete)

pointStatusSpi.applyPointStatusChanges(penaltyStart)
pointHistorySpi.saveUserListPointHistory(userId, point)
}

private fun calculatePenaltyStart(penaltyEducationComplete: PointStatus): PointStatus {
val penaltyLevelUp = penaltyEducationComplete.penaltyLevelUp()
return if (penaltyEducationComplete.badPoint >= PENALTY_LEVEL_LIST[penaltyEducationComplete.penaltyLevel]) {
penaltyLevelUp.penaltyEducationStart()
} else {
penaltyEducationComplete.penaltyEducationComplete()
}
}

private fun applyPenaltyStatusChanges(pointStatus: PointStatus): PointStatus {
val pointStatusMinusGoodPoint = pointStatus.penaltyEducationCompleteAndMinusGoodPoint()
val pointStatusMinusBadPoint = pointStatusMinusGoodPoint.penaltyEducationCompleteAndMinusBadPoint()
return pointStatusMinusBadPoint.penaltyEducationComplete()
}

private fun applyOutPenaltyStatusChange(pointStatus: PointStatus): PointStatus {
val pointStatusMinusBadPoint = pointStatus.penaltyEducationCompleteAndMinusBadPoint()
return pointStatusMinusBadPoint.penaltyEducationComplete()
commandPointHistorySpi.saveUserPointHistory(userId, getPointByPointId.id)
}

override suspend fun deleteUserPoint(studentId: UUID, historyId: UUID) {
val pointHistory = pointHistorySpi.findByIdAndStudentId(historyId, studentId)
val pointHistory = queryPointHistorySpi.findByIdAndStudentId(historyId, studentId)
?: throw PointHistoryNotFoundException(PointHistoryNotFoundException.POINT_HISTORY_NOT_FOUND)

val getPointByPointId = pointSpi.findByPointId(pointHistory.pointId)
val getPointByPointId = queryPointSpi.findByPointId(pointHistory.pointId)
?: throw PointNotFoundException(PointNotFoundException.POINT_NOT_FOUND)

val pointStatus = pointStatusSpi.findByUserId(pointHistory.userId)
val pointStatus = queryPointStatusSpi.findByUserId(pointHistory.userId)
?: throw UserNotFoundException(UserNotFoundException.USER_ID_NOT_FOUND)

when (getPointByPointId.type) {
true -> {
val minusGoodPoint = pointStatus.minusGoodPoint(getPointByPointId.point)
pointStatusSpi.applyPointStatusChanges(minusGoodPoint)
commandPointStatusSpi.applyPointStatusChanges(minusGoodPoint)
}

false -> {
val minusBadPoint = pointStatus.minusBadPoint(getPointByPointId.point)
pointStatusSpi.applyPointStatusChanges(minusBadPoint)
commandPointStatusSpi.applyPointStatusChanges(minusBadPoint)
}
}

pointHistorySpi.deleteByIdAndUserId(pointHistory)
commandPointHistorySpi.deleteByIdAndUserId(pointHistory)
}

override suspend fun queryUserPointHistory(userId: UUID, type: String): PointHistoryListResponse {
val pointHistory = pointHistorySpi.findAllByUserIdAndType(userId, convertType(type))
val pointHistory = queryPointHistorySpi.findAllByUserIdAndType(userId, convertType(type))
return PointHistoryListResponse(pointHistory)
}

override suspend fun queryUserPointHistoryForStudent(userId: UUID, type: String): PointHistoryListStudentResponse {
val getUserPointStatus = pointStatusSpi.findByUserId(userId)
val getUserPointStatus = queryPointStatusSpi.findByUserId(userId)
?: throw UserNotFoundException(UserNotFoundException.USER_ID_NOT_FOUND)

val pointHistory = pointHistorySpi.findAllByUserIdAndType(getUserPointStatus.userId, convertType(type))
val pointHistory = queryPointHistorySpi.findAllByUserIdAndType(getUserPointStatus.userId, convertType(type))

return PointHistoryListStudentResponse(
goodPoint = getUserPointStatus.goodPoint,
Expand All @@ -155,21 +112,6 @@ class PointHistoryApiImpl(
}
}

override suspend fun savePointStatus(userId: UUID) {
pointStatusSpi.findByUserId(userId)?.run {
throw UserExistException(UserExistException.USER_ID_EXIST)
}

val pointStatus = PointStatus(
userId = userId,
goodPoint = 0,
badPoint = 0,
penaltyLevel = 1,
isPenaltyRequired = false,
)
pointStatusSpi.savePointStatus(pointStatus)
}

override suspend fun queryUserPointHistoryExcel(): ExportUserPointStatusResponse {
val fileName = String(
bytes = "상벌점 부여내역 ${LocalDate.now()}.xlsx".toByteArray(charset("UTF-8")),
Expand Down
Loading