This episode connects all the material with real-world cases: examples of Android apps, backend services, and multiplatform libraries, clean, hexagonal, and reactive architecture, data flow and state management, and scalability and maintainability patterns for systems that last.

All the material from episodes 0 through 19 now comes together. Episode 20 looks at how those concepts are assembled into real systems: Android apps, backend services, and multiplatform libraries, with clean, hexagonal, and reactive architecture.
Architecture isn't specific code; it's decisions about where code lives and how it communicates. Good architecture lets a system be extended, tested, and maintained for years — the same reason this episode is a bridge toward the closing episode.
After this episode, you'll design clear project structures for different kinds of applications.
Modern Android apps organize code into layers: UI (Compose), state holder (ViewModel), and data (Repository). Data flows in one direction, from the UI to the ViewModel to the Repository and back:
class ProdukViewModel(
private val repo: ProdukRepository,
) : ViewModel() {
private val _state = MutableStateFlow<UiState>(UiState.Loading)
val state: StateFlow<UiState> = _state.asStateFlow()
fun muat() {
viewModelScope.launch {
_state.value = UiState.Content(repo.ambilProduk())
}
}
}The ViewModel holds state as a StateFlow and communicates with the Repository. This one-way flow is easy to test: repo can be mocked (episode 13) and the state can be verified without a UI.
A backend service uses the same pattern: a controller or route handles requests, a service holds business logic, and a repository accesses the database. Dependency injection (episode 11) connects these layers without tightly coupled code.
A multiplatform library (episode 12) uses a shared module structure with a small public API and internal implementations. This pattern keeps a stable contract across all platforms while hiding platform-dependent details.
Clean Architecture centers business logic in a core and makes dependencies point inward: use cases in the middle, frameworks at the edges. In Kotlin, this means a framework-free domain implemented with interfaces:
interface OrderGateway {
suspend fun simpan(order: Order)
}
class OrderService(
private val gateway: OrderGateway,
) {
suspend fun buat(order: Order) {
gateway.simpan(order)
}
}OrderService depends on the OrderGateway interface, not a concrete implementation. Implementations (adapters) are injected from outside. The result: business logic can be tested without a database, and frameworks can be swapped without touching the core. You can verify this pattern with ./gradlew test.
Hexagonal architecture is a sibling of clean architecture: the business core in the middle, ports (interfaces) at the edges, and adapters for each external technology — database, HTTP, message broker. This pattern enforces clear boundaries and makes external technologies easy to replace.
Reactive applications propagate data changes automatically. In Kotlin, this means Flow and StateFlow (episode 9): a data source emits values, and the UI or other systems respond:
val jumlahBaru: Flow<Int> = repo
.pantauPerubahan()
.map { it.size }map { it.size } transforms the data stream without changing its source. Reactive state management keeps the UI always in sync with the data, eliminating the whole class of manual synchronization bugs.
Reactive architecture adds conceptual complexity. For small applications with linear flows, direct processing is simpler. Start simple and add reactivity only when it's genuinely needed.
Patterns that keep a system healthy as it grows:
The best architecture is one that's sufficient for today's needs and adaptable for tomorrow. Overdoing it adds cost; underdoing it adds debt. Evaluate the architecture regularly and refactor when boundaries start to strain — not earlier, not later.
Episode 20 connected all the material with the real world: layering in Android and backend applications, clean and hexagonal architecture with ports and adapters, reactive data flow with Flow and StateFlow, and the scalability and maintainability patterns that make systems last.
The key takeaways:
In episode 21 we'll discuss ecosystem and tools — complete tooling like IntelliJ IDEA, the Kotlin plugin, Gradle, and Android Studio, community resources and learning paths, community channels like Slack and forums, and related frameworks and libraries that extend your abilities.