Skip to main content
The domain layer represents the core business logic of the application, independent of any framework or UI concerns. It follows clean architecture principles and defines the business rules through models, gateways, and use cases.

Module Overview

Model

Business objects and domain models

Gateway

Repository interfaces and contracts

Use Case

Business logic and application use cases

Model Module

Module: domain:model Package: es.mobiledev.domain.model Defines the core business objects (Business Objects - Bo) used throughout the application.

ArticleBo

File: domain/model/src/main/java/es/mobiledev/domain/model/article/ArticleBo.kt:3 Represents an article in the domain layer.
data class ArticleBo(
    val id: Long,
    val title: String,
    val authors: List<AuthorBo>,
    val url: String,
    val imageUrl: String,
    val newsSite: String,
    val summary: String,
    val publishedAt: String,
    val updatedAt: String,
)
id
Long
required
Unique identifier for the article
title
String
required
Article title
authors
List<AuthorBo>
required
List of article authors with their information
url
String
required
URL to the full article
imageUrl
String
required
URL to the article’s featured image
newsSite
String
required
Source news site name
summary
String
required
Brief summary or excerpt of the article
publishedAt
String
required
ISO 8601 formatted publication timestamp
updatedAt
String
required
ISO 8601 formatted last update timestamp

AuthorBo

File: domain/model/src/main/java/es/mobiledev/domain/model/article/AuthorBo.kt:3 Represents an article author.
data class AuthorBo(
    val name: String,
    val socials: SocialsBo?,
)
name
String
required
Author’s full name
socials
SocialsBo?
Optional social media links for the author

SocialsBo

Represents social media links.
data class SocialsBo(
    val twitter: String?,
    val linkedin: String?,
    val instagram: String?
)

ArticleResponseBo

Wrapper for paginated article responses.
data class ArticleResponseBo(
    val results: List<ArticleBo>,
    val count: Int,
    val next: String?,
    val previous: String?
)
results
List<ArticleBo>
required
List of articles in the current page
count
Int
required
Total number of articles available
next
String?
URL for the next page of results, null if last page
previous
String?
URL for the previous page of results, null if first page
The “Bo” suffix stands for “Business Object” and distinguishes domain models from DTOs (Data Transfer Objects) and DBOs (Database Objects).

Gateway Module

Module: domain:gateway Package: es.mobiledev.domain.gateway Defines interfaces (gateways) that describe how the domain layer interacts with external systems. These interfaces are implemented by the data layer.

ArticleGateway

File: domain/gateway/src/main/java/es/mobiledev/domain/gateway/article/ArticleGateway.kt:7 Interface defining operations for article data access.
interface ArticleGateway {
    suspend fun getArticles(
        limit: Long,
        offset: Long,
    ): Flow<ArticleResponseBo>

    suspend fun getArticleById(
        id: Long
    ): Flow<ArticleBo>

    suspend fun getFavoriteArticles(): Flow<List<ArticleBo>>

    suspend fun saveFavoriteArticle(articleBo: ArticleBo)

    suspend fun removeFavoriteArticle(articleBo: ArticleBo)

    suspend fun isArticleFavorite(id: Long): Flow<Boolean>
}

Methods

getArticles
suspend function
Retrieves a paginated list of articles
limit
Long
required
Maximum number of articles to return
offset
Long
required
Number of articles to skip for pagination
Returns: Flow<ArticleResponseBo> - Flow emitting article response with pagination info
getArticleById
suspend function
Retrieves a single article by its ID
id
Long
required
Unique article identifier
Returns: Flow<ArticleBo> - Flow emitting the requested article
getFavoriteArticles
suspend function
Retrieves all articles marked as favorites by the userReturns: Flow<List<ArticleBo>> - Flow emitting list of favorite articles
saveFavoriteArticle
suspend function
Adds an article to the user’s favorites
articleBo
ArticleBo
required
Article to mark as favorite
removeFavoriteArticle
suspend function
Removes an article from the user’s favorites
articleBo
ArticleBo
required
Article to remove from favorites
isArticleFavorite
suspend function
Checks if an article is in the user’s favorites
id
Long
required
Article identifier to check
Returns: Flow<Boolean> - Flow emitting true if article is favorited

PreferencesGateway

Package: es.mobiledev.domain.gateway.preferences Interface for user preferences and app settings.
interface PreferencesGateway {
    suspend fun saveLastOpenTime(timeInMillis: Long)
    suspend fun getLastOpenTime(): Long
}
Gateways follow the Gateway pattern (similar to Repository pattern) and define the contract between domain and data layers. This enables dependency inversion and makes the domain layer testable.

UseCase Module

Module: domain:useCase Package: es.mobiledev.domain.usecase Encapsulates specific business logic operations. Each use case represents a single business action.

GetArticlesUseCase

File: domain/useCase/src/main/java/es/mobiledev/domain/usecase/article/GetArticlesUseCase.kt:7 Retrieves a paginated list of articles.
interface GetArticlesUseCase {
    suspend operator fun invoke(
        limit: Long,
        offset: Long
    ): Flow<ArticleResponseBo>
}

class GetArticlesUseCaseImpl(
    private val articleGateway: ArticleGateway,
) : GetArticlesUseCase {
    override suspend fun invoke(
        limit: Long,
        offset: Long
    ): Flow<ArticleResponseBo> = 
        articleGateway.getArticles(limit = limit, offset = offset)
}
limit
Long
required
Maximum number of articles to retrieve
offset
Long
required
Pagination offset
Returns: Flow<ArticleResponseBo>

GetArticleByIdUseCase

File: domain/useCase/src/main/java/es/mobiledev/domain/usecase/article/GetArticleByIdUseCase.kt:7 Retrieves a specific article by ID.
interface GetArticleByIdUseCase {
    suspend operator fun invoke(
        id: Long,
    ): Flow<ArticleBo>
}

class GetArticleByIdUseCaseImpl(
    private val articleGateway: ArticleGateway,
) : GetArticleByIdUseCase {
    override suspend fun invoke(
        id: Long,
    ): Flow<ArticleBo> = articleGateway.getArticleById(id = id)
}
id
Long
required
Unique identifier of the article
Returns: Flow<ArticleBo>

GetFavoriteArticlesUseCase

Retrieves all favorite articles.
interface GetFavoriteArticlesUseCase {
    suspend operator fun invoke(): Flow<List<ArticleBo>>
}
Returns: Flow<List<ArticleBo>>

SaveOrRemoveFavoriteArticleUseCase

Toggles an article’s favorite status.
interface SaveOrRemoveFavoriteArticleUseCase {
    suspend operator fun invoke(
        article: ArticleBo,
        isFavorite: Boolean
    )
}
article
ArticleBo
required
The article to toggle
isFavorite
Boolean
required
Current favorite status (will be toggled)

IsArticleFavoriteUseCase

Checks if an article is favorited.
interface IsArticleFavoriteUseCase {
    suspend operator fun invoke(id: Long): Flow<Boolean>
}
id
Long
required
Article identifier to check
Returns: Flow<Boolean>

Preferences Use Cases

interface GetLastOpenTimeUseCase {
    suspend operator fun invoke(): Long
}

Use Case Pattern

interface GetArticlesUseCase {
    suspend operator fun invoke(
        limit: Long,
        offset: Long
    ): Flow<ArticleResponseBo>
}
Use cases implement the operator fun invoke() pattern, allowing them to be called like functions. This provides a clean API: useCase(params) instead of useCase.execute(params).

Dependency Injection

Use cases are provided via Hilt modules:
@Module
@InstallIn(ViewModelComponent::class)
object UseCaseModule {
    @Provides
    fun provideGetArticlesUseCase(
        articleGateway: ArticleGateway
    ): GetArticlesUseCase = GetArticlesUseCaseImpl(articleGateway)
}

Build docs developers (and LLMs) love