Skip to main content
The Space Flight News Android app follows Clean Architecture principles combined with MVVM (Model-View-ViewModel) pattern to create a scalable, maintainable, and testable codebase.

Architecture Principles

The app is structured around three core architectural principles:
  1. Separation of Concerns: Each layer has a distinct responsibility
  2. Dependency Inversion: Dependencies point inward toward the domain layer
  3. Testability: Business logic is independent of Android framework

Layer Structure

The application is organized into three main layers:

Presentation

UI components, ViewModels, and user interaction logic

Domain

Business logic, use cases, and domain models

Data

Data sources, repositories, and API clients

Package Structure

The codebase is organized into the following packages:
com.bsvillarraga.spaceflightnews/
├── core/                    # Shared utilities and common classes
│   ├── common/             # Resource wrapper, base classes
│   ├── extensions/         # Kotlin extension functions
│   └── network/            # Network helpers
├── data/                    # Data layer
│   ├── local/              # Room database, DAOs, entities
│   ├── model/              # DTOs (Data Transfer Objects)
│   ├── remote/             # API clients, API helpers
│   ├── repository/         # Repository implementations
│   └── utils/              # Data layer utilities
├── di/                      # Dependency injection modules
│   ├── NetworkModule.kt    # Network dependencies
│   └── RoomModule.kt       # Database dependencies
├── domain/                  # Domain layer
│   ├── model/              # Domain models
│   ├── repository/         # Repository interfaces
│   └── usecase/            # Use cases (business logic)
└── presentation/            # Presentation layer
    ├── permission/         # Permission handling
    └── ui/                 # Fragments, ViewModels, adapters

Data Flow

The typical data flow through the architecture follows this pattern:
1

User Interaction

User interacts with the UI (Fragment/Activity)
2

ViewModel Processing

ViewModel receives the event and calls the appropriate Use Case
3

Business Logic

Use Case executes business logic and calls the Repository
4

Data Retrieval

Repository fetches data from remote API or local database
5

Data Transformation

Data is transformed from DTOs to Domain models
6

UI Update

ViewModel updates LiveData/StateFlow, triggering UI updates

Core Components

Resource Wrapper

The app uses a sealed class to represent operation states:
com/bsvillarraga/spaceflightnews/core/common/Resource.kt
sealed class Resource<out T> {
    data class Success<out T>(val data: T?) : Resource<T>()
    data class Error<out T>(val code: String?, val msg: String, val error: Throwable? = null) : Resource<T>()
    data class Loading<out T>(val data: T? = null) : Resource<T>()
}
The Resource class provides a type-safe way to handle loading, success, and error states throughout the application.

Dependency Injection

The app uses Dagger Hilt for dependency injection, configured at the application level:
com/bsvillarraga/spaceflightnews/MyApp.kt:4-7
@HiltAndroidApp
class MyApp: Application()

Key Features

  • Clear separation between layers
  • Business logic independent of frameworks
  • Easy to test and maintain
  • Kotlin Coroutines for asynchronous operations
  • LiveData and StateFlow for reactive UI updates
  • Flow-based search with debouncing
  • Dagger Hilt for compile-time dependency injection
  • Singleton components for shared resources
  • Constructor injection for testability
  • Kotlin’s type system for compile-time safety
  • Domain models separate from DTOs
  • Sealed classes for state management

Next Steps

Clean Architecture

Deep dive into the three-layer architecture

Dependency Injection

Learn how Dagger Hilt is configured

Build docs developers (and LLMs) love