Notre prochaine étape dans la construction d’une application MVC est de planifier ce que va contenir notre contrôleur. Plongeons-nous dans ce sujet !
Comment planifier le Contrôleur ?
Le contrôleur est responsable du séquençage des interactions utilisateur. C’est un peu le médiateur de l’application, qui vérifie son fonctionnement global, et utilise vues et modèles quand il le faut. Si l’on observe le jeu, voici à quoi ressemble la séquence :
Créez le jeu.
Entrez les noms des joueurs.
Battez les cartes.
Distribuez une carte à chaque joueur.
Retournez les cartes.
Identifiez le vainqueur.
Montrez le vainqueur.
Reconstituez le jeu.
Comment le contrôleur sait-il quels inputs ont été donnés ?
La commande input vient de la vue. N’oubliez pas que la vue a deux buts : elle présente les informations à l’utilisateur, mais elle lui demande aussi tout input nécessaire. Ce sera cependant au contrôleur de récupérer cet input pour le traiter !
Nous devons maintenant regarder la séquence des étapes ci-dessus et trouver les interactions entre le contrôleur et la vue :
Démarrez le jeu
La première étape de toute interaction est d’instancier le modèle. Le contrôleur reçoit ou construit les objets fondamentaux du jeu. Ce sont le jeu de 52 cartes, et une liste de joueurs vide.
Il doit également être informé de la vue. La vue doit être créée ailleurs, et passée au contrôleur, plutôt que de faire créer sa propre vue au contrôleur.
Pourquoi passer la vue au contrôleur, plutôt que de simplement laisser le contrôleur la créer ?
Eh bien, si vous deviez créer une version mobile de cette application, il lui faudrait une interface utilisateur (une vue) complètement différente. Vous devriez ensuite modifier le contrôleur. Dans l’idéal, le modèle, la vue et le contrôleur doivent chacun être remplaçables sans toucher aux autres composantes.
Entrez les noms de joueurs
Pour chaque joueur qui entre son nom dans le contrôleur, ce dernier crée un objet Joueur et l’ajoute à sa liste de joueurs (dans le modèle).
Indiquez que la saisie des noms est terminée
Le contrôleur a également besoin de savoir quand tous les joueurs ont été ajoutés, pour qu’il puisse commencer à distribuer les cartes, etc.
Distribuez les cartes
Le contrôleur bat le jeu de cartes, puis pour chaque joueur il retire la carte du dessus du jeu pour la placer dans la main de ce joueur (tout cela dans le modèle).
Révélez les cartes
Le contrôleur retourne la carte de chaque joueur, puis identifie le vainqueur.
Rejouez
Les cartes sont reprises au joueur et remises dans le jeu. Le jeu peut alors recommencer depuis l’étape « Distribuez les cartes ».
Comment implémenter le Contrôleur ?
Le contrôleur doit avoir des méthodes qui correspondent aux différentes étapes du jeu. Elles peuvent utiliser n’importe quel objet du modèle, demander des informations à l’utilisateur par le biais de la vue, et présenter des informations à la vue.
Créons ces méthodes ensemble ! Reprenez le code des modèles en suivant ce lien. Puis, suivez le fil avec la capture d’écran en vidéo ci-dessous :
Voici le lien vers le code.
Nous avons notre base. Continuons sur cette lancée jusqu’à finaliser notre contrôleur. 😉
Voici le lien vers le code.
Regardons ce que nous avons construit :
Démarrez le jeu : le constructeur de
Controller
s’attend à ce qu’on lui donne un Jeu et une Vue, et instancie une liste d’objets Joueurs.Entrez les noms de joueurs : la méthode
add_player
les récupère depuis la vue.Indiquez que la saisie des noms est terminée : la méthode
run
interprète l’input None comme signifiant qu’il n’y a plus d’autres joueurs.Distribuez les cartes : c’est géré par la méthode
start_game
, car c’est la première chose qui se produit au début du jeu.Révélez les cartes : la méthode
run
attend un signal de l’utilisateur, puis elle retourne les cartes et appelle la méthodeevaluate_game
.Rejouez :
rebuild_deck
récupère toutes les cartes des joueurs, les remet dans le jeu de cartes, puis remet l’état du jeu au début de l’étape 4.
Comment implémenter la Vue ?
N’oubliez pas que la vue est à la fois l’interface utilisateur et le générateur d’événements. Notre contrôleur appellera les méthodes de la vue à la fois pour présenter des informations et pour récolter des informations de la part de l’utilisateur. La Vue ne doit par contre jamais traiter les entrées de l’utilisateur : c’est au contrôleur de s’en charger.
N’oubliez pas que si vous pouvez vous contenter de partager des valeurs “simples” (int, str, bool) entre vos différentes couches de l’application, vous pouvez aussi passer des objets complexes comme des listes, des dictionnaires ou encore des instances de classe. La plupart des design patterns reposent d’ailleurs sur les liens que peuvent faire les classes entre elles. 🧐
Alors, à quoi ressemblera la classe Vue ( View
) ? Construisons-la ensemble !
Voici le lien vers le code.
Regardons ce que nous avons ajouté :
Entrez les noms de joueurs : la vue envoie la chaîne entrée au contrôleur, qui crée un objet Player et l’ajoute au modèle.
Révélez les cartes : la vue donne à l’utilisateur un moyen de faire retourner les cartes et évaluer le jeu.
Démarrez le jeu : la vue donne à l’utilisateur un moyen d’indiquer s’il veut rejouer ou quitter l’application.
Notre implémentation est simple et directe. Elle montre simplement les noms des joueurs, les cartes distribuées et les résultats sur la ligne de commande. Néanmoins, vu que nous avons séparé cette fonctionnalité, nous pourrions facilement remplacer ce mécanisme par une implémentation GUI, ou même des haut-parleurs et un micro !
Il ne reste plus qu’à ce que le code appelant crée le Jeu, la Vue et le Contrôleur, puis exécute l’application – regardons-les collaborer.
Voici le lien vers le code.
En résumé
Le contrôleur est responsable du séquençage du cas d’usage, et valide les événements envoyés par la vue.
La vue est responsable de la présentation du modèle, de l’information de la séquence, et de la récolte des inputs de l’utilisateur.
Les responsabilités du contrôleur sont définies en regardant les étapes de l’application. Les responsabilités de la vue sont définies par ce que le contrôleur doit montrer à l’utilisateur.
Nous avons maintenant une application qui fonctionne, et qui suit l’approche MVC. Dans la prochaine partie, nous allons découvrir les principes de conception SOLID un par un, et les utiliser pour renforcer notre application.
Je finis par un petit partage : la page web de Trygve M. H. Reenskaug, le créateur de ce pattern très connu et répandu dans le monde du développement. Lecture en anglais, mais ça en vaut le coup (surtout la partie sur le MVC, dans notre cas). 🤗