Где описаны запросы клиент-сервер в твоем проекте?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Организация сетевых запросов в проекте
В моих проектах описание и реализация клиент-серверных запросов распределены по нескольким слоям архитектуры, что соответствует принципам чистой архитектуры и MVVM. Вот основные места, где можно найти информацию о запросах:
1. Retrofit-интерфейсы в data-слое
В пакете data/network/api/ находятся интерфейсы с аннотациями Retrofit, которые явно описывают эндпоинты, методы HTTP, параметры и форматы данных.
interface UserApiService {
@GET("users/{id}")
suspend fun getUserById(@Path("id") userId: Long): Response<UserDto>
@POST("users")
@Headers("Content-Type: application/json")
suspend fun createUser(@Body user: UserDto): Response<CreateUserResponse>
@Multipart
@PUT("users/avatar")
suspend fun uploadAvatar(
@Part avatar: MultipartBody.Part,
@Query("compress") compress: Boolean = true
): Response<AvatarResponse>
}
2. Repository-классы с бизнес-логикой
В data/repositories/ находятся репозитории, которые используют API-сервисы, добавляя кеширование, обработку ошибок и трансформацию DTO в доменные модели.
class UserRepositoryImpl @Inject constructor(
private val userApi: UserApiService,
private val userCache: UserCache
) : UserRepository {
override suspend fun getUser(userId: Long): Result<User> {
return try {
val response = userApi.getUserById(userId)
if (response.isSuccessful) {
val userDto = response.body()!!
val user = UserMapper.toDomain(userDto)
userCache.saveUser(user)
Result.success(user)
} else {
Result.failure(NetworkException(response.code(), response.message()))
}
} catch (e: Exception) {
Result.failure(NetworkException.cause(e))
}
}
}
3. DTO-модели в data-слое
В data/model/dto/ расположены классы данных, которые точно соответствуют структуре JSON-ответов от сервера.
data class UserDto(
@SerializedName("id")
val id: Long,
@SerializedName("full_name")
val fullName: String,
@SerializedName("email")
val email: String,
@SerializedName("profile_image_url")
val profileImageUrl: String?,
@SerializedName("created_at")
val createdAt: String
)
4. UseCase-классы в domain-слое
В domain/usecases/ содержатся сценарии использования, которые определяют, какие запросы и в какой последовательности должны выполняться для конкретной бизнес-операции.
class GetUserProfileUseCase @Inject constructor(
private val userRepository: UserRepository,
private val postsRepository: PostsRepository
) {
suspend operator fun invoke(userId: Long): UserProfileData {
val user = userRepository.getUser(userId)
val posts = postsRepository.getUserPosts(userId)
return UserProfileData(user, posts)
}
}
5. Конфигурация сетевого слоя
В di/network/ модуле Dependency Injection настраиваются все компоненты для работы с сетью:
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(LoggingInterceptor())
.addInterceptor(AuthInterceptor())
.connectTimeout(30, TimeUnit.SECONDS)
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideUserApi(retrofit: Retrofit): UserApiService {
return retrofit.create(UserApiService::class.java)
}
}
6. Документация API
Дополнительно в проекте поддерживается:
- Postman-коллекция в папке
docs/api/с примерами всех запросов - Swagger/OpenAPI спецификация в виде YAML-файла для автогенерации документации
- Wiki-страницы в репозитории с описанием бизнес-логики каждого эндпоинта
Преимущества такого подхода:
- Разделение ответственности: каждый слой отвечает за свою часть работы с сетью
- Тестируемость: легко мокировать API-сервисы и репозитории
- Гибкость: замена сетевой библиотеки затрагивает только data-слой
- Единый источник истины: DTO-модели гарантируют соответствие структуре API
- Автодокументация: Retrofit-аннотации служат документацией прямо в коде
Такой структурированный подход позволяет быстро находить информацию о любом сетевом запросе, понимать его назначение и вносить изменения с минимальным риском поломки существующей функциональности.