UI, domain and data layers

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

Pick the fix

A ViewModel calls Retrofit, maps JSON, caches in a HashMap and formats prices. What's the best first refactor?

Options
Hint 1 of 1

Which parts are about where data comes from?

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

Show answer

Answer: A Move fetching, mapping and caching into a repository; keep formatting for the UI

Correct. The data layer owns sources and caching; the ViewModel just exposes UI state.

Why not the others?
  • B Move everything into a single use case. That just moves the god class.
  • C Make the ViewModel a singleton. Lifetime isn't the problem; responsibilities are.
  • D Split the ViewModel into four ViewModels. The screen still mixes data and UI concerns.

30-second answer

The UI layer shows state and sends events: composables or Views plus state holders such as ViewModels. The data layer owns data through repositories, each exposing data for one area and hiding the sources (network, database, files) behind it. An optional domain layer of use cases sits in between for business logic that several ViewModels share. Dependencies point inward: UI depends on data, never the reverse.

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

Explain the recommended app layers.

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

  • UI layer shows state, sends events
  • Data layer with repositories
  • Optional domain layer
  • Dependencies point inward
  • Repositories are the source of truth

Deep dive

Repositories are the single source of truth for their data, usually backed by a local database.

The domain layer is optional; add it when logic is reused or ViewModels grow too big.

Each layer exposes Kotlin types and Flows, not Android framework types, which keeps them testable.

Data flows up as streams of state; events flow down as function calls.

Common mistakes

  • Calling Retrofit directly from a ViewModel.
  • Adding a use case for every single repository call.
  • Letting DTOs from the API reach composables.

Senior take & follow-ups

Explain responsibilities, then say what's optional. Rigid layer worship is a red flag.

Follow-up questions

Think of your answer first, then open the hint.

  1. When is a domain layer worth it?

    Show hint

    When business logic is reused across screens or makes ViewModels hard to read.

  2. What is the single source of truth here?

    Show hint

    Usually the local database the repository exposes.

Similar on iOS: MVC, MVVM, VIPER and TCA compared The iOS page covers MVC, MVVM and coordinators; Android's guide adds an explicit data layer.

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