Код-ревью Middle MVC, MVP, MVVM, MVI, VIPER обновлено
Код-ревью: view model экрана заказа (Kotlin)
Вопрос
Найдите архитектурные проблемы во view model экрана заказа.
class OrderViewModel(private val context: Context) : ViewModel() {
var isLoading = false
var error: String? = null
var order: Order? = null
lateinit var view: OrderFragment
fun load(id: String) {
isLoading = true
GlobalScope.launch {
val response = Retrofit.Builder().baseUrl(BASE).build()
.create(Api::class.java).order(id)
order = response
isLoading = false
view.render(order!!)
}
}
}
Коротко
Правильно: class OrderViewModel @Inject constructor(private val repo: OrderRepository) : ViewModel(), состояние MutableStateFlow<OrderUiState(Loading), загрузка в viewModelScope.launch с try/catch или runCatching, переход в Content или Error. Фрагмент собирает uiState с учётом жизненного цикла и рисует его.
Что должен найти ревьюер
- Ошибкастрока 1View model держит
Context(скорее всего Activity): утечка после поворота. Нужен Application-контекст или, лучше, никаких Android-зависимостей. - Стильстрока 2Три независимых поля состояния допускают невозможные комбинации. Нужно одно неизменяемое состояние (sealed class) в
StateFlow. - Ошибкастрока 5Ссылка на фрагмент: view model переживает view, будет утечка и обращение к уничтоженному экрану. View должна подписываться на состояние.
- Ошибкастрока 9
GlobalScopeне отменяется при уходе с экрана. НуженviewModelScope. - Стильстрока 10Создание Retrofit прямо во view model: нет репозитория, нельзя подменить в тестах. Зависимость должна приходить через конструктор (DI).
- Ошибкастрока 12Ошибки сети не обрабатываются: исключение уронит корутину, а
isLoadingостанетсяtrue.
Разбор
Правильно: class OrderViewModel @Inject constructor(private val repo: OrderRepository) : ViewModel(), состояние MutableStateFlow<OrderUiState>(Loading), загрузка в viewModelScope.launch с try/catch или runCatching, переход в Content или Error. Фрагмент собирает uiState с учётом жизненного цикла и рисует его.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
Одноразовые события во view model
Следующий вопрос
MVVM или VIPER: как выбрать паттерн
Термины по теме
Ещё по теме «MVC, MVP, MVVM, MVI, VIPER»
- Выбор паттерна для небольшого приложения
- MVC, MVP, MVVM, MVI, VIPER коротко
- TCA, BLoC, Redux: общий принцип
- Что такое UDF
- Почему MVC в iOS называют Massive View Controller
- Кто за что отвечает в паттернах
- Однонаправленный поток данных в MVI
- Чем MVP отличается от MVVM