• 8 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 19/03/2024

Structurez une application avec le pattern d’architecture MVC

Notre dernier pattern, qui sera un pattern d’architecture, est le MVC – ou le pattern Modèle-Vue-Contrôleur. Comme nous le verrons, ce pattern constitue un excellent choix lorsque les utilisateurs doivent interagir fréquemment avec le système que vous codez !

Un pattern d’architecture ? C’est nouveau, ça, non ?

Oui, en effet ! Pour ce dernier exemple, je vais vous proposer un pattern d’architecture, qui à la différence des design patterns, s’applique sur tout votre code. Vous ne pourrez donc utiliser qu’un seul pattern d’architecture par projet, et ce projet pourra d’ailleurs inclure plusieurs design patterns. 🤯

Qu’est-ce que le MVC ?

Le MVC est une approche d’architecture de logiciel. Il divise les responsabilités du système en 3 parties distinctes :

  • Modèle : Le modèle contient les informations relatives à l’état du système. Ce sont les fonctionnalités brutes de l’application.

  • Vue : La vue présente les informations du modèle à l’utilisateur. Elle sert d’interface visuelle et/ou sonore pour l’utilisateur.

  • Contrôleur : Le contrôleur garantit que les commandes utilisateurs soient exécutées correctement, modifiant les objets du modèle appropriés, et mettant à jour l’application. C’est finalement les rouages de l’application, et c’est la couche qui apporte une interaction avec l’utilisateur.  

3 blocs nommés Modéle, Vue et Contrôleur. Des flèches illustrant que le contrôleur reçoit des actions d'utilisateurs de la vue et des notifications du modèle et met à jour l'application.
L'architecture MVC

Comment cela fonctionne-t-il concrètement ?

Réfléchissez à la façon dont vous pourriez interagir avec un juke-box à l’ancienne.

Un juke-box
Un juke-box (Wikimedia)

Lorsque vous voulez écouter une chanson, tout ce qui vous intéresse, c’est l’outil pour sélectionner les chansons, et le système de haut-parleurs qui va vous les passer.

Vous insérez votre pièce, choisissez votre chanson, et enfin vous l’écoutez tandis que tous ceux qui se trouvent à portée d’oreille vous jugent pour vos goûts musicaux infâmes. 😱

Cependant, peu vous importe que les chansons soient en format MP3, en vinyle, ou soient téléchargées d’Internet sur le moment. Vous ne vous demandez pas à quelle fréquence le technicien vient assurer l’entretien de la machine ou récupérer l’argent.

Les choses avec lesquelles vous avez des interactions comprennent la Vue, tandis qu’en coulisses le Modèle conserve toutes les informations sur l’état, que le Contrôleur séquence toutes les actions, et qu’ainsi vous ne puissiez pas lancer votre chanson avant d’insérer votre pièce, par exemple !

Et il s’avère que ce processus est beaucoup plus simple si ces trois composantes – avec leurs responsabilités distinctes – sont bien séparées dans l’architecture de votre système.

Alors, que verrait-on si on pouvait implémenter le juke-box en Python ?

Que contient le Modèle (M) ?

Les informations relatives à l’état sont conservées dans les classes du modèle. Ce sont les éléments qui sont vus et manipulés. De plus, s’il y a quelque chose que vous devrez stocker à long terme, ce sont bien les objets du modèle. Pour le juke-box, il pourrait s’agir de la bibliothèque de chansons et d’illustrations, de la liste des tarifs, et de la date du dernier passage du technicien.

PRICE_PER_SONG = 1.20
 

class Song:
    """Modèle représentant un son."""
 
    def __init__(self, name, artist, genre, artwork):
        """Initialise les détails relatifs au son."""
        self.artist = artist
        self.name = name
        self.genre = genre
        self.artwork = artwork
 

class Library:
    """Modèle qui stocke les sons."""
 
    def __init__(self):
        """Initialise une liste de sons."""
        self.songs = []
 

class ServiceInfo:
    """Modèle qui gère la maintenance de la jukebox."""

    def __init__(self, status, engineer_name):
        """Initialise les détails du service."""
        self.service_date = datetime.now()
        self.status = status
        self.engineer = engineer_name

Au chapitre suivant, nous nous entraînerons à mettre ceci en application en développant une application simple, où nous placerons la fonctionnalité concernée respectivement dans le modèle, la vue et le contrôleur.

Que contient la Vue (V) ?

La vue correspond à la façon dont le modèle est présenté à l’utilisateur, et dont il interagit avec lui. C’est l’élément qui est le plus susceptible de changer. Il vous faut clairement distinguer la manière dont cette partie interagit avec le reste de votre système. Pour le juke-box, cela inclurait le panneau de boutons servant à sélectionner la musique, la fente où insérer la pièce pour payer, et les haut-parleurs qui passent vos classiques préférés. 🎵

class Touchscreen:
    """Vue qui gère l'interface de la jukebox."""
 
    def select_song(self):
        """Sélectionne un son."""
        pass
 
    def prompt_for_next_song(self, songs):
        """Demande un nouveau son."""
        for song in songs:
            # affiche les sons
            pass
        return "Dark Chest of Wonders"
 
 
class Speakers:
    """Vue qui gère le son."""
 
    def __init__(self):
        """Initialise le volume."""
        self.volume = 5
 
    def get_louder(self):
        """Augmente le volume."""
        self.volume += 1
 
    def get_quieter(self):
        """Baisse le volume."""
        self.volume -= 1
 
    def play_song(self, song):
        """Joue la musique."""
        pass
 
 
class CoinSlot:
    """Vue qui gère la reception de l'argent."""
 
    def __init__(self, amount):
        """Initialise le montant."""
        self.amount = amount
 
    def request_money(self, amount):
        """Attend un montant de l'utilisateur."""
        # attend l'argent
        # donne le change
        self.amount += amount
        return True

Comment la vue peut-elle contenir des haut-parleurs ? Ils ne produisent pas d’images !

C’est vrai – mais Vue est simplement le nom générique donné à toutes les composantes du système qui assurent l’interface avec l’utilisateur. Dans notre prochaine application, un jeu de cartes, la vue sera simplement constituée par les outputs de la console, mais pour d’autres applications, il pourrait plutôt s’agir d’une interface API, ou d’une page web.

Que contient le Contrôleur (C) ?

C’est dans le contrôleur que le flux de l’application est géré. Tout le séquençage des interactions entre l’utilisateur et le système s’y trouve. Voyez le contrôleur comme une sorte de colle entre le modèle et la vue. L’utilisateur interagit avec la vue, qui interagit à son tour avec le contrôleur. Le contrôleur apporte ensuite les modifications appropriées aux objets du modèle, en crée de nouveaux, ou supprime ceux dont on n’a plus besoin.

Dans le juke-box, cela inclurait la logique de sélection des chansons d’après le catalogue que vous pouvez consulter, la logique qui attend que vous ayez payé avant que l’on ne passe la musique, et le système pour appeler le technicien. Notez la façon dont le contrôleur utilise et modifie le modèle, et celle dont il dit quoi faire à la vue.

class Controller:
    """Contrôleur principal."""
 
    def __init__(self):
        """Initialise les modèles et les vues."""
        self.bank = CoinBox()
        self.library = Library()
        self.service_history = []
 
        self.ui = Touchscreen()
        self.audio_output = Speakers()
 
    def play_next_song(self):
        """Joue le prochain son."""
        songs_to_suggest = []
        for song in self.library:
            # filter logic
            songs_to_suggest.append(song)
 
        chosen_song = self.ui.prompt_for_next_song(songs_to_suggest)
        request_money(PRICE_PER_SONG)
        self.audio_output.play_song(chosen_song)
 
    # Beaucoup plus de méthodes ici...

Quels sont les avantages du MVC ?

Imaginez que vous souhaitiez moderniser votre juke-box avec vos titres récents favoris. Vous n’avez qu’à mettre à jour le modèle ! La vue et le contrôleur travailleront sans accroc avec la bibliothèque mise à jour.

Ou alors, imaginez que vous souhaitiez ajouter des écouteurs sans fil, afin que vos amis et vous-même puissiez faire la fête sans déranger le voisinage. Ceci n’affecte que la vue, tandis que le modèle et le contrôleur restent inchangés.

Cela signifie aussi que vous pouvez tester la technologie des écouteurs avant de les acheter et de les installer – essayez-les simplement avec un autre appareil pour écouter de la musique au magasin !

Le fait de séparer ainsi des parties de l’architecture en morceaux différents, avec des responsabilités distinctes, rend le système beaucoup plus facile à :

  • comprendre ;

  • modifier ;

  • tester ;

  • réparer.

D’ailleurs, plus loin dans ce cours, nous traiterons des principes SOLID, qui constituent des règles que vous pouvez suivre pour vous assurer que votre code est maintenable pour ces raisons. Pas de surprise – nous verrons que le design pattern MVC suit très bien ces principes ! 

En résumé

  • Le MVC assure que votre code est facile à maintenir, en séparant les responsabilités :

    • Le modèle contient les informations sur l’état.

    • La vue contient les éléments qui interagissent avec l’utilisateur.

    • Le contrôleur s’assure que la séquence des étapes se déroule correctement.

Au chapitre suivant, nous nous focaliserons sur la création des classes du modèle en créant une application simple ensemble – un jeu de cartes  !

Exemple de certificat de réussite
Exemple de certificat de réussite