Что представляют собой MV*-паттерны, и чем отличаются MVP от MVVM?

MV*-паттерны — это архитектурные шаблоны проектирования пользовательских интерфейсов, основанные на разделении приложения на Model, View и один из вариантов "развязки" между ними: Presenter, ViewModel, Controller и т.д.

Семейство включает:

  • **MVC (Model-View-Controller)
    **
  • **MVP (Model-View-Presenter)
    **
  • **MVVM (Model-View-ViewModel)
    **
  • (и менее распространённые: MVI, MVU и др.)

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

📦 Общие компоненты MV*-паттернов

  • Model — данные и бизнес-логика (например, use cases, domain-слой, работа с API/БД).

  • View — пользовательский интерфейс, который показывает данные и принимает ввод от пользователя.

  • X (Presenter / ViewModel / Controller) — связующее звено, управляющее логикой отображения, преобразованием данных и реакцией на действия пользователя.

🔀 Сравнение MVP и MVVM

Характеристика MVP (Model-View-Presenter) MVVM (Model-View-ViewModel)
Связь View ↔ Presenter Двусторонняя: View вызывает методы Presenter, а Presenter напрямую вызывает View Односторонняя: View подписывается на LiveData / StateFlow, ViewModel не знает о View
--- --- ---
Тестируемость Высокая: Presenter легко мокается Очень высокая: ViewModel изолирована и без UI-зависимостей
--- --- ---
Управление состоянием Presenter хранит UI-логику ViewModel хранит State, LiveData, Flow
--- --- ---
Инструменты для реактивности Нет встроенных средств (используются колбэки или Rx) Используются корутины, LiveData, Flow
--- --- ---
Поддержка Android архитектурных компонентов Не обязательно Плотно интегрирован с Jetpack (ViewModel, LiveData, SavedStateHandle)
--- --- ---
Сложность Прост в реализации, но громоздок в Android-контексте Более декларативен и современен
--- --- ---

MVP — как устроено

interface View {
fun showData(data: String)
}
class Presenter(private val view: View) {
fun onButtonClicked() {
val data = getDataFromModel()
view.showData(data)
}
}
  • View вызывает методы Presenter.

  • Presenter обращается к модели и обновляет View вручную.

🔸 Минус: Presenter жёстко зависит от View, приходится писать много интерфейсов.

🧠 MVVM — как устроено

class MyViewModel : ViewModel() {
val data = MutableLiveData<String>()
fun load() {
data.value = getDataFromModel()
}
}

Во View (например, Activity):

viewModel.data.observe(this) {
textView.text = it
}
  • ViewModel ничего не знает о View.

  • View подписывается на данные и реактивно обновляется.

  • Это позволяет использовать DataBinding, StateFlow, Jetpack Compose.

✅ Когда выбирать что

Сценарий Рекомендация
Современные Android-приложения ✅ MVVM с Jetpack
--- ---
Большие легаси-проекты MVP, если уже используется
--- ---
Тестируемость View и логики — ключевое требование Обе архитектуры хороши, MVVM предпочтительнее
--- ---
У тебя много состояний и реактивного UI MVVM + StateFlow
--- ---

🔚 Вывод

  • MV* — это семейство архитектур, которое стремится разделить обязанности между слоями.

  • MVP даёт полный контроль, но требует много "рук".

  • MVVM позволяет строить реактивный, более декларативный UI, особенно удобно в связке с архитектурными компонентами Android.

  • В современных Android-проектах MVVM считается предпочтительным решением благодаря простоте, читаемости и полной интеграции с Jetpack (ViewModel, LiveData, Flow, Compose).