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

feat: 알송파트 유즈케이스 적용 #666

Open
wants to merge 16 commits into
base: chongdae
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result

interface AuthRepository {
suspend fun saveLogin(
suspend fun postLogin(
accessToken: String,
fcmToken: String,
): Result<Member, DataError.Network>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class AuthRepositoryImpl
constructor(
@AuthDataSourceQualifier private val authRemoteDataSource: AuthRemoteDataSource,
) : AuthRepository {
override suspend fun saveLogin(
override suspend fun postLogin(
accessToken: String,
fcmToken: String,
): Result<Member, DataError.Network> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.zzang.chongdae.di.annotations

import javax.inject.Qualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class CheckAlreadyLoggedInUseCaseQualifier
Copy link
Contributor

Choose a reason for hiding this comment

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

usecase 구현체가 1개 인것으로 하는데 굳이 Qualifier를 설정하는 이유가 궁금해요!!
제가 모르는 다른 이유가 있나요? 🧐

Copy link
Contributor Author

@songpink songpink Dec 21, 2024

Choose a reason for hiding this comment

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

일단은 구현체가 추가될 것에 대비해서 Qualifier를 설정 해두었습니다.

usecase를 추상화 하지 않아도 된다라는 피드백이라면, 목요일에 서기와도 얘기를 했던 부분인데요,
https://mashup-android.vercel.app/mashup-11th/heejin/useCase/useCase/
위 링크에서 usecase를 interface로 추상화 했길래, 저도 추상화 했습니다.

서기도 usecase를 추상화 할 필요까지는 없다는 의견을 주었는데요, 저도 대체적으로 동의하지만 저는 usecase를 처음 적용해 보는 것이기도 해서 위 블로그 내용을 최대한 따라하려고 노력했고, 또 확장성의 관점에서 usecase를 추상화 함으로써 비즈니스 로직이 바뀔 경우 구현체만 교체하는 방식으로 수정이 용이해지는 장점이 있다고 생각해서 이렇게 구현했습니다. 서기와 채채는 usecase를 추상화 하지 않고 구현해도 된다고 생각합니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

저는 usecase에 대한 구현체가 여러개가 된다는 가정이 필요없다는 의견이어서 이렇게 코멘트를 남겼습니다! 불필요한 복잡도가 늘어나는 것을 경계해야한다고 생각하기 때문에!! 하지만 알송의 코멘트를 통해서 알송의 생각을 알게되었숩니다 감사해요~


@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class PostLoginUseCaseQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class PostOfferingUseCaseQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class UploadImageFileUseCaseQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class PostProductImageOgUseCaseQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class FetchOfferingDetailUseCaseQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class PostOfferingModifyUseCaseQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class UpdateCommentRoomsUseCaseQualifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.zzang.chongdae.di.module

import com.zzang.chongdae.di.annotations.CheckAlreadyLoggedInUseCaseQualifier
import com.zzang.chongdae.di.annotations.FetchOfferingDetailUseCaseQualifier
import com.zzang.chongdae.di.annotations.PostLoginUseCaseQualifier
import com.zzang.chongdae.di.annotations.PostOfferingModifyUseCaseQualifier
import com.zzang.chongdae.di.annotations.PostOfferingUseCaseQualifier
import com.zzang.chongdae.di.annotations.PostProductImageOgUseCaseQualifier
import com.zzang.chongdae.di.annotations.UpdateCommentRoomsUseCaseQualifier
import com.zzang.chongdae.di.annotations.UploadImageFileUseCaseQualifier
import com.zzang.chongdae.domain.usecase.comment.UpdateCommentRoomsUseCase
import com.zzang.chongdae.domain.usecase.comment.UpdateCommentRoomsUseCaseImpl
import com.zzang.chongdae.domain.usecase.login.CheckIfAlreadyLoggedInUseCase
import com.zzang.chongdae.domain.usecase.login.CheckIfAlreadyLoggedInUseCaseImpl
import com.zzang.chongdae.domain.usecase.login.PostLoginUseCase
import com.zzang.chongdae.domain.usecase.login.PostLoginUseCaseImpl
import com.zzang.chongdae.domain.usecase.offeringmodify.FetchOfferingDetailUseCase
import com.zzang.chongdae.domain.usecase.offeringmodify.FetchOfferingDetailUseCaseImpl
import com.zzang.chongdae.domain.usecase.offeringmodify.PostOfferingModifyUseCase
import com.zzang.chongdae.domain.usecase.offeringmodify.PostOfferingModifyUseCaseImpl
import com.zzang.chongdae.domain.usecase.write.PostOfferingUseCase
import com.zzang.chongdae.domain.usecase.write.PostOfferingUseCaseImpl
import com.zzang.chongdae.domain.usecase.write.PostProductImageOgUseCase
import com.zzang.chongdae.domain.usecase.write.PostProductImageOgUseCaseImpl
import com.zzang.chongdae.domain.usecase.write.UploadImageFileUseCase
import com.zzang.chongdae.domain.usecase.write.UploadImageFileUseCaseImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
abstract class UseCaseDependencyModule {
@Binds
@Singleton
@CheckAlreadyLoggedInUseCaseQualifier
abstract fun provideCheckIfAlreadyLoggedInUseCase(impl: CheckIfAlreadyLoggedInUseCaseImpl): CheckIfAlreadyLoggedInUseCase

@Binds
@Singleton
@PostLoginUseCaseQualifier
abstract fun providePostLoginUseCase(impl: PostLoginUseCaseImpl): PostLoginUseCase

@Binds
@Singleton
@PostOfferingUseCaseQualifier
abstract fun providePostOfferingUseCase(impl: PostOfferingUseCaseImpl): PostOfferingUseCase

@Binds
@Singleton
@UploadImageFileUseCaseQualifier
abstract fun provideUploadImageFileUseCase(impl: UploadImageFileUseCaseImpl): UploadImageFileUseCase

@Binds
@Singleton
@PostProductImageOgUseCaseQualifier
abstract fun providePostProductImageOgUseCase(impl: PostProductImageOgUseCaseImpl): PostProductImageOgUseCase

@Binds
@Singleton
@FetchOfferingDetailUseCaseQualifier
abstract fun provideFetchOfferingDetailUseCase(impl: FetchOfferingDetailUseCaseImpl): FetchOfferingDetailUseCase

@Binds
@Singleton
@PostOfferingModifyUseCaseQualifier
abstract fun providePostOfferingModifyUseCase(impl: PostOfferingModifyUseCaseImpl): PostOfferingModifyUseCase

@Binds
@Singleton
@UpdateCommentRoomsUseCaseQualifier
abstract fun provideUpdateCommentRoomsUseCase(impl: UpdateCommentRoomsUseCaseImpl): UpdateCommentRoomsUseCase
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.zzang.chongdae.domain.usecase.comment

import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.domain.model.CommentRoom

interface UpdateCommentRoomsUseCase {
suspend operator fun invoke(): Result<List<CommentRoom>, DataError.Network>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.zzang.chongdae.domain.usecase.comment

import com.zzang.chongdae.auth.repository.AuthRepository
import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.di.annotations.AuthRepositoryQualifier
import com.zzang.chongdae.di.annotations.CommentRoomsRepositoryQualifier
import com.zzang.chongdae.domain.model.CommentRoom
import com.zzang.chongdae.domain.repository.CommentRoomsRepository
import javax.inject.Inject

class UpdateCommentRoomsUseCaseImpl
@Inject
constructor(
@AuthRepositoryQualifier private val authRepository: AuthRepository,
@CommentRoomsRepositoryQualifier private val commentRoomsRepository: CommentRoomsRepository,
) : UpdateCommentRoomsUseCase {
override suspend fun invoke(): Result<List<CommentRoom>, DataError.Network> {
return when (val result = commentRoomsRepository.fetchCommentRooms()) {
is Result.Success -> Result.Success(result.data)
is Result.Error -> {
when (result.error) {
DataError.Network.UNAUTHORIZED -> {
when (authRepository.saveRefresh()) {
is Result.Success -> invoke()
is Result.Error -> result
}
}

else -> result
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.zzang.chongdae.domain.usecase.login

interface CheckIfAlreadyLoggedInUseCase {
suspend operator fun invoke(): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.zzang.chongdae.domain.usecase.login

import com.zzang.chongdae.common.datastore.UserPreferencesDataStore
import kotlinx.coroutines.flow.first
import javax.inject.Inject

class CheckIfAlreadyLoggedInUseCaseImpl
@Inject
constructor(
private val userPreferencesDataStore: UserPreferencesDataStore,
) : CheckIfAlreadyLoggedInUseCase {
override suspend fun invoke(): Boolean {
val accessToken = userPreferencesDataStore.accessTokenFlow.first()
return accessToken != null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.zzang.chongdae.domain.usecase.login

import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result

interface PostLoginUseCase {
suspend operator fun invoke(
accessToken: String,
fcmToken: String,
): Result<Unit, DataError.Network>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.zzang.chongdae.domain.usecase.login

import com.zzang.chongdae.auth.repository.AuthRepository
import com.zzang.chongdae.common.datastore.UserPreferencesDataStore
import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.di.annotations.AuthRepositoryQualifier
import javax.inject.Inject

class PostLoginUseCaseImpl
@Inject
constructor(
@AuthRepositoryQualifier private val authRepository: AuthRepository,
private val userPreferencesDataStore: UserPreferencesDataStore,
) : PostLoginUseCase {
override suspend fun invoke(
accessToken: String,
fcmToken: String,
): Result<Unit, DataError.Network> {
return when (val result = authRepository.postLogin(accessToken, fcmToken)) {
is Result.Success -> {
userPreferencesDataStore.saveMember(result.data.memberId, result.data.nickName)
userPreferencesDataStore.saveFcmToken(fcmToken)
Result.Success(Unit)
}

is Result.Error -> result
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.zzang.chongdae.domain.usecase.offeringmodify

import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.domain.model.OfferingDetail

interface FetchOfferingDetailUseCase {
suspend operator fun invoke(offeringId: Long): Result<OfferingDetail, DataError.Network>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.zzang.chongdae.domain.usecase.offeringmodify

import com.zzang.chongdae.auth.repository.AuthRepository
import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.di.annotations.AuthRepositoryQualifier
import com.zzang.chongdae.di.annotations.OfferingDetailRepositoryQualifier
import com.zzang.chongdae.domain.model.OfferingDetail
import com.zzang.chongdae.domain.repository.OfferingDetailRepository
import javax.inject.Inject

class FetchOfferingDetailUseCaseImpl
@Inject
constructor(
@OfferingDetailRepositoryQualifier private val offeringDetailRepository: OfferingDetailRepository,
@AuthRepositoryQualifier private val authRepository: AuthRepository,
) : FetchOfferingDetailUseCase {
override suspend fun invoke(offeringId: Long): Result<OfferingDetail, DataError.Network> {
return when (val result = offeringDetailRepository.fetchOfferingDetail(offeringId)) {
is Result.Success -> Result.Success(result.data)
is Result.Error -> {
when (result.error) {
DataError.Network.UNAUTHORIZED -> {
when (authRepository.saveRefresh()) {
is Result.Success -> invoke(offeringId)
is Result.Error -> result
}
}

else -> result
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.zzang.chongdae.domain.usecase.offeringmodify

import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.domain.model.OfferingModifyDomainRequest

interface PostOfferingModifyUseCase {
suspend operator fun invoke(
offeringId: Long,
offeringModifyDomainRequest: OfferingModifyDomainRequest,
): Result<Unit, DataError.Network>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.zzang.chongdae.domain.usecase.offeringmodify

import com.zzang.chongdae.auth.repository.AuthRepository
import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.di.annotations.AuthRepositoryQualifier
import com.zzang.chongdae.di.annotations.OfferingRepositoryQualifier
import com.zzang.chongdae.domain.model.OfferingModifyDomainRequest
import com.zzang.chongdae.domain.repository.OfferingRepository
import javax.inject.Inject

class PostOfferingModifyUseCaseImpl
@Inject
constructor(
@OfferingRepositoryQualifier private val offeringRepository: OfferingRepository,
@AuthRepositoryQualifier private val authRepository: AuthRepository,
) : PostOfferingModifyUseCase {
override suspend fun invoke(
offeringId: Long,
offeringModifyDomainRequest: OfferingModifyDomainRequest,
): Result<Unit, DataError.Network> {
return when (
val result =
offeringRepository.patchOffering(offeringId, offeringModifyDomainRequest)
) {
is Result.Success -> Result.Success(Unit)
is Result.Error -> {
when (result.error) {
DataError.Network.UNAUTHORIZED -> {
when (authRepository.saveRefresh()) {
is Result.Success -> invoke(offeringId, offeringModifyDomainRequest)
is Result.Error -> result
}
}

else -> result
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.zzang.chongdae.domain.usecase.write

import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.domain.model.OfferingWrite

interface PostOfferingUseCase {
suspend operator fun invoke(offeringWrite: OfferingWrite): Result<Unit, DataError.Network>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.zzang.chongdae.domain.usecase.write

import com.zzang.chongdae.auth.repository.AuthRepository
import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.di.annotations.AuthRepositoryQualifier
import com.zzang.chongdae.di.annotations.OfferingRepositoryQualifier
import com.zzang.chongdae.domain.model.OfferingWrite
import com.zzang.chongdae.domain.repository.OfferingRepository
import javax.inject.Inject

class PostOfferingUseCaseImpl
@Inject
constructor(
@OfferingRepositoryQualifier private val offeringRepository: OfferingRepository,
@AuthRepositoryQualifier private val authRepository: AuthRepository,
) : PostOfferingUseCase {
override suspend fun invoke(offeringWrite: OfferingWrite): Result<Unit, DataError.Network> {
return when (val result = offeringRepository.saveOffering(offeringWrite)) {
is Result.Success -> Result.Success(Unit)
is Result.Error -> {
when (result.error) {
DataError.Network.UNAUTHORIZED -> {
when (authRepository.saveRefresh()) {
is Result.Success -> invoke(offeringWrite)
is Result.Error -> result
}
}
else -> result
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.zzang.chongdae.domain.usecase.write

import com.zzang.chongdae.common.handler.DataError
import com.zzang.chongdae.common.handler.Result
import com.zzang.chongdae.domain.model.ProductUrl

interface PostProductImageOgUseCase {
suspend operator fun invoke(productUrl: String): Result<ProductUrl, DataError.Network>
}
Loading