Какие знаешь сущности в Data слое Clean Architecture?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Основные сущности Data слоя в Clean Architecture
В Clean Architecture слой Data выступает в роли моста между бизнес-логикой (Domain слоем) и внешними источниками данных. Его главная цель — предоставить Domain слою прозрачный доступ к данным, скрывая сложность их получения, кэширования и преобразования. Вот ключевые сущности этого слоя:
1. Repository (Репозиторий)
Центральная сущность, реализующая интерфейсы из Domain слоя. Репозиторий определяет единую точку доступа к данным, абстрагируя источник их получения.
interface UserRepository {
suspend fun getUser(id: String): Result<User>
suspend fun saveUser(user: User): Result<Unit>
}
class UserRepositoryImpl(
private val localDataSource: UserLocalDataSource,
private val remoteDataSource: UserRemoteDataSource
) : UserRepository {
override suspend fun getUser(id: String): Result<User> {
// Проверяем кэш, затем сеть
val localUser = localDataSource.getUser(id)
return if (localUser != null) {
Result.success(localUser)
} else {
when (val remoteResult = remoteDataSource.getUser(id)) {
is Result.Success -> {
localDataSource.saveUser(remoteResult.data)
remoteResult
}
is Result.Error -> remoteResult
}
}
}
}
2. Data Sources (Источники данных)
Конкретные реализации для работы с различными источниками:
- LocalDataSource — работа с локальным хранилищем:
interface UserLocalDataSource {
suspend fun getUser(id: String): User?
suspend fun saveUser(user: User)
}
class UserRoomDataSource(
private val userDao: UserDao
) : UserLocalDataSource {
override suspend fun getUser(id: String): User? {
return userDao.getById(id)?.toDomain()
}
}
- RemoteDataSource — работа с сетевыми API:
interface UserRemoteDataSource {
suspend fun getUser(id: String): Result<User>
}
class UserRetrofitDataSource(
private val apiService: UserApiService
) : UserRemoteDataSource {
override suspend fun getUser(id: String): Result<User> {
return try {
val response = apiService.getUser(id)
Result.success(response.toDomain())
} catch (e: Exception) {
Result.error(e)
}
}
}
3. Mappers (Преобразователи)
Классы для преобразования данных между слоями:
class UserMapper {
fun toDomain(userEntity: UserEntity): User {
return User(
id = userEntity.id,
name = userEntity.fullName,
email = userEntity.emailAddress
)
}
fun toEntity(user: User): UserEntity {
return UserEntity(
id = user.id,
fullName = user.name,
emailAddress = user.email
)
}
}
4. Data Models (Модели данных)
Специфичные для Data слоя модели, которые могут отличаться от Domain моделей:
@Entity(tableName = "users")
data class UserEntity(
@PrimaryKey val id: String,
val fullName: String,
val emailAddress: String,
val lastUpdated: Long
)
data class UserApiResponse(
@SerializedName("user_id") val userId: String,
@SerializedName("name") val name: String,
@SerializedName("email") val email: String
)
5. Data Transfer Objects (DTO)
Объекты для передачи данных между слоями или компонентами:
data class UserRequestDto(
val userId: String,
val authToken: String
)
data class UserResponseDto(
val user: UserApiResponse,
val metadata: Map<String, Any>
)
6. Database и API клиенты
Конкретные реализации для работы с технологиями:
- Room DAO интерфейсы
- Retrofit интерфейсы
- WorkManager для фоновых задач
- SharedPreferences/DataStore для хранения настроек
Принципы организации Data слоя:
- Инверсия зависимостей — Domain слой определяет интерфейсы, Data слой их реализует
- Единая ответственность — каждый класс отвечает за одну конкретную задачу
- Тестируемость — все зависимости внедряются через конструктор
- Гибкость — легко заменять реализации источников данных
- Кэширование стратегий — интеллектуальное управление данными (сначала кэш, потом сеть)
Практический пример структуры пакетов:
data/
├── repository/
│ └── UserRepositoryImpl.kt
├── source/
│ ├── local/
│ │ ├── UserLocalDataSource.kt
│ │ └── dao/
│ └── remote/
│ ├── UserRemoteDataSource.kt
│ └── api/
├── model/
│ ├── UserEntity.kt
│ └── UserApiResponse.kt
└── mapper/
└── UserMapper.kt
Data слой обеспечивает изоляцию изменений — при замене библиотеки (например, с Retrofit на Ktor) или базы данных (с Room на Realm) изменения остаются внутри этого слоя, не затрагивая Domain и Presentation слои. Это делает приложение устойчивым к эволюции технологического стека и упрощает поддержку кода.