MVC: суть патерну Model-View-Controller та його реалізація

Автор: IT Sectr Опубліковано: 2026-02-16 Час читання: 9 хв

MVC (Model-View-Controller) — архітектурний патерн, який розділяє застосунок на три компоненти: Model відповідає за дані та бізнес-логіку, View — за користувацький інтерфейс, Controller — за обробку введення та координацію Model і View. В iOS MVC реалізується через UIViewController, в Android — через Activity та Fragment. MVC залишається базовим патерном, на основі якого побудовані MVVM, MVP та Clean Architecture. Детальніше — на MVC in Cocoa Core.

Головне

  • MVC — три компоненти: Model (дані), View (інтерфейс), Controller (логіка)
  • UIViewController — реалізація Controller на iOS, що відповідає за життєвий цикл екрана
  • Activity/Fragment — реалізація Controller в Android з аналогічними функціями
  • Massive View Controller — головна проблема MVC: контролер розростається до тисяч рядків
  • Зв'язок компонентів — Controller оновлює View та Model, Model повідомляє Controller про зміни

Що таке MVC: суть патерну Model-View-Controller

MVC (Model-View-Controller) — архітектурний патерн, запропонований Trygve Reenskaug у 1979 році для мови Smalltalk-80. Патерн розділяє застосунок на три шари: Model містить дані та бізнес-логіку, View відповідає за відображення, Controller обробляє введення користувача та оновлює Model і View. Розділення відповідальності дозволяє змінювати кожен шар незалежно — наприклад, замінити View з UIKit на SwiftUI без зміни бізнес-логіки в Model.

Взаємодія компонентів у MVC слідує циклу: користувач взаємодіє з View → Controller отримує подію → Controller оновлює Model → Model повідомляє Controller про зміни → Controller оновлює View. У класичній реалізації Model використовує патерн Observer: при зміні даних Model розсилає сповіщення, Controller підписується та оновлює View. У реалізації Apple Key-Value Observing (KVO) або NotificationCenter виконують цю роль.

КомпонентВідповідальністьПриклад в iOSПриклад в Android
ModelДані, бізнес-логіка, мережаStruct User, CoreDataData class, Repository
ViewВідображення UIStoryboard, XIB, UIViewXML layout, Jetpack Compose
ControllerОбробка введення, координаціяUIViewControllerActivity, Fragment

MVC в сучасній мобільній розробці використовується рідше, ніж 10 років тому, але залишається обов'язковим для розуміння. Apple рекомендує MVC для простих екранів у UIKit-застосунках. Google не рекомендує чистий MVC для Android — офіційна документація пропонує MVVM з Jetpack. Однак знання MVC необхідне для роботи з успадкованими проєктами та для розуміння еволюції архітектурних патернів.

MVC в iOS: UIViewController та storyboard

Apple MVC — кастомна реалізація патерну, вбудована в UIKit. UIViewController виконує роль Controller: керує життєвим циклом екрана (viewDidLoad, viewWillAppear, viewDidDisappear), обробляє дотики та дії користувача, оновлює View через IBOutlets. View створюється в Interface Builder (storyboard або XIB) або програмно. Model — будь-які об'єкти даних: мережеві сервіси, стеки CoreData, структури Swift.

swift
final class UserViewController: UIViewController {
    // View (через storyboard outlet)
    @IBOutlet private var nameLabel: UILabel!
    @IBOutlet private var emailLabel: UILabel!

    // Model
    private let userService = UserService()

    override func viewDidLoad() {
        super.viewDidLoad()
        loadUser()
    }

    private func loadUser() {
        userService.fetchUser { [weak self] user in
            // Controller оновлює View
            self?.nameLabel.text = user.name
            self?.emailLabel.text = user.email
        }
    }
}

Проблема Apple MVC — View і Controller тісно пов'язані. UIViewController одночасно керує і View, і логікою. Storyboard зберігає View у XML, але контролер має прямі посилання на UI-елементи через IBOutlets. Це порушує принцип єдиної відповідальності: контролер відповідає за життєвий цикл, делегатів, datasource, target-action та анімації. В результаті стандартний екран iOS-застосунку містить 200–500 рядків у контролері.

Життєвий цикл ViewController — Apple надає 6 методів життєвого циклу: loadView (створення View вручну), viewDidLoad (після завантаження View у пам'ять), viewWillAppear (перед появою на екрані), viewDidAppear (після анімації), viewWillDisappear (перед виходом з екрана), viewDidDisappear (після виходу). Кожен метод — місце для розміщення логіки в MVC. Використання цих методів для бізнес-логіки прискорює зростання контролера.

MVC в Android: Activity, Fragment та XML layout

Android MVC — Activity та Fragment виконують роль Controller, XML-файли layout — View, будь-який POJO-клас з даними — Model. Activity керує життєвим циклом екрана: onCreate, onStart, onResume, onPause, onStop, onDestroy. Fragment — підекран всередині Activity з власним життєвим циклом. View (XML) відокремлена від Controller і завантажується через setContentView або LayoutInflater. Model — репозиторії, бази даних, мережеві виклики.

kotlin
class UserActivity : AppCompatActivity() {
    // View через XML layout
    private lateinit var binding: ActivityUserBinding

    // Model
    private val userRepository = UserRepository()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityUserBinding.inflate(layoutInflater)
        setContentView(binding.root)
        loadUser()
    }

    private fun loadUser() {
        userRepository.getUser { user ->
            runOnUiThread {
                binding.nameText.text = user.name
                binding.emailText.text = user.email
            }
        }
    }
}

Android ViewBinding та DataBinding — сучасні інструменти, що зменшують зв'язність Controller та View. ViewBinding генерує клас з прямими посиланнями на View з XML, усуваючи findViewById. DataBinding додає можливість зв'язувати дані з UI в XML-розмітці через @{user.name}. DataBinding — крок у бік MVVM, оскільки дозволяє передавати дані з Model у View без коду в Activity. Google рекомендує DataBinding для всіх нових проєктів.

Життєвий цикл Android складніший за iOS: Activity може бути знищена та перестворена при повороті екрана, нестачі пам'яті або зміні конфігурації. У чистому MVC контролер (Activity) містить логіку, яка втрачається при знищенні. Це вимагає збереження стану через onSaveInstanceState або ViewModel з Jetpack, що виходить за рамки чистого MVC і наближає архітектуру до MVVM.

Massive View Controller та обмеження MVC

Massive View Controller — термін, що описує головну проблему MVC у мобільній розробці. Контролер в iOS та Android бере на себе занадто багато обов'язків: обробка введення, валідація даних, мережева взаємодія, навігація, кешування, анімації, управління життєвим циклом. В результаті контролер розростається до 500–2000 рядків коду, стає важким для читання, тестування та підтримки.

Причини Massive View Controller — архітектура UIKit та Android Framework стимулює розміщення логіки в контролері. Мережеві виклики, обробка JSON, навігація — все це природно писати в Activity або UIViewController, оскільки вони мають доступ до життєвого циклу та UI. Розробник повинен свідомо виносити логіку в окремі класи (Service, Manager, Interactor), що вимагає дисципліни та розуміння архітектурних принципів.

Проблема MVCОписРішення
Сильна зв'язністьController знає про View та ModelMVVM — ViewModel не знає про View
Складність тестуванняController залежить від UIKit/AndroidВинос логіки в сервіси
Життєвий циклСтан втрачається при поворотіViewModel з Jetpack/SwiftUI
Відсутність навігаціїController керує переходамиCoordinator патерн, Router

Тестування MVC — Model тестується ізольовано юніт-тестами. Controller тестувати складно через залежність від UIKit/UIFoundation. XCTest не дозволяє створювати UIViewController без вікна перегляду. Для Android ActivityTestRule та Robolectric частково вирішують проблему, але тести повільні. View зазвичай не тестується юніт-тестами — для UI застосовуються скріншотні та UI-тести (XCUITest, Espresso).

Коли MVC виправданий — прості екрани з одного-двох елементів (екран логіна, профілю, налаштувань). Прототипи та MVP для перевірки гіпотез — MVC швидше писати без додаткових шарів. Проєкти з малою кодовою базою до 10–15 екранів. У складних проєктах MVC веде до накопичення технічного боргу та вимагає рефакторингу кожні 6–12 місяців.

Порівняння MVC з MVVM, MVP та Clean Architecture

MVC vs MVVM — головна відмінність: у MVVM контролер замінено на ViewModel, який не має посилання на View. Дані передаються через Observable (SwiftUI), LiveData/StateFlow (Android) або Combine/RxSwift. ViewModel тестується юніт-тестами без UI-залежностей. Apple рекомендує MVVM зі SwiftUI з 2019 року, Google — MVVM з LiveData/Flow як офіційну архітектуру Android. MVVM вимагає більше коду для зв'язування, але суттєво покращує тестованість.

MVC vs MVP — у MVP (Model-View-Presenter) Presenter — це тестований шар, який отримує View через інтерфейс. На відміну від MVC, де Controller безпосередньо керує View через UIKit, Presenter не залежить від фреймворку — він працює через абстракцію ViewInterface. MVP популярний в Android-розробці до появи Jetpack і використовується в старих проєктах. Presenter живе довше за Activity і зберігає стан при повороті екрана.

MVC vs Clean Architecture — Clean Architecture додає шари Use Cases (Interactors), Entities, Gateways та Repository. MVC залишається в Presentation шарі, але бізнес-логіка виноситься в Domain шар з Use Cases. Clean Architecture вирішує проблему Massive View Controller радикально — Controller містить лише виклики Use Cases та оновлення View. Недолік — значне збільшення кількості класів та файлів, що виправдано для проєктів від 50+ екранів.

swift
// MVC в iOS: Controller містить все
class OrderViewController: UIViewController {
    func placeOrder() {
        // Валідація + мережа + UI оновлення
        guard Validation.isValid(total) else { return }
        NetworkService.shared.submit(order) { [weak self] result in
            self?.handleResult(result)
        }
    }
}

// MVVM: логіка в ViewModel
class OrderViewModel: ObservableObject {
    @Published var state: OrderState = .idle
    func placeOrder() { /* бизнес-логика */ }
}

Вибір архітектури залежить від розміру команди, проєкту та необхідної тестованості. Для команди з 1–2 розробників та проєкту до 20 екранів підійде MVVM. Для великої команди від 5 розробників та проєкту від 50 екранів — Clean Architecture з модульною структурою. MVC залишається актуальним для розуміння еволюції архітектур, для підтримки легасі-проєктів та для простих екранів в UIKit без складної бізнес-логіки.

Часті запитання

У чому головна проблема MVC у мобільній розробці?

Основна проблема — Massive View Controller. В iOS контролер UIViewController відповідає за все: обробку введення, оновлення View, роботу з мережею, навігацію та життєвий цикл. В Android Activity/Fragment виконує аналогічні функції. В результаті контролер розростається до тисяч рядків коду, стає складним для тестування та підтримки, порушуючи принцип єдиної відповідальності.

Чим MVC відрізняється від MVVM?

В MVC контролер безпосередньо оновлює View та обробляє введення користувача. В MVVM роль контролера виконує ViewModel, який не має посилання на View — дані передаються через механізми прив'язки. MVVM краще тестується, оскільки ViewModel не залежить від UIKit або Android Framework. Apple рекомендує MVVM зі SwiftUI, Google — MVVM з Jetpack Compose.

Чи можна використовувати MVC у сучасних проєктах?

Так, MVC залишається робочим патерном для простих екранів та прототипів. Apple рекомендує MVC для UIKit-застосунків з простими екранами. Для складних проєктів з безліччю екранів, мережевими запитами та кешуванням краще обрати MVVM, VIPER або Clean Architecture. Початківцям рекомендується освоїти MVC перед вивченням складніших патернів.

Як тестувати MVC застосунок?

Model тестується ізольовано — це звичайні об'єкти даних та бізнес-логіка. Controller складно тестувати через залежність від UIKit або Android Framework. Рекомендується виносити бізнес-логіку з контролера в окремі сервіси або interactor'и, які тестуються юніт-тестами. View зазвичай не тестується юніт-тестами — для неї використовуються UI-тести та скріншотні тести.

Який патерн обрати після MVC?

На iOS — MVVM зі SwiftUI та Combine, стандарт Apple з 2019 року. На Android — MVVM з LiveData або StateFlow, офіційно рекомендований Google. Для великих проєктів з командами від 5 розробників — Clean Architecture з VIPER на iOS або Clean Architecture на Android з розділенням на модулі за фічами. Для легасі-проєктів з MVC — поступовий рефакторинг з виносом логіки в окремі сервіси.

Підсумки

  • MVC — архітектурний патерн з розділенням на Model, View та Controller
  • iOS MVC — UIViewController + storyboard + сервіси даних
  • Android MVC — Activity/Fragment + XML layout + репозиторії
  • Massive View Controller — головна проблема через змішування відповідальності
  • Тестування — Model тестується легко, Controller вимагає виносу логіки
  • Еволюція — MVC → MVVM → Clean Architecture для зростаючих проєктів
  • Сумісність — патерни можна комбінувати в одному проєкті

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також