← Назад к вопросам

Как устроен Data слой в Clean Architecture?

2.7 Senior🔥 191 комментариев
#Архитектура и паттерны#Многомодульность#Работа с данными

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Структура Data слоя в Clean Architecture

В Clean Architecture (также известной как Onion Architecture) Data слой является центральным слоем, который отвечает за управление данными приложения. Он служит "мостом" между бизнес-логикой (Domain слой) и внешними источниками данных (Presentation слой и внешние сервисы). Data слой реализует интерфейсы, определенные в Domain слое, и предоставляет конкретные реализации репозиториев, источников данных и мапперов.

Ключевые компоненты Data слоя

1. Реализации репозиториев (Repository Implementations)

Это классы, которые реализуют интерфейсы репозиториев, определенные в Domain слое. Они инкапсулируют логику работы с данными, скрывая детали источников данных.

class UserRepositoryImpl @Inject constructor(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource,
    private val userMapper: UserMapper
) : UserRepository {
    
    override suspend fun getUserById(id: String): User {
        // Сначала проверяем локальное хранилище
        val localUser = localDataSource.getUserById(id)
        if (localUser != null) {
            return userMapper.mapToDomain(localUser)
        }
        
        // Если нет локально, запрашиваем с сервера
        val remoteUser = remoteDataSource.getUserById(id)
        val domainUser = userMapper.mapToDomain(remoteUser)
        
        // Сохраняем локально для будущих запросов
        localDataSource.saveUser(remoteUser)
        
        return domainUser
    }
}

2. Источники данных (Data Sources)

  • Local Data Sources: Работа с локальным хранилищем (Room, SQLite, DataStore, SharedPreferences)
  • Remote Data Sources: Работа с сетевыми API (Retrofit, gRPC)
  • Memory Data Sources: Кэширование в оперативной памяти
interface UserLocalDataSource {
    suspend fun getUserById(id: String): UserEntity?
    suspend fun saveUser(user: UserEntity)
    suspend fun deleteUser(id: String)
}

class UserLocalDataSourceImpl @Inject constructor(
    private val userDao: UserDao
) : UserLocalDataSource {
    
    override suspend fun getUserById(id: String): UserEntity? {
        return userDao.getUserById(id)
    }
}

3. Модели данных (Data Models)

Это объекты, которые отражают структуру данных в конкретных источниках. Они отличаются от Domain моделей, так как содержат специфичные для источника детали.

@Entity(tableName = "users")
data class UserEntity(
    @PrimaryKey
    val id: String,
    @ColumnInfo(name = "full_name")
    val name: String,
    val email: String,
    @ColumnInfo(name = "created_at")
    val createdAt: Long
)

data class UserRemote(
    @SerializedName("id")
    val id: String,
    @SerializedName("name")
    val name: String,
    @SerializedName("email_address")
    val email: String,
    @SerializedName("registration_date")
    val registrationDate: String
)

4. Мапперы (Mappers)

Преобразуют модели данных между слоями: Data ↔ Domain.

class UserMapper @Inject constructor() {
    
    fun mapToDomain(entity: UserEntity): User {
        return User(
            id = entity.id,
            name = entity.name,
            email = entity.email
        )
    }
    
    fun mapToEntity(domain: User): UserEntity {
        return UserEntity(
            id = domain.id,
            name = domain.name,
            email = domain.email,
            createdAt = System.currentTimeMillis()
        )
    }
}

Принципы организации Data слоя

Принцип инверсии зависимостей (Dependency Inversion)

Data слой ЗАВИСИТ от Domain слоя (реализует его интерфейсы), а не наоборот. Это обеспечивает гибкость и тестируемость.

// Domain слой определяет контракт
interface UserRepository {
    suspend fun getUserById(id: String): User
}

// Data слой реализует контракт
class UserRepositoryImpl : UserRepository {
    // Реализация
}

Разделение ответственности (Separation of Concerns)

Каждый компонент отвечает за одну конкретную задачу:

  • Репозитории: Оркестрируют работу с источниками данных
  • Data Sources: Непосредственная работа с конкретными хранилищами
  • Мапперы: Преобразование данных

Стратегия кэширования (Caching Strategy)

Data слой часто реализует стратегии кэширования, например:

  • Cache-first: Сначала проверять кэш, потом сеть
  • Network-first: Сначала сеть, потом обновление кэша
  • Hybrid approach: Интеллектуальное комбинирование подходов

Поток данных в Data слое

  1. Получение запроса от Domain слоя через интерфейс репозитория
  2. Определение источника данных (локальный/удаленный/память)
  3. Извлечение данных из выбранного источника
  4. Преобразование данных в Domain модели
  5. Возврат результата в Domain слой
  6. Обновление кэша при необходимости (фоново или синхронно)

Преимущества такого подхода

  • Тестируемость: Легко мокать репозитории и источники данных
  • Гибкость: Замена источников данных без изменения бизнес-логики
  • Масштабируемость: Добавление новых источников без переписывания кода
  • Поддержка многопоточности: Четкое разделение синхронных/асинхронных операций
  • Безопасность: Централизованное управление конфиденциальными данными

Data слой в Clean Architecture служит фундаментом для надежной работы с данными, обеспечивая изоляцию бизнес-логики от деталей реализации хранения и получения данных, что соответствует принципу инкапсуляции и способствует созданию поддерживаемого и гибкого кода.

Как устроен Data слой в Clean Architecture? | PrepBro