MVC (Model-View-Controller) est un modèle architectural qui divise une application en trois composants : Model est responsable des données et de la logique métier, View est responsable de l'interface utilisateur, Controller est responsable du traitement des entrées et de la coordination entre Model et View. Sous iOS, MVC est implémenté via UIViewController, sous Android — via Activity et Fragment. MVC reste le modèle fondamental sur lequel sont construits MVVM, MVP et Clean Architecture. En savoir plus sur MVC in Cocoa Core.
Points clés
MVC (Model-View-Controller) est un modèle architectural proposé par Trygve Reenskaug en 1979 pour le langage Smalltalk-80. Le modèle divise une application en trois couches : Model contient les données et la logique métier, View est responsable de l'affichage, Controller traite les entrées utilisateur et met à jour Model et View. La séparation des responsabilités permet de modifier chaque couche indépendamment — par exemple, remplacer View de UIKit vers SwiftUI sans changer la logique métier dans Model.
Interaction des composants dans MVC suit un cycle : l'utilisateur interagit avec View → Controller reçoit l'événement → Controller met à jour Model → Model notifie Controller des changements → Controller met à jour View. Dans l'implémentation classique, Model utilise le modèle Observer : lorsque les données changent, Model envoie des notifications, Controller s'abonne et met à jour View. Dans l'implémentation d'Apple, Key-Value Observing (KVO) ou NotificationCenter remplissent ce rôle.
| Composant | Responsabilité | Exemple sous iOS | Exemple sous Android |
|---|---|---|---|
| Model | Données, logique métier, réseau | Struct User, CoreData | Data class, Repository |
| View | Affichage UI | Storyboard, XIB, UIView | XML layout, Jetpack Compose |
| Controller | Traitement des entrées, coordination | UIViewController | Activity, Fragment |
MVC dans le développement mobile moderne est moins utilisé qu'il y a 10 ans, mais reste essentiel à comprendre. Apple recommande MVC pour les écrans simples dans les applications UIKit. Google ne recommande pas le MVC pur pour Android — la documentation officielle suggère MVVM avec Jetpack. Cependant, la connaissance de MVC est nécessaire pour travailler avec des projets legacy et pour comprendre l'évolution des modèles architecturaux.
Apple MVC est une implémentation personnalisée du modèle intégrée dans UIKit. UIViewController agit comme Controller : gère le cycle de vie de l'écran (viewDidLoad, viewWillAppear, viewDidDisappear), traite les touches et les actions utilisateur, met à jour View via les IBOutlets. View est créée dans Interface Builder (storyboard ou XIB) ou programmatiquement. Model — tous les objets de données : services réseau, piles CoreData, structures Swift.
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 met à jour View
self?.nameLabel.text = user.name
self?.emailLabel.text = user.email
}
}
}
Le problème d'Apple MVC — View et Controller sont fortement couplés. UIViewController gère simultanément View et la logique. Storyboard stocke View en XML, mais le contrôleur a des références directes aux éléments UI via les IBOutlets. Cela viole le principe de responsabilité unique : le contrôleur est responsable du cycle de vie, des délégués, de la datasource, de target-action et des animations. En conséquence, un écran standard d'application iOS contient 200–500 lignes dans le contrôleur.
Cycle de vie du ViewController — Apple fournit 6 méthodes de cycle de vie : loadView (création manuelle de View), viewDidLoad (après chargement de View en mémoire), viewWillAppear (avant l'apparition à l'écran), viewDidAppear (après l'animation), viewWillDisappear (avant de quitter l'écran), viewDidDisappear (après avoir quitté). Chaque méthode est un endroit pour placer la logique dans MVC. Utiliser ces méthodes pour la logique métier accélère la croissance du contrôleur.
Android MVC — Activity et Fragment agissent comme Controller, les fichiers XML layout comme View, toute classe POJO avec données comme Model. Activity gère le cycle de vie de l'écran : onCreate, onStart, onResume, onPause, onStop, onDestroy. Fragment est un sous-écran dans Activity avec son propre cycle de vie. View (XML) est séparée de Controller et chargée via setContentView ou LayoutInflater. Model — repositories, bases de données, appels réseau.
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 et DataBinding — des outils modernes qui réduisent le couplage entre Controller et View. ViewBinding génère une classe avec des références directes aux Views depuis XML, éliminant findViewById. DataBinding ajoute la possibilité de lier des données à l'UI dans le balisage XML via @{user.name}. DataBinding est un pas vers MVVM, car il permet de transmettre des données de Model à View sans code dans Activity. Google recommande DataBinding pour tous les nouveaux projets.
Cycle de vie Android est plus complexe qu'iOS : Activity peut être détruite et recréée lors de la rotation de l'écran, d'un manque de mémoire ou d'un changement de configuration. Dans le MVC pur, le contrôleur (Activity) contient de la logique qui est perdue lors de la destruction. Cela nécessite de sauvegarder l'état via onSaveInstanceState ou ViewModel de Jetpack, ce qui dépasse le MVC pur et rapproche l'architecture de MVVM.
Massive View Controller est un terme qui décrit le problème principal de MVC dans le développement mobile. Le contrôleur sous iOS et Android assume trop de responsabilités : traitement des entrées, validation des données, interaction réseau, navigation, mise en cache, animations, gestion du cycle de vie. En conséquence, le contrôleur gonfle jusqu'à 500–2000 lignes de code, devenant difficile à lire, tester et maintenir.
Causes du Massive View Controller — l'architecture de UIKit et Android Framework encourage à placer la logique dans le contrôleur. Appels réseau, traitement JSON, navigation — tout cela va naturellement dans Activity ou UIViewController car ils ont accès au cycle de vie et à l'UI. Le développeur doit consciemment extraire la logique dans des classes séparées (Service, Manager, Interactor), ce qui nécessite de la discipline et une compréhension des principes architecturaux.
| Problème de MVC | Description | Solution |
|---|---|---|
| Couplage fort | Controller connaît View et Model | MVVM — ViewModel ne connaît pas View |
| Complexité des tests | Controller dépend de UIKit/Android | Extraire la logique dans des services |
| Cycle de vie | L'état est perdu à la rotation | ViewModel de Jetpack/SwiftUI |
| Absence de navigation | Controller gère les transitions | Modèle Coordinator, Router |
Tester MVC — Model est testé isolément avec des tests unitaires. Controller est difficile à tester en raison de la dépendance à UIKit/UIFoundation. XCTest ne permet pas de créer UIViewController sans fenêtre d'affichage. Pour Android, ActivityTestRule et Robolectric résolvent partiellement le problème, mais les tests sont lents. View n'est généralement pas testée avec des tests unitaires — pour l'UI, on utilise des tests de capture d'écran et des tests UI (XCUITest, Espresso).
Quand MVC est justifié — écrans simples avec un ou deux éléments (écran de connexion, profil, paramètres). Prototypes et MVP pour validation d'hypothèses — MVC est plus rapide à écrire sans couches supplémentaires. Projets avec une petite base de code jusqu'à 10–15 écrans. Dans les projets complexes, MVC conduit à l'accumulation de dettes techniques et nécessite une refactorisation tous les 6–12 mois.
MVC vs MVVM — la principale différence : dans MVVM, le contrôleur est remplacé par ViewModel qui n'a pas de référence à View. Les données sont transmises via Observable (SwiftUI), LiveData/StateFlow (Android) ou Combine/RxSwift. ViewModel est testable avec des tests unitaires sans dépendances UI. Apple recommande MVVM avec SwiftUI depuis 2019, Google — MVVM avec LiveData/Flow comme architecture officielle Android. MVVM nécessite plus de code pour la liaison mais améliore considérablement la testabilité.
MVC vs MVP — dans MVP (Model-View-Presenter), Presenter est une couche testable qui reçoit View via une interface. Contrairement à MVC où Controller gère directement View via UIKit, Presenter ne dépend pas du framework — il fonctionne via l'abstraction ViewInterface. MVP était populaire dans le développement Android avant Jetpack et est utilisé dans les projets legacy. Presenter survit à Activity et préserve l'état à la rotation de l'écran.
MVC vs Clean Architecture — Clean Architecture ajoute des couches : Use Cases (Interactors), Entities, Gateways et Repository. MVC reste dans la couche Presentation, mais la logique métier est déplacée dans la couche Domain avec Use Cases. Clean Architecture résout radicalement le problème du Massive View Controller — Controller contient seulement des appels Use Cases et des mises à jour de View. L'inconvénient est une augmentation significative du nombre de classes et de fichiers, ce qui est justifié pour les projets de 50+ écrans.
// MVC sous iOS : Controller contient tout
class OrderViewController: UIViewController {
func placeOrder() {
// Validation + réseau + mise à jour UI
guard Validation.isValid(total) else { return }
NetworkService.shared.submit(order) { [weak self] result in
self?.handleResult(result)
}
}
}
// MVVM : logique dans ViewModel
class OrderViewModel: ObservableObject {
@Published var state: OrderState = .idle
func placeOrder() { /* logique métier */ }
}
Choix de l'architecture dépend de la taille de l'équipe, de la portée du projet et de la testabilité requise. Pour une équipe de 1–2 développeurs et un projet jusqu'à 20 écrans, MVVM fonctionne bien. Pour une grande équipe de 5+ développeurs et un projet de 50+ écrans — Clean Architecture avec structure modulaire. MVC reste pertinent pour comprendre l'évolution des architectures, maintenir des projets legacy et pour les écrans UIKit simples sans logique métier complexe.
Questions fréquentes
Le principal problème est le Massive View Controller. Sous iOS, UIViewController gère tout : traitement des entrées, mise à jour de View, réseau, navigation et cycle de vie. Sous Android, Activity/Fragment remplit des fonctions similaires. En conséquence, le contrôleur gonfle jusqu'à des milliers de lignes de code, devenant difficile à tester et à maintenir, violant le principe de responsabilité unique.
Dans MVC, le contrôleur met directement à jour View et traite les entrées utilisateur. Dans MVVM, le rôle de contrôleur est joué par ViewModel, qui n'a pas de référence à View — les données sont transmises via des mécanismes de liaison. MVVM est plus facile à tester car ViewModel ne dépend pas d'UIKit ou d'Android Framework. Apple recommande MVVM avec SwiftUI, Google recommande MVVM avec Jetpack Compose.
Oui, MVC reste un modèle fonctionnel pour les écrans simples et les prototypes. Apple recommande MVC pour les applications UIKit avec des écrans simples. Pour les projets complexes avec de nombreux écrans, requêtes réseau et mise en cache, il est préférable de choisir MVVM, VIPER ou Clean Architecture. Les développeurs débutants sont invités à maîtriser MVC avant d'apprendre des modèles plus complexes.
Model est testé isolément — ce sont des objets de données et de logique métier ordinaires. Controller est difficile à tester en raison de la dépendance à UIKit ou Android Framework. Il est recommandé d'extraire la logique métier du contrôleur dans des services ou interactors séparés, qui sont testés avec des tests unitaires. View n'est généralement pas testée avec des tests unitaires — des tests UI et des tests de capture d'écran sont utilisés.
Sous iOS — MVVM avec SwiftUI et Combine, standard d'Apple depuis 2019. Sous Android — MVVM avec LiveData ou StateFlow, officiellement recommandé par Google. Pour les grands projets avec des équipes de 5+ développeurs — Clean Architecture avec VIPER sous iOS ou Clean Architecture sous Android avec séparation des modules par fonctionnalité. Pour les projets legacy avec MVC — refactorisation progressive avec extraction de la logique dans des services séparés.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi