Pourquoi MVC pourrait ne pas être le meilleur modèle pour les applications Cocoa

MVC représente Modèle Vue Contrôleur, et c'est un modèle architectural répandu pour le développement de logiciels. C'est le modèle de conception de facto pour le développement de Cocoa, et ce depuis de très nombreuses années. La plupart d'entre nous ne peuvent imaginer créer d'applications sans cela. UIKit (iOS) et AppKit(macOS) utilisent fréquemment le MVC. Il semble presque que nous n’ayons pas d’autre option pour créer des applications pour iOS, tvOS, macOS et watchOS..

Même si vous n'êtes pas familier avec le modèle Model-View-Controller, si vous avez l'ambition de développer des applications pour l'une des plates-formes Apple, vous devez apprendre comment les vues (iOS) et Windows (macOS) sont liées aux contrôleurs et à leur rôle. modèle joue dans une application typique de cacao. Heureusement, MVC est facile à apprendre.

Dans cette courte série, j'explique ce qu'est MVC, à quoi ça ressemble dans une application Cocoa typique et pourquoi ce n'est peut-être pas la meilleure solution pour les développeurs Cocoa..

1. Un exemple

Laissez-moi vous montrer à quoi ressemble le motif MVC dans une application Cocoa typique. L'exemple que je vais vous montrer concerne iOS, mais tout ce dont nous discutons s'applique également à tvOS, macOS et watchOS. Ouvrez Xcode et créez un nouveau iOS projet basé sur le Application à vue unique modèle.

Nommez le projet MVC, Et mettre La langue à Rapide et Dispositifs à iPhone. J'utilise Xcode 8 pour ce tutoriel. Les options de configuration du projet peuvent être légèrement différentes si vous utilisez Xcode 9.

Comme son nom l’indique, le modèle Model-View-Controller définit trois composants, le modèle, la vue, et le manette. Laissez-moi vous montrer où trouver ces composants dans un projet iOS typique.

Contrôleurs

Les contrôleurs d’une application iOS sont des contrôleurs de vue, des instances du UIViewController classe ou une sous-classe de celle-ci. le UIViewController la classe est définie dans le UIKit cadre. Parce que nous avons choisi le Application à vue unique lorsque nous avons configuré le projet, Xcode a créé un contrôleur pour nous permettre de commencer, le ViewController classe, définie dans ViewController.Swift. Il hérite de la UIViewController classe.

Comme son nom l'indique, un UIViewController instance est chargée de contrôler une vue, une instance du UIView classe. Chaque contrôleur de vue d'un projet iOS conserve une référence forte à une vue, un autre composant du modèle Model-View-Controller. le UIView la classe est également définie dans le UIKit cadre.

Des vues

Nous pouvons trouver le composant de vue dans le scénario principal du projet. Ouvrir Tableau principal dans le Navigateur de projet à gauche et inspectez le Voir la scène du contrôleur. La scène contient un contrôleur de vue, une instance du ViewController classe, et il gère un UIView exemple.

Sélectionner Vue dans le storyboard à gauche et ouvrez le Inspecteur d'identité sur la droite. le Classe le champ de la vue est défini sur UIView. Dans une application iOS, les vues sont typiquement des instances de UIKit. UIView classe ou une sous-classe de celle-ci.

Des modèles

Jusqu'ici, nous avons exploré la couche contrôleur et la couche vue. Mais où pouvons-nous trouver la couche modèle du projet? Le modèle est presque toujours spécifique au projet sur lequel vous travaillez, et c'est à vous de définir, d'implémenter et d'utiliser le modèle du projet. j'écris modèle, mais vous avez généralement plusieurs modèles, en fonction de la complexité de votre projet.

Ajoutons la dernière pièce du puzzle MVC en créant un modèle. Créez un nouveau fichier Swift et nommez-le Person.swift.

Sélectionner Person.swift dans le Navigateur de projet à gauche et définir une structure nommée La personne. Nous définissons trois propriétés: 

  • Prénom de type Chaîne
  • nom de famille de type Chaîne
  • âge de type Int
struct Person let firstName: String let lastName: String let age: Int

Vous avez maintenant un modèle que vous pouvez utiliser dans votre projet. Restons simples et définissons une propriété, la personne, de type La personne? dans le ViewController classe. Nous créons un La personne exemple dans le contrôleur de vue viewDidLoad () méthode et l'assigner à la la personne propriété.

importer la classe UIKit ViewController: UIViewController // MARK: - Propriétés var person: Person? // MARK: - Voir cycle de vie ignorer func viewDidLoad () super.viewDidLoad () // Créer une personne personne = Personne (prénom: "John", nom: "Doe", age: 40)

Ce que nous voyons dans cet exemple est très courant dans les applications Cocoa utilisant le modèle Model-View-Controller. Le contrôleur de vue possède et gère le modèle et utilise le modèle pour renseigner sa vue. Dans une application plus complexe, vous chargez les données du modèle à partir d'un magasin persistant ou vous les récupérez à partir d'un back-end distant..

Définissons un débouché pour un UILabel exemple dans le contrôleur de vue et, dans le storyboard principal, ajouter une étiquette au Voir la scène du contrôleur.

importez la classe UIKit ViewController: UIViewController // MARK: - Propriétés @IBOutlet var label: UILabel!…

Dans le contrôleur de vue viewDidLoad () méthode, nous déroulons en toute sécurité la valeur stockée dans le la personne propriété et utiliser ses données pour définir la texte propriété du UILabel exemple.

Fonction de remplacement ViewDidLoad () super.viewDidLoad () // Create person person = Person (prénom: "John", lastName: "Doe", age: 40) // Remplit le libellé si let = personne label.text = " \ (person.lastName), \ (person.firstName) (\ (person.age)) "

Le résultat n'est pas très surprenant si vous connaissez le développement de Cocoa. C'est ce que nous finissons avec.

2. Qu'est-ce que Model-View-Controller?

Le modèle Model-View-Controller est facile à comprendre et à comprendre. Malgré sa simplicité, vous pouvez trouver un large éventail de saveurs du modèle MVC. MVC propose uniquement un plan de base modifiable en fonction de la plate-forme sur laquelle il est utilisé.. 

Le modèle Model-View-Controller que vous connaissez bien sur iOS, tvOS, macOS et watchOS diffère de manière subtile de la définition d'origine. Bien que les différences par rapport à la définition d'origine soient subtiles, elles ont un impact significatif sur le code que vous écrivez ainsi que sur la maintenabilité du projet..

Petite conversation

Le modèle Model-View-Controller est un ancien modèle. Il a fait sa première apparition dans les années 1970 en Smalltalk. Le motif a été conçu par Trygve Reenskaug. Au fil des ans, le modèle Model-View-Controller a fait son chemin dans de nombreux langages et frameworks, notamment Java, Rails et Django..

J'ai mentionné précédemment que le modèle MVC divise les applications en trois composants distincts: modèle, vue, et manette. L'implémentation d'origine du modèle définit le fait que la vue est chargée d'afficher les données du modèle à l'utilisateur. L'utilisateur interagit avec l'application via la couche de vue. Le contrôleur est responsable de la gestion des interactions de l'utilisateur et de la manipulation des données du modèle. La vue visualise ces modifications pour l'utilisateur. Comme illustré dans le diagramme ci-dessous, le modèle joue un rôle clé dans le modèle MVC tel qu'il a été conçu par Reenskaug..

MVC et cacao

La mise en œuvre que nous utilisons dans le développement de Cocoa diffère de la conception originale de Reenskaug. Jetez un coup d’œil au diagramme ci-dessous pour mieux comprendre l’impact de ces différences..

Comme je l'ai mentionné précédemment, la vue et le contrôleur partagent une relation étroite. Dans une application iOS typique, un contrôleur contient une référence forte à la vue qu'il gère. La vue est un objet muet qui sait comment afficher des données et répondre aux interactions de l'utilisateur. Le résultat est un composant hautement réutilisable.

Le contrôleur joue un rôle essentiel dans les applications Cocoa utilisant le modèle Model-View-Controller. Il reprend certaines des tâches du modèle dans l'implémentation MVC originale de Reenskaug. La vue et le modèle ne communiquent pas directement entre eux. Au lieu de cela, le modèle appartient généralement au contrôleur, qu'il utilise pour configurer et remplir la vue qu'il gère..

J'espère que vous pourrez voir les différences subtiles entre l'implémentation originale de Reenskaug dans Smalltalk et l'implémentation de Cocoa à laquelle nous nous sommes habitués. Les différences sont mineures, mais, comme je le dirai dans un instant, leur impact est important..

3. Le bien: séparation des problèmes et réutilisation

Avant de passer en revue les problèmes introduits par MVC, je voudrais vous montrer pourquoi le modèle Model-View-Controller est devenu un modèle si populaire et si répandu dans le développement logiciel. Le modèle Model-View-Controller que nous utilisons dans le développement de Cocoa présente un certain nombre d'avantages évidents qu'il a hérités de la mise en œuvre originale de Reenskaug..

L’avantage le plus évident du modèle Model-View-Controller est un séparation des préoccupations. La couche de vue, par exemple, est responsable de la présentation des données à l'utilisateur. Les couches modèle et contrôleur ne sont pas concernées par la présentation des données. Mais si vous utilisez MVC dans un projet Cocoa, vous savez que ce n'est pas toujours vrai. Je vais en parler plus dans un instant.

Un avantage direct de cette séparation des préoccupations est réutilisabilité. Chacun des composants du modèle Model-View-Controller est concentré sur une tâche spécifique, ce qui signifie que les blocs de construction d'une application MVC sont souvent faciles à réutiliser. Cela permet également à ces composants d'être couplés de manière lâche, ce qui augmente leur réutilisabilité. Ce n'est pas vrai pour chaque composant, cependant. Dans un projet Cocoa, par exemple, les contrôleurs sont souvent spécifiques à l'application et ne sont pas de bons candidats à la réutilisation..

Cependant, les vues et les modèles d'un projet sont hautement réutilisables s'ils sont conçus correctement. Les vues de table et de collection, par exemple, sont UIView sous-classes utilisées dans des millions d'applications. Dans la mesure où une vue sous forme de tableau délègue les interactions de l'utilisateur à un autre objet et demande à une source de données les données à afficher, elle peut se concentrer exclusivement sur la présentation des données et les interactions de l'utilisateur..

4. The Bad: Contrôleurs de vue massive

La plupart des développeurs comprennent rapidement ce que le modèle Model-View-Controller apporte à la table et comment il doit être implémenté. Malheureusement, le modèle Model-View-Controller a aussi un côté moche. J'ai déjà écrit sur la réutilisabilité et la séparation des préoccupations. Je suis sûr que je n'ai pas besoin de vous convaincre de ces avantages. Une vue de table est hautement réutilisable et incroyablement performante. Les développeurs peuvent utiliser des composants UIKit standard dans leurs applications sans avoir besoin de sous-classement ou de personnalisation..

Frapper les limites de MVC

Mais ce n'est qu'une partie de l'histoire. Vous savez quand vous commencez à atteindre les limites de MVC lorsque de nombreux contrôleurs de vues se sont introduits dans votre projet. Il est temps de changer lorsque vous parcourez des centaines ou des milliers de lignes de code pour trouver la méthode que vous recherchez.. 

Dumping It dans le contrôleur

La plupart des développeurs savent ce qui se passe dans les couches de vue et de modèle d'une application Cocoa typique optimisée par le modèle Model-View-Controller. Mais quel composant est responsable du formatage des données affichées à l'utilisateur? N'oubliez pas que les vues sont supposées être stupides et réutilisables. La vue ne devrait pas avoir besoin de formater les données. Droite? Il doit savoir uniquement comment présenter les données et répondre aux interactions de l'utilisateur. Le modèle doit-il être concerné par le formatage des données?

Et qu'en est-il du réseautage? Ce n'est certainement pas la tâche de la vue. Devrait-il être délégué au modèle? Cela ne semble pas juste. Pourquoi ne glissons-nous pas ce morceau de code dans le contrôleur. Ça ne va pas, mais ça ira pour le moment.

Après plusieurs lignes de code, vous vous retrouvez avec un contrôleur prêt à exploser et un cauchemar à tester. Essai? Je t'entends. Je ne voudrais pas tester un contrôleur de vue souffrant de syndrome de contrôleur de vue massive non plus.

5. Une meilleure solution

Vous avez commencé avec de bonnes intentions, mais vous vous êtes retrouvé avec un projet comportant un ensemble de contrôleurs en surpoids difficiles à gérer et à entretenir. Vous n'êtes pas impatient d'ajouter de nouvelles fonctionnalités au projet sur lequel vous travaillez car l'ouverture de ces contrôleurs de vue vous rend malade. Cela vous semble familier?

Il est important de réaliser qu'il s'agit d'un scénario courant. De nombreux développeurs atteignent les limites du modèle Model-View-Controller et réalisent qu'ils ont besoin de quelque chose de mieux. Il est probable que vous ayez déjà envisagé plusieurs solutions, telles que MVP (Model-View-Presenter) ou MVVM (Model-View-ViewModel).

Dans le prochain épisode de cette série, je vais zoomer sur le Model-View-ViewModel modèle. Cela vous semblera étrangement familier si vous avez déjà travaillé avec le modèle Model-View-Controller. Mais le modèle Model-View-ViewModel apporte quelques améliorations à la table qui fonctionnent très bien pour le développement de Cocoa..

Et pendant que vous attendez, consultez certains de nos autres articles sur le développement d'applications Cocoa.!