MVC (Model-View-Controller) — een architectuurpatroon dat de applicatie in drie componenten verdeelt: Model is verantwoordelijk voor gegevens en bedrijfslogica, View — voor de gebruikersinterface, Controller — voor de verwerking van invoer en coördinatie van Model en View. In iOS wordt MVC geïmplementeerd via UIViewController, in Android — via Activity en Fragment. MVC blijft het basispatroon waarop MVVM, MVP en Clean Architecture zijn gebouwd. Meer — op MVC in Cocoa Core.
Belangrijkste
MVC (Model-View-Controller) — een architectuurpatroon voorgesteld door Trygve Reenskaug in 1979 voor de taal Smalltalk-80. Het patroon verdeelt de applicatie in drie lagen: Model bevat gegevens en bedrijfslogica, View is verantwoordelijk voor weergave, Controller verwerkt gebruikersinvoer en werkt Model en View bij. Scheiding van verantwoordelijkheden maakt het mogelijk elke laag onafhankelijk te wijzigen — bijvoorbeeld het vervangen van View van UIKit naar SwiftUI zonder de bedrijfslogica in Model te wijzigen.
Interactie van componenten in MVC volgt een cyclus: de gebruiker interageert met View → Controller ontvangt de gebeurtenis → Controller werkt Model bij → Model stelt Controller op de hoogte van wijzigingen → Controller werkt View bij. In de klassieke implementatie gebruikt Model het Observer-patroon: bij wijziging van gegevens verzendt Model meldingen, Controller abonneert zich en werkt View bij. In de Apple-implementatie vervullen Key-Value Observing (KVO) of NotificationCenter deze rol.
| Component | Verantwoordelijkheid | Voorbeeld in iOS | Voorbeeld in Android |
|---|---|---|---|
| Model | Gegevens, bedrijfslogica, netwerk | Struct User, CoreData | Data class, Repository |
| View | Weergave van UI | Storyboard, XIB, UIView | XML-layout, Jetpack Compose |
| Controller | Verwerking van invoer, coördinatie | UIViewController | Activity, Fragment |
MVC in moderne mobiele ontwikkeling wordt minder gebruikt dan 10 jaar geleden, maar blijft verplicht om te begrijpen. Apple beveelt MVC aan voor eenvoudige schermen in UIKit-applicaties. Google raadt pure MVC niet aan voor Android — officiële documentatie stelt MVVM met Jetpack voor. Kennis van MVC is echter noodzakelijk voor het werken met legacy-projecten en voor het begrijpen van de evolutie van architectuurpatronen.
Apple MVC — een aangepaste implementatie van het patroon ingebouwd in UIKit. UIViewController vervult de rol van Controller: beheert de levenscyclus van het scherm (viewDidLoad, viewWillAppear, viewDidDisappear), verwerkt aanrakingen en gebruikersacties, werkt View bij via IBOutlets. View wordt gemaakt in Interface Builder (storyboard of XIB) of programmatisch. Model — alle gegevensobjecten: netwerkservices, CoreData-stacks, Swift-structuren.
final class UserViewController: UIViewController {
// View (via 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 werkt View bij
self?.nameLabel.text = user.name
self?.emailLabel.text = user.email
}
}
}
Probleem van Apple MVC — View en Controller zijn nauw verbonden. UIViewController beheert tegelijkertijd zowel View als logica. Storyboard slaat View op in XML, maar de controller heeft directe verwijzingen naar UI-elementen via IBOutlets. Dit schendt het principe van enkele verantwoordelijkheid: de controller is verantwoordelijk voor levenscyclus, delegates, datasource, target-action en animaties. Als gevolg bevat een standaard scherm van een iOS-applicatie 200–500 regels in de controller.
Levenscyclus van ViewController — Apple biedt 6 methoden van de levenscyclus: loadView (handmatig aanmaken van View), viewDidLoad (na laden van View in geheugen), viewWillAppear (vóór verschijnen op het scherm), viewDidAppear (na animatie), viewWillDisappear (vóór verlaten van het scherm), viewDidDisappear (na verlaten). Elke methode — een plek voor het plaatsen van logica in MVC. Het gebruik van deze methoden voor bedrijfslogica versnelt de groei van de controller.
Android MVC — Activity en Fragment vervullen de rol van Controller, XML-lay-outbestanden — View, elke POJO-klasse met gegevens — Model. Activity beheert de levenscyclus van het scherm: onCreate, onStart, onResume, onPause, onStop, onDestroy. Fragment — subscherm binnen Activity met eigen levenscyclus. View (XML) is gescheiden van Controller en wordt geladen via setContentView of LayoutInflater. Model — repositories, databases, netwerkoproepen.
class UserActivity : AppCompatActivity() {
// View via 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 en DataBinding — moderne hulpmiddelen die de koppeling tussen Controller en View verminderen. ViewBinding genereert een klasse met directe verwijzingen naar View uit XML, waardoor findViewById overbodig wordt. DataBinding voegt de mogelijkheid toe om gegevens aan UI te koppelen in XML-opmaak via @{user.name}. DataBinding is een stap naar MVVM, omdat het mogelijk maakt gegevens van Model naar View over te dragen zonder code in Activity. Google beveelt DataBinding aan voor alle nieuwe projecten.
Levenscyclus van Android is complexer dan iOS: Activity kan worden vernietigd en opnieuw aangemaakt bij rotatie van het scherm, geheugengebrek of configuratiewijziging. In pure MVC bevat de controller (Activity) logica die verloren gaat bij vernietiging. Dit vereist het opslaan van de toestand via onSaveInstanceState of ViewModel uit Jetpack, wat buiten het kader van pure MVC valt en de architectuur dichter bij MVVM brengt.
Massive View Controller — de term die het grootste probleem van MVC in mobiele ontwikkeling beschrijft. De controller in iOS en Android neemt te veel verantwoordelijkheden op zich: verwerking van invoer, gegevensvalidatie, netwerkinteractie, navigatie, caching, animaties, beheer van de levenscyclus. Als gevolg groeit de controller uit tot 500–2000 regels code, wordt moeilijk leesbaar, testbaar en onderhoudbaar.
Oorzaken van Massive View Controller — de architectuur van UIKit en Android Framework stimuleert het plaatsen van logica in de controller. Netwerkoproepen, JSON-verwerking, navigatie — dit alles wordt van nature geschreven in Activity of UIViewController, omdat ze toegang hebben tot de levenscyclus en UI. De ontwikkelaar moet bewust logica in afzonderlijke klassen (Service, Manager, Interactor) onderbrengen, wat discipline en begrip van architectuurprincipes vereist.
| MVC-probleem | Beschrijving | Oplossing |
|---|---|---|
| Sterke koppeling | Controller kent View en Model | MVVM — ViewModel kent View niet |
| Moeilijk testen | Controller is afhankelijk van UIKit/Android | Logica onderbrengen in services |
| Levenscyclus | Toestand gaat verloren bij rotatie | ViewModel uit Jetpack/SwiftUI |
| Gebrek aan navigatie | Controller beheert overgangen | Coordinator-patroon, Router |
Testen van MVC — Model wordt geïsoleerd getest met unittesten. Controller is moeilijk te testen vanwege afhankelijkheid van UIKit/UIFoundation. XCTest staat niet toe UIViewController te maken zonder weergavevenster. Voor Android lossen ActivityTestRule en Robolectric het probleem gedeeltelijk op, maar de testen zijn traag. View wordt meestal niet getest met unittesten — voor UI worden screenshot- en UI-testen (XCUITest, Espresso) gebruikt.
Wanneer MVC gerechtvaardigd is — eenvoudige schermen met een of twee elementen (inlogscherm, profiel, instellingen). Prototypes en MVP voor het testen van hypotheses — MVC wordt sneller geschreven zonder extra lagen. Projecten met een kleine codebasis tot 10–15 schermen. In complexe projecten leidt MVC tot ophoping van technische schuld en vereist refactoring elke 6–12 maanden.
MVC vs MVVM — het belangrijkste verschil: in MVVM wordt de controller vervangen door ViewModel, dat geen verwijzing naar View heeft. Gegevens worden overgedragen via Observable (SwiftUI), LiveData/StateFlow (Android) of Combine/RxSwift. ViewModel wordt getest met unittesten zonder UI-afhankelijkheden. Apple beveelt MVVM met SwiftUI aan sinds 2019, Google — MVVM met LiveData/Flow als officiële architectuur voor Android. MVVM vereist meer code voor binding, maar verbetert de testbaarheid aanzienlijk.
MVC vs MVP — in MVP (Model-View-Presenter) is Presenter een testbare laag die View ontvangt via een interface. In tegenstelling tot MVC, waar Controller direct View beheert via UIKit, is Presenter niet afhankelijk van het framework — het werkt via de abstractie ViewInterface. MVP was populair in Android-ontwikkeling vóór de komst van Jetpack en wordt gebruikt in oude projecten. Presenter leeft langer dan Activity en behoudt de toestand bij rotatie van het scherm.
MVC vs Clean Architecture — Clean Architecture voegt lagen Use Cases (Interactors), Entities, Gateways en Repository toe. MVC blijft in de Presentation-laag, maar bedrijfslogica wordt verplaatst naar de Domain-laag met Use Cases. Clean Architecture lost het probleem van Massive View Controller radicaal op — Controller bevat alleen oproepen van Use Cases en het bijwerken van View. Nadeel is een aanzienlijke toename van het aantal klassen en bestanden, wat gerechtvaardigd is voor projecten met 50+ schermen.
// MVC in iOS: Controller bevat alles
class OrderViewController: UIViewController {
func placeOrder() {
// Validatie + netwerk + UI-update
guard Validation.isValid(total) else { return }
NetworkService.shared.submit(order) { [weak self] result in
self?.handleResult(result)
}
}
}
// MVVM: logica in ViewModel
class OrderViewModel: ObservableObject {
@Published var state: OrderState = .idle
func placeOrder() { /* bedrijfslogica */ }
}
Keuze van architectuur hangt af van de teamgrootte, project en vereiste testbaarheid. Voor een team van 1–2 ontwikkelaars en een project tot 20 schermen is MVVM geschikt. Voor een groot team van 5 ontwikkelaars en een project vanaf 50 schermen — Clean Architecture met modulaire structuur. MVC blijft relevant voor het begrijpen van de evolutie van architecturen, voor ondersteuning van legacy-projecten en voor eenvoudige schermen in UIKit zonder complexe bedrijfslogica.
Veelgestelde vragen
Het grootste probleem is Massive View Controller. In iOS is de UIViewController-controller verantwoordelijk voor alles: verwerking van invoer, bijwerken van View, werken met netwerk, navigatie en levenscyclus. In Android vervult Activity/Fragment vergelijkbare functies. Als gevolg groeit de controller uit tot duizenden regels code, wordt moeilijk te testen en te onderhouden, en schendt het principe van enkele verantwoordelijkheid.
In MVC werkt de controller direct View bij en verwerkt gebruikersinvoer. In MVVM wordt de rol van de controller vervuld door ViewModel, dat geen verwijzing naar View heeft — gegevens worden overgedragen via bindingsmechanismen. MVVM is beter testbaar omdat ViewModel niet afhankelijk is van UIKit of Android Framework. Apple beveelt MVVM met SwiftUI aan, Google — MVVM met Jetpack Compose.
Ja, MVC blijft een werkend patroon voor eenvoudige schermen en prototypes. Apple beveelt MVC aan voor UIKit-applicaties met eenvoudige schermen. Voor complexe projecten met meerdere schermen, netwerkverzoeken en caching kunt u beter MVVM, VIPER of Clean Architecture kiezen. Beginnende ontwikkelaars wordt aangeraden MVC onder de knie te krijgen voordat ze complexere patronen bestuderen.
Model wordt geïsoleerd getest — dit zijn gewone gegevensobjecten en bedrijfslogica. Controller is moeilijk te testen vanwege afhankelijkheid van UIKit of Android Framework. Het wordt aanbevolen bedrijfslogica uit de controller onder te brengen in afzonderlijke services of interactors, die met unittesten worden getest. View wordt meestal niet getest met unittesten — hiervoor worden UI-testen en screenshot-testen gebruikt.
Op iOS — MVVM met SwiftUI en Combine, de Apple-standaard sinds 2019. Op Android — MVVM met LiveData of StateFlow, officieel aanbevolen door Google. Voor grote projecten met teams van 5 ontwikkelaars — Clean Architecture met VIPER op iOS of Clean Architecture op Android met verdeling in modules per functie. Voor legacy-projecten met MVC — geleidelijke refactoring met het onderbrengen van logica in afzonderlijke services.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook