Как устроен Data слой в Clean Architecture?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Структура 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 слое
- Получение запроса от Domain слоя через интерфейс репозитория
- Определение источника данных (локальный/удаленный/память)
- Извлечение данных из выбранного источника
- Преобразование данных в Domain модели
- Возврат результата в Domain слой
- Обновление кэша при необходимости (фоново или синхронно)
Преимущества такого подхода
- Тестируемость: Легко мокать репозитории и источники данных
- Гибкость: Замена источников данных без изменения бизнес-логики
- Масштабируемость: Добавление новых источников без переписывания кода
- Поддержка многопоточности: Четкое разделение синхронных/асинхронных операций
- Безопасность: Централизованное управление конфиденциальными данными
Data слой в Clean Architecture служит фундаментом для надежной работы с данными, обеспечивая изоляцию бизнес-логики от деталей реализации хранения и получения данных, что соответствует принципу инкапсуляции и способствует созданию поддерживаемого и гибкого кода.