Should we want to pass Usecase interface as param

117 views Asked by At

In clean architecture, the main core is usecase layer which contains business logics. Now in Android we will use case and pass it to viewmodel as param in constructor. For example

class AddNoteUseCase(noteRepository:INoteRepository):IUseCase{
  override fun invoke(note:Note){
      noteRepository.addNote(note)
}
}

I saw two type of code to pass usecase for viewmodel

  1. Usecase is tightly coupled to viewmodel
class NoteViewModel(addNoteUseCase:AddNoteUseCase){
  // usecase code
}
  1. Usecase is loosely coupled to viewmodel
class NoteViewModel(addNoteUseCase:IUseCase){
  // usecase code
}

If we go with first approach then we cant fake and also it would be difficult for future changes. If we go with second approach then we able to fake for unit testing

My question is which approach will be helpful. Because some says one approach because there is no need of faking the usecase as it only contains one method some says without faking how will you test the usecase

1

There are 1 answers

2
Sergei Mikhailovskii On

I would say that the second variant is right. From my experience, if u have a base usecase class/interface, ususally it looks like this:

interface UseCase<I, O> {
    suspend operator fun invoke(param: I): O
}

And let's suppose u have a subclass AddNoteUseCase:

class AddNoteUseCase : UseCase<Note, Unit> {
    override suspend operator fun invoke(param: Note) {}
}

If u pass this usecase as a param to VM in this way:

class ViewModel(
    val addNoteUseCase: UseCase<Note, Unit>
) {
}

it still makes your code readable(since u understand by the name, what this usecase does) and testable (since u can pass any implementation u want in unit tests). Imho, there's no need to create a separate abstraction for each usecase, since all of them have the same interface - one public method invoke and that's all