Что такое паттерн MVVM?

«Что такое паттерн MVVM?» — вопрос из категории Архитектура, который задают на 33% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

MVVM (Model-View-ViewModel) — это архитектурный паттерн, который разделяет ответственность в приложении на три основных слоя для улучшения тестируемости и поддержки кода.

Компоненты:

  1. Model: Представляет данные и бизнес-логику. Не зависит от UI.
  2. View: Отображает пользовательский интерфейс (UIViewController, UIView, SwiftUI View). Его задача — отражать состояние ViewModel и передавать пользовательские действия.
  3. ViewModel: Посредник между Model и View. Он:
    • Преобразует данные из Model в удобный для отображения формат.
    • Содержит логику представления (например, форматирование строк).
    • Реагирует на действия пользователя из View, обновляя Model.

Ключевой принцип: View связывается (binds) с ViewModel, обычно реактивно (через Combine, RxSwift или замыкания), чтобы автоматически обновляться при изменении состояния ViewModel.

Пример на SwiftUI и Combine:

// MARK: - Model
struct User {
    let name: String
    let registrationDate: Date
}

// MARK: - ViewModel
import Combine

final class UserViewModel: ObservableObject {
    @Published var displayName: String = ""
    private let user: User
    private let dateFormatter: DateFormatter

    init(user: User) {
        self.user = user
        dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        configureDisplayName()
    }

    private func configureDisplayName() {
        let formattedDate = dateFormatter.string(from: user.registrationDate)
        displayName = "(user.name) (joined: (formattedDate))"
    }
}

// MARK: - View (SwiftUI)
struct UserView: View {
    @StateObject var viewModel: UserViewModel

    var body: some View {
        Text(viewModel.displayName) // View автоматически обновится при изменении `displayName`
    }
}

Преимущества MVVM:

  • Разделение ответственности: View становится "тупым" и занимается только отображением.
  • Высокая тестируемость: ViewModel можно протестировать юнит-тестами без необходимости в UI.
  • Упрощение ViewController: Логика "уходит" из массивных ViewController.