Repository & Data Layer Flashcards
ARCHITECTURE › Patterns
- What are the core responsibilities of a repository class?
- Exposing data to the app, centralizing data changes, resolving conflicts between multiple data sources, abstracting data sources from consumers, and containing business logic. It is the only entry point to the data layer.
- How should the data layer expose one-shot operations versus ongoing data changes?
- One-shot CRUD operations are exposed as suspend functions; to notify consumers of data changes over time, expose a Flow (a cold stream that emits new values as the source of truth updates).
- What is the single source of truth and why is a local database recommended for it?
- The single source of truth is the one place holding consistent, correct, up-to-date data that the repository exposes. A local database (e.g. Room) is recommended because it survives process death and enables offline-first reads independent of the network.
- Why should data exposed from the data layer be immutable?
- Immutable data cannot be tampered with by other classes, avoiding inconsistent state, and it can be safely shared across multiple threads without synchronization.
- Why map network DTOs to separate domain models instead of passing DTOs to the UI?
- It reduces data to only what the app needs (saving memory), adapts external types to app types, and improves separation of concerns so the UI is not coupled to API shape. Recommended whenever a source's data doesn't match what the rest of the app expects.
- What does main-safe mean for repositories and data sources, and who moves work off the main thread?
- Main-safe means a function is safe to call from the main thread. The data source/repository is responsible for moving long-running blocking work to an appropriate dispatcher (e.g. withContext(ioDispatcher)). Room, Retrofit and Ktor suspend APIs are already main-safe.
- Where does conflict resolution between multiple data sources belong, and why not in the ViewModel?
- In the repository. It owns the policy for merging/choosing between network, cache and database so consumers see one consistent result. Putting it in the ViewModel would leak data-layer logic into the UI layer and break reuse and testability.
- What are UI-, app-, and business-oriented operations, and how do they differ in lifecycle?
- UI-oriented are cancelled when the user leaves a screen; app-oriented live while the app/process is alive (e.g. an in-memory cache); business-oriented must survive process death and cannot be cancelled — run those with WorkManager.
- How do you safely cache results in-memory in a repository accessed from coroutines?
- Guard the mutable cached field with a Mutex and read/write it inside withLock, so concurrent coroutines don't corrupt it. For data that must survive process death, persist to Room, DataStore, or a file instead.