Architecture Overview
The domain layer follows Clean Architecture principles with three main components:Domain Models
Pure data classes representing business entities
Repository Interfaces
Contracts defining data access operations
Use Cases
Business logic orchestration
Domain Models
Domain models are pure Kotlin data classes that represent business entities without any framework dependencies.Article
Represents a simplified article for list views:domain/model/Article.kt
The
Article model contains only essential fields needed for displaying article lists, optimizing performance and memory usage.ArticleDetail
Represents a complete article with all details:domain/model/ArticleDetail.kt
Having separate models for list and detail views follows the principle of data tailoring - each screen gets exactly the data it needs.
Resource
A sealed class that wraps data with loading and error states:core/common/Resource.kt
Repository Interfaces
Repository interfaces define contracts for data access without specifying implementation details.ArticleRepository
domain/repository/ArticleRepository.kt
Why use interfaces?
Why use interfaces?
Repository interfaces provide several benefits:
- Abstraction: The domain layer doesn’t need to know about implementation details
- Testability: Easy to create mock implementations for unit tests
- Flexibility: Can swap implementations without changing business logic
- Dependency Inversion: High-level modules don’t depend on low-level modules
Suspend functions
Suspend functions
All repository methods are
suspend functions, which means:- They can be called from coroutines
- They’re non-blocking and asynchronous
- They integrate seamlessly with Kotlin’s coroutine framework
- They enable structured concurrency
Use Cases
Use cases encapsulate specific business logic operations. Each use case has a single responsibility and coordinates between repositories and the presentation layer.GetArticlesUseCase
Retrieves a list of articles with optional search filtering:domain/usecase/GetArticlesUseCase.kt
GetArticleByIdUseCase
Retrieves detailed information for a specific article:domain/usecase/GetArticleByIdUseCase.kt
While these use cases appear simple, they serve as a layer of indirection that can be extended with additional business logic, validation, or data transformation as the app grows.
Benefits of Use Cases
Single Responsibility
Each use case has one clear purpose
Reusability
Can be shared across multiple ViewModels
Testability
Easy to unit test in isolation
Business Logic Centralization
All business rules in one place
Dependency Flow
The domain layer is at the center of the architecture:Notice that dependencies flow inward. The domain layer doesn’t depend on the presentation or data layers, making it the most stable part of the architecture.
Clean Architecture Principles
The domain layer implements several Clean Architecture principles:Independence of Frameworks
Independence of Frameworks
Domain models and use cases don’t depend on Android SDK, Retrofit, Room, or any external frameworks. This makes them:
- Easy to test without Android dependencies
- Portable to other platforms
- Free from framework version constraints
Testability
Testability
Pure business logic with no external dependencies:
Separation of Concerns
Separation of Concerns
Clear boundaries between different types of logic:
- Models: Data structure
- Repositories: Data access contracts
- Use Cases: Business operations
Dependency Inversion
Dependency Inversion
The data layer implements interfaces defined in the domain layer:This means the domain layer controls the contract while remaining independent of implementation details.
Communication Between Layers
Here’s how the domain layer interacts with other layers:Best Practices
Keep It Pure
Domain models should be pure data classes without business logic methods
Single Purpose
Each use case should do one thing well
Framework Free
No Android or external framework dependencies
Immutable Models
Use
val properties to ensure data immutabilityRelated Components
Data Layer
Explore repository implementations
Presentation Layer
See how ViewModels use use cases