ViewModel — це не місце для вашої логіки
20 лютого 2023 р.2 хв читанняВостаннє оновлено 11.01.2026
Одна з найпоширеніших помилок, яку я бачу в Android-розробці, — це перевантажені ViewModels.
ViewModel є — і повинна залишатися — тримачем UI-стану (state), і нічим більше. Її відповідальність — експозити (expose) стейт і трансформувати його. Все, що не стосується стейту, наприклад, навігація або I/O, там не місце.
Чому ніякої навігації?
Розгляньмо застосунок, спочатку розроблений тільки для телефонів. Навігація проста: ви передаєте навігатор і пушите (push) екрани в стек. Тепер уявіть адаптацію цього ж застосунку для планшетів або десктопів.
Раптом навігація перестає бути лінійним стеком. Екран може потребувати відображення поруч з іншим, у панелі (pane) або в зовсім іншому лейауті. Якщо логіка навігації живе всередині ViewModel, ви застрягнете на переписуванні або розгалуженні цієї логіки для кожного форм-фактора.
Навіть якщо ми ігноруємо Single Responsibility Principle, вбудовування навігації у ViewModels тісно пов'язує (tightly couples) їх з конкретною структурою UI — і це не масштабується за межі одного розміру екрана.
Чому ніяких I/O операцій?
ViewModel, що виконує низькорівневе I/O — це прямий удар по тестуємості та підтримуваності. Ці питання належать до дата-леєру (data layer).
Як тільки I/O прокрадається у ViewModel, тести починають розмивати відповідальність.
UI-логіка, бізнес-логіка та доступ до даних тестуються разом — або не тестуються зовсім. Саме тут зазвичай з'являються
@VisibleForTesting, рефлексія або просто відсутні тести.У цей момент ViewModel більше не є передбачуваним контейнером стейту, а неявним оркестратором всього — недоторканним, як головний герой у фільмі.
Емпіричне правило (The rule of thumb)
- •UI: обробляє навігацію та реагує на інтеракції користувача
- •ViewModel: тримає та трансформує стейт
- •Data / Application / Domain layers: обробляють I/O та бізнес-правила
Ось і все. Тримайте ViewModels нудними — і ваша архітектура залишиться гнучкою.
Вам також може сподобатися
20 хв читання
Помилки, які ми моделюємо неправильно
Чому повернення null, кидання ексепшнів або загортання всього в Result — це не просто питання стилю, а контракт, який ви визначаєте.
Читати нотатку
24 хв читання
Семантична типізація, яку ми ігноруємо
Перейдіть від менталітету «це просто стрінг» до підходу «це концепція». Дослідіть семантичну типізацію в Kotlin для створення кращих доменних моделей, що документують самі себе.
Читати нотатку