На чем построено сетевое взаимодействие на текущем проекте?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Архитектура сетевого взаимодействия на текущем проекте
На текущем проекте сетевое взаимодействие построено на многоуровневой архитектуре, сочетающей нативные инструменты Apple и современные архитектурные паттерны. Это обеспечивает высокую производительность, безопасность и удобство сопровождения. Основой служит фреймворк URLSession, но с абстракциями, соответствующим принципам SOLID и Clean Architecture.
Основные компоненты
1. Модуль сетевого слоя (Network Layer)
На нижнем уровне используется кастомная обертка над URLSession, реализующая протоколо-ориентированный подход. Это позволяет легко подменять реализации для тестирования и поддержки различных типов запросов.
protocol NetworkServiceProtocol {
func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T
}
final class NetworkService: NetworkServiceProtocol {
private let session: URLSession
private let decoder: JSONDecoder
init(session: URLSession = .shared) {
self.session = session
self.decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
}
func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T {
let request = try endpoint.urlRequest()
let (data, response) = try await session.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw NetworkError.invalidResponse
}
return try decoder.decode(T.self, from: data)
}
}
2. Модель Endpoint
Каждый API-запрос инкапсулирован в структуру, соответствующую протоколу Endpoint. Это обеспечивает централизованное управление заголовками, параметрами, методом и путем.
protocol Endpoint {
var baseURL: URL { get }
var path: String { get }
var method: HTTPMethod { get }
var headers: [String: String]? { get }
var parameters: [String: Any]? { get }
}
extension Endpoint {
func urlRequest() throws -> URLRequest {
let url = baseURL.appendingPathComponent(path)
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
request.allHTTPHeaderFields = headers
// Добавление токена авторизации из Keychain
if let token = AuthService.shared.accessToken {
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
if let parameters = parameters {
switch method {
case .get:
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
components?.queryItems = parameters.map {
URLQueryItem(name: $0.key, value: "\($0.value)")
}
request.url = components?.url
default:
request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
}
}
return request
}
}
3. Интеграция с DTO / Codable
Все сетевые модели реализованы через DTO (Data Transfer Object) с использованием Codable для автоматической сериализации/десериализации. Это минимизирует бойлерплейт и ошибки парсинга.
struct UserDTO: Codable {
let id: Int
let username: String
let email: String
let createdAt: Date
enum CodingKeys: String, CodingKey {
case id, username, email
case createdAt = "created_at"
}
}
Ключевые особенности реализации:
- Асинхронность: Активное использование Swift Concurrency (
async/await) вместо callback'ов, что делает код линейным и читаемым - Обработка ошибок: Единая иерархия ошибок с категориями для сетевых сбоев, ошибок парсинга и бизнес-логики
- Кэширование: Двухуровневое кэширование: в памяти через
NSCacheдля частых запросов и на диске черезCoreDataдля данных, требующих персистентности - Безопасность:
- Использование SSL Pinning для критичных эндпоинтов
- Хранение токенов в Keychain Services
- Динамическая подгрузка конфигураций сервера через Remote Config
- Мониторинг: Интеграция с MetricKit и кастомной системой логирования для отслеживания производительности сетевых запросов
- Модульные тесты: Полное покрытие сетевого слоя юнит-тестами с моками через Protocol Mocks
- Поддержка фоновых загрузок:
URLSessionсконфигурирован для поддержки загрузок в фоновом режиме для медиафайлов
Преимущества текущего подхода:
- Гибкость: Легко добавлять новые эндпоинты без изменения существующего кода
- Тестируемость: Все компоненты изолированы и могут быть протестированы отдельно
- Масштабируемость: Архитектура позволяет легко добавлять новые функции (пагинация, retry-логика, офлайн-режим)
- Производительность: Оптимизированное использование пула соединений и кэширование
- Безопасность: Современные практики защиты данных и аутентификации
Данная архитектура доказала свою эффективность в проекте с более чем 100 различными API