Connect with us

Разработка

Расцвет «достаточно хорошей» архитектуры в Android

Идеальная архитектура — это миф. Достаточно хорошая архитектура — это дисциплина, знающая, что нужно делать, что отложить, а что вообще не стоит использовать.

Опубликовано

/

     
     

Вот куда все движется: интерфейс на 200 строк. «Защищенная» (future-proof) абстракция, которую никто не просил. Но, может быть, секрет выпуска хороших Android-приложений не в большем количестве слоев, а в том, чтобы остановиться после этих слоев?

Наступает эпоха «достаточно хорошей архитектуры», где прагматизм ставится выше перфекционизма, и где вашим пользователям наплевать на ваш граф зависимостей.

 Ловушка чистой архитектуры

В разработке Android-приложений годами мы поклонялись алтарю чистой архитектуры дяди Боба: репозитории, юз кейсы, мапперы и больше папок, чем в Библиотеке Конгресса.

Проблема? Большинству приложений это не нужно.

Вы создаете не банковское программное обеспечение, а фитнес-трекер. Эта пятислойная абстракция для получения профилей пользователей? Она заставляет вас терять скорость, прозрачность, а также рассудок.

Что на самом деле означает «достаточно хорошо»

Позвольте мне прояснить: «достаточно хорошая» архитектура не означает «ковбойский код». Это намеренный прагматизм.

Вот изменение мышления:

  • Начните с простого. Используйте ViewModel, используйте репозитории, небольшая разграниченность имеет большое значение. Добавляйте сложность только тогда, когда возникают проблемы.
  • Примите Jetpack. Он проверен в бою, и Google считает, что библиотеки (Room, Hilt, Navigation) будут «достаточно хороши» для 90% приложений.
  • Тестируйте там, где это важно. Модульные тесты для бизнес-логики? Да. Тестирование скрытого граничного случая путем написания интеграционного теста? Возможно, позже.
  • Рефакторинг по мере необходимости, а не превентивно. Ваш друг — YAGNI (You Aren’t Gonna Need It — Вам это не понадобится).

Пример из реальной жизни: экран входа в систему

«Идеальный» способ (избыточный):

// LoginUseCase, LoginRepository, LoginMapper, LoginLocalDataSource,
// LoginRemoteDataSource, LoginEntity, LoginDTO, LoginDomainModel...

class LoginViewModel(
    private val loginUseCase: LoginUseCase,
    private val mapperFactory: MapperFactory
) : ViewModel() {
    // 47 lines of abstraction for a POST request
}

«Достаточно хороший» способ:

class LoginViewModel(
    private val authRepository: AuthRepository
) : ViewModel() {
    fun login(email: String, password: String) {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            authRepository.login(email, password)
                .onSuccess { user -> 
                    _uiState.value = UiState.Success(user) 
                }
                .onFailure { error -> 
                    _uiState.value = UiState.Error(error.message) 
                }
        }
    }
}

1 день против 1 часа. Быстрее. По-прежнему тестируемо. По-прежнему поддерживается.

Когда повышать уровень

«Достаточно хорошо» не означает статичность. Добавляйте масштабируемость вашей архитектуры по мере масштабирования вашего приложения:

  • 10 000 пользователей? Нет проблем с базовой архитектурой MVVM + Репозиторий.
  • 100 000 пользователей? Добавьте модульность, улучшите стратегии кэширования.
  • 1 миллион+ пользователей? Добавьте многомодульную архитектуру, флаги функций и наблюдаемость.

Как показало исследование JetBrains за 2024 год, 68% команд Android-разработчиков по-прежнему проводят рефакторинг архитектуры после достижения соответствия продукта рынку, а не до этого.

Преимущества Compose

Jetpack Compose ускоряет процесс мышления «Достаточно хорошо». Декларативный подход Compose значительно уменьшает количество шаблонного кода, а встроенная обработка состояний (например, remember, derivedStateOf, collectAsStateWithLifecycle) решает наиболее распространенные архитектурные проблемы.

Пример:

@Composable
fun UserProfileScreen(viewModel: ProfileViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    
    when (uiState) {
        is UiState.Loading -> LoadingIndicator()
        is UiState.Success -> ProfileContent(uiState.data)
        is UiState.Error -> ErrorMessage(uiState.message)
    }
}

Чистота. Прямота. Без церемоний.

Почему это важно сейчас

Еще несколько факторов, ускоряющих развитие экосистемы Android: компилятор K2, выход Kotlin 2.1, Compose Multiplatform, KMP для общей логики. Избыточное проектирование архитектуры отнимает время на эксперименты с этими революционными новшествами.

Речь не идет о создании идеального кода по учебнику — речь идет о выпуске функций, которые важны для пользователей, быстрой итерации и сохранении гибкости.

Вердикт

Идеальная архитектура — это миф. Достаточно хорошая архитектура — это дисциплина, знающая, что нужно делать, что отложить, а что вообще не стоит использовать.

Начните с простого. Когда возникнут проблемы, добавляйте уровни. И помните, что отзывы о вашем приложении в Play Store пишут пользователи, а не ваш граф внедрения зависимостей.

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: