Use cases and the domain layer

Architecture and dependency injection Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Pick the fix

Two ViewModels each combine the cart, the user's tier and promotions to compute a total, and they disagree. What's the best fix?

Options
Hint 1 of 1

Where should logic shared by screens live?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Move the calculation into a CalculateCartTotalUseCase both ViewModels use

Correct. Shared business logic in one place stops the drift.

Why not the others?
  • B Copy the more correct version into both. Still duplicated.
  • C Put the logic in the composable. Logic in UI is harder to test and still duplicated.
  • D Put it in a base ViewModel. Inheritance for shared logic couples unrelated screens.

30-second answer

A use case (interactor) is a small class with one job, such as GetFeedWithAuthorsUseCase, often with operator fun invoke. It holds business logic that combines repositories or would otherwise be copied between ViewModels. It's worth adding when logic is reused or complex; wrapping every single repository call in a use case only adds files.

Practise saying it · 30 s. No recording, just a timer

Explain use cases.

Say your answer out loud, then check which of these points you covered:

  • One job, invoke operator
  • For reused or complex logic
  • No Android types
  • Don't wrap every call

Deep dive

Use cases should be free of Android types, so they run in plain JVM tests.

They usually depend on repositories and other use cases, never on ViewModels.

Keep them stateless; state belongs in the repository or ViewModel.

Name them by what they do, in the verb-noun form.

A use case Compile-checked · Kotlin 2.4.21
class GetGreetingUseCase(private val users: UserRepository) {
    suspend operator fun invoke(id: String): String {
        val user = users.user(id)
        return "Hello, ${user.name}"
    }
}

Common mistakes

  • A use case per repository method with no logic.
  • Use cases holding mutable state.
  • Using Android Context inside a use case.

Senior take & follow-ups

Show judgement: when you would and wouldn't add one.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you call a use case?

    Show hint

    With operator fun invoke, like getFeed().

  2. Can use cases depend on each other?

    Show hint

    Yes, as long as there are no cycles.

Suggest a fix if something here is wrong or out of date.