Autour du codeDevelopper toujours mieux
Posté le

L'histoire du MVC (Modèle, Vue Controller)

Nous allons partir en 1978 pour assister à la naissance du MVC...

Le MVC (Model, View, Controller) traduit par Modèle, Vue, Contrôleur en français est un modèle d'architecture utisé pour la première fois dans le langage de programmation Smalltalk.

C'est dans un article de 1988 intitulé "A Cookbook for Using the Model-View-Controller User Interface Paradigm in Smalltalk -80" que le principe de programmation MVC est présenté au public. Cette publication fait suite aux travaux de 1978 de Trygve Reenskaug sur le Model View Controller Editor en 1979.

Smalltalk à l'instar de Python est un langage où tout est objet, c'est donc à partir de l'article de 1988 que nous allons implémenter notre architecture MVC en python. Commençons par le Modèle, cette partie dit contenir les informations métier.

Le modèle doit avoir des composants qui lui sont dépendants, les vues, et il doit pouvoir envoyer un même message à toutes ses vues en une seule fois. L'expression envoie de message peut vous sembler obscure, en fait dans la littérature sur la programmation orienté objet, on parle d'envoi de message pour parler d'appel de méthode. Dans notre implémentation, on utilisera la méthode changed qui appellera la méthode update des vues.

Le Modèle

Le Modèle à la responsabilité d'ajouter ses Vues à lui même. En fait la relation entre le Modèle et la Vue est un patron de conception Observateur. Le modèle est un Observable et les vues sont des Observateurs

La Vue

La vue a pour responsabilité l'affichage des données d'un modèle. Les vues ont un contrôleur dédié. La classe du contrôleur d'une vue est accessible via l'attribut default_controller_class. Le modèle est passé explicitement à la vue, par le constructeur. Lors de l'instanciation d'une vue, elle instancie son contrôleur dédié auquel elle passe le modèle

Les vues sont conçue pour être imbriquées les unes aux autres. Chaque vue peut contenir plusieurs sous-vues et ont une référence vers leur vue parente. Elle possède une méthode update pour se rafraîchir l'appel de cette méthode remet à jours les sous-vues

Le Contrôleur

Il gère les évènements utilisateurs est manipule le modèle. C'est ce qui lie la vue au modèle.

Dans notre exemple, on va simplifier pour mettre en avant les avantages du MVC, de ce fait, on va faire plusieurs modifications - Le contrôleur ne récupérera pas réellement des événements, mais lira l'entré standard. - Les Vues ne seront pas imbriquable, de toute façon, il y en aura qu'une seule.

Le fichier mvc.py définis les trois classes de base et le fichier mvc_exemple.py hérite de ces classes pour mettre en place un compteur. Le modèle du compteur est garant de la logique, c'est-à-dire que le conteur peut être incrémenté d'un à un et lorsque l'on est à 9, il retourne à 0.

class Model:
    def __init__(self):
        self.views = []

    def _changed(self, value):
        for view in self.views:
            view.update(value)


class Controller:
    def __init__(self, model):
        self.model = model

    def listen_user_event(self):
        ...


class View:
    default_controller_class = Controller

    def __init__(self, model):
        self.model = model
        model.views.append(self)
        self.controller = self.default_controller_class(model)

    def update(self, value):
        ...

from mvc import Model, Controller, View


class CounterModel(Model):
    def __init__(self):
        super().__init__()
        self.value = 0

    def incr(self):
        self.value += 1
        if self.value > 9:
             self.value = 0
        self._changed(self.value)


class CounterController(Controller):

    def listen_user_event(self):
        value = 1
        while value:
            for _ in range(value):
                self.model.incr()
            value = int(input('Ajouter un chiffre au compteur : '))


class CounterView(View):
    default_controller_class = CounterController

    digits = ("zero", "un", "deux", "trois",
              "quatre", "cinq", "six",
              "sept", "huit", "neuf")

    def update(self, value):
        print("Compteur:", self.digits[value])


model = CounterModel()
view = CounterView(model)
view.controller.listen_user_event()

Le gros avantage, du MVC, c'est que si demain, je dois afficher la vue autrement, cela ne remettra pas en question les autres composant. Si je change de machine pour une machine qui n'a pas de touche numérique, je peux changer le contrôleur pour qu'il modifie le modèle lorsque la touche haut est enfoncée. Cela ne remettra pas en question les autres composant. De plus, j'ai la possibilité de faire écouter un même modèle par plusieurs vues comme ceci cool

    model = CounterModel()
    view_1 = CounterView(model)
    view_2 = CounterView(model)
    view_2.digits = ("null", "ein", "zwei", "drei",
                     "vier", "fünf", "sechs", "sieben",
                     "acht", "neun")
    view_2.controller = view_1.controller
    view_1.controller.listen_user_event()

Si le modèle change, cela peut impacter la vue et le contrôleur, mais cela doit être vu comme une fatalité et non un problème qui doit être résolu. En effet si le modèle doit changer, cela veut dire que le logique métier a changé ce n'est donc pas choquant que tout puisse changer. Par analogie, sur un grille-pain, je dois pouvoir changer le design sans changer le mécanisme. Par contre si demain, je fais des gaufres à la place du pain griller, tout change.

Bon, il est temps d'avancer un peu dans le temps ! laughing

Le web et le MVC

Les années passent et le web se développe d'abord statique puis dynamique, on a de plus en plus d'interactions entre les données coté serveur et les pages affichées par le navigateur. Il faut mettre en place la stratégie MVC dans le web.

Si l'on regarde rapidement, les vues seront les pages HTML affichées par le navigateur. Elles génèrent des évènements via l'envoi de requêtes HTTP POST et GET lorsque l'utilisateur clique sur des liens ou envoie des formulaires. Côté serveur, on aura les contrôleurs et les modèles.

Sauf que quand on regarde de plus près, un problème se pose, on voie mal comment le modèle va notifier la vue d'un changement, c'est dû à la nature du protocole HTTP. Le serveur web ne peut pas envoyer une Requête au navigateur pour lui dire de rafraîchir la vue. C'est le navigateur qui doit demander.

Sun sort le MVC modèle 2

Le monde Java est le premier à tenter l'adaptation sur des serveurs d'applications. Les serveurs d'applications sont chargés de recevoir des requêtes HTTP et de fournir ces requêtes en fonction de l'URL demandée à une classe Servlet. Les JSP sortie en 1998 sont des gabaris dans lesquelles on définie des pages HTML dans lequel ce glisse des instructions en Java c'est une technologie parfaite pour faire les vues. Les JSP sont ensuite compilées en Servlet.

Sun propose deux types d'architecture le modèle 1 et le modèle 2 undecided

Dans la première, une JSP fait office de contrôleur en étant lié à une URL. La JSP va chercher elle-même ces données pour s'afficher auprès du modèle.

Dans la seconde, il n'y a qu'un seul contrôleur, qui est implémente par un servelet. Ce contrôleur va instancier le modèle. JSP est utilisé pour afficher les modèles que le contrôleur fournit. Le contrôleur à aussi la charge de sélectionner la bonne JSP en fonction de la requête reçue.

Le gros avantage du modèle 2, c'est qu'il allège les vues de le logique métier en les rendants moins dépendantes du modèle. Il permet aussi de centraliser les URL.

Ainsi, le modèle 1 sera également connu sous le nom de Component-based ou pull-based et le modèle 2 sous le nom de push-based ou Action-base, on verra également apparaitre le terme MVC2 dû à l'abréviation de MVC modèle 2. Voilà pourquoi on parle de MVC pour les frameworks web qui ont une architecture modèle 2, mais comme on peut le voir, ce n'est plus vraiment du MVC.

Dans le futur, les WebSocket pourraient changer la donne, en effet comme elle permette une communication asynchrone entre le serveur et le client, la vue pourrait de nouveau être notifiée par le modèle en cas de changement. wink

Sur ce, si vous voulez en savoir plus, je vous laisse les clés de la Delorean pour consulter cet article d'InformIT

A vos IDE et bon code smile