One Android Architecture Mistake: Skipping the Mapper Layer
When API DTOs leak directly into UI state, every backend change breaks screens. A small mapper layer prevents this coupling and keeps refactors cheap.
Step 1: Separate transport and UI models
data class LessonDto(val id: String, val title: String?, val level: String)
data class LessonCard(val id: String, val title: String, val badge: String)
Step 2: Centralize transformation rules
fun LessonDto.toCard(): LessonCard = LessonCard(
id = id,
title = title ?: "Untitled lesson",
badge = level.uppercase()
)
Step 3: Test mapper behavior with edge payloads
@Test fun null_title_falls_back() {
val dto = LessonDto("1", null, "beginner")
assertEquals("Untitled lesson", dto.toCard().title)
}
Common pitfall
Applying fallback rules in composables. You will duplicate business logic across screens.
What to check
- UI never imports raw DTO types.
- Mapper rules are unit-tested.
- Backend schema changes affect one mapper file first.