오늘은 이전에 저의 멘토님께서 말씀하신 usecase을 적용을 해볼려고 코드 간결성 이 얼마나 좋아졌는지 보겠습니다.
왜 usecase을 써야 하는가
이건 이전에 제가 멘토님에게 질문했던것이랑 똑같았고 적용 이전까지도 의문 이었습니다.
Assist : usecase을 적용하면 MVVM 패턴 같은 경우는 ViewModel 이 비즈니스 로직을 담당한다고 나와있는데 그럼 viewModel 은 LiveData만 하는거 아닌가요?
멘토님 : 네 맞아요
Asisst : ?
멘토님 : 그것또한 viewModel 에 책임이죠. 비즈니스 로직을 viewModel 에 적용해도 상관은 없어요
단 viewModel 에 비즈니스 로직이 1천줄 넘어가면 그 프로그램은 나중에 더 쉽게 기능 추가나 유지보수를 할수 있을까요?
대충 이런 대화 였습니다 .
그럼 한번 적용해보러 가보겠습니다
일단 Repository을 interface으로 선언 해본다고 생각을 해보겠습니다 .
@HiltViewModel
class viewModel @Inject constructor (private val repository : Repository) : ViewModel
여기에 문제점은 무엇일까요
바로
viewModel : .... interface 만 넘기면 어쪄자고!!!!
라고 나올것 입니다
보통 Factory을 선언하면
val facotry = viewModelFactory(repositoryImpl)
이런식으로 넘기니 구현체가 무엇인지 알기 때문이죠
그럼 Hilt으로는 답이 없는가
아닙니다 더 쉽습니다
@Module
@InstallIn(SingletonComponent :: class)
object RepositoryModule {
@Provides
@Singleton
fun provideRepository( useCase: MainUseCase) : Repository {
return MainRepositoryImpl(useCase)
}
}
이런식으로 한번에 클래스를 선언해 버리면 끝납니다
이게 무슨뜻이냐
싱글톤으로 만들어서 모듈 형식으로 MainRepository 에 usecase을 넘겨주고 바로 viewModel에 넘겨주지요
--사실 쫌더 조사해서 댓글에 적어 두겠습니다. 아직 조사중이라...---
그럼 repository에도 usecase을 넘겨줫으니 그럼 한번 사용을 해보면
class MainRepositoryImpl @Inject constructor(private val useCase : MainUseCase) : Repository{
override suspend fun useUseCase (data: token , page: Int, pageSize: Int, key: String) {
val getWardRoom = RetrofitInterface.requestBaseUrl().testUsecase (data.token , data.customerId , page , pageSize , key)
getUsecaseData.enqueue(object : Callback<Any> {
override fun onResponse(call: Call<Any>, response: Response<Any>) {
when(response.code()){
Define.CALL_SUCCESS ->{
val data = response.body()
if(data == null) {
usecaseLiveData.postValue(Resource.error(Define.MESSAGE_DATA_NULL))
return
}
val reformData = useCase.usecase(data as String) -> 원래는 따로 private 을 선언 해둔것
usecas1 = useCase.reformData0(reformData) -> 원래는 따로 private 을 선언 해둔것
usecas2 = useCase.reformData1(reformData) -> 원래는 따로 private 을 선언 해둔것
//
usecaseLiveData.postValue(Resource.success(UseCaseData(usecas1 , usecas2)))
}
Define.CALL_EXPIRE_TOKEN ->{
usecaseLiveData.postValue(Resource.error(Define.MESSAGE_TOKEN_EXPIRE))
}
else ->usecaseLiveData.postValue(Resource.error(Define.MESSAGE_DATA_NULL))
}
}
override fun onFailure(call: Call<Any>, t: Throwable) {
usecaseLiveData.postValue(Resource.error(Define.MESSAGE_FAIL))
}
})
}
}
상당히 클린 코드에 가까워 지는거 같습니다.
덕분에 repository와 viewModel에 따로 비즈니스 로직을 안적어도 되어서 코드가 상당히 깔끔해지는 현상을 볼수 잇습니다.
그럼 오늘도 읽어주셔서 감사합니다
-피드백와 빞나은 언제나 환영입니다-