A propos de MVC
By Geoffrey on Tuesday 13 September 2005, 19:01 - Coding - Permalink
Après mes aventures avec Flexy (cf billet précédent), et la lecture d'un thread particulièrement interressant sur sitepoint, j'ai pas mal réfléchi, et j'ai pondu un petit schéma explicatif sur le MVC, assorti de quelques explications sur les dénominations utilisée. Bon bien sur, c'est loin, IMHO, d'être parfait, mais j'espère que ça pourra aider quelques personnes à appréhender un peu mieux le concept de base du pattern MVC, et si par la même occasion vous pouviez me donner votre avis sur ma vision de la chose, et bien je n'aurai doublement pas perdu mon temps.

Description Générale
Bon donc, le but du MVC est de séparer une application en trois couches: le Model, le Controller, et la View. Très bien. La couche Model contient tout la logique d'accès aux données, la couche Controller contient la logique applicative (je crois bien que c'est ce qu'on appelle également la logique métier de l'application), et la couche View contient la logique d'affichage des données.
Dans le cas d'une application web standard, on peut assimiler le serveur web (apache par exemple) à une partie du Controller. En effet, le rôle du Controller consiste à analyser la requête de l'utilisateur et à demander l'execution de la tâche ad hoc. Dans la même veine, le navigateur (oui je veux bien ne pas dire browser, mais non je ne dirais pas butineur) peut être assimilé à une partie de la couche View, puisqu'il est le mécanisme qui assure le rendu de la page web finale.
On va continuer avec une brève description de chaque terme employé dans le schéma.
FrontController
Le FrontController reçoit la requête HTTP (notée HTTPRequest sur le schéma) et la passe au RequestHandler pour analyse.
Selon la réponse du RequestHandler, le FrontController décide de l'action à invoquer, puis execute une série de filtres (InterceptingFilter), avant d'executer l'action précédemment sélectionnée.
RequestHandler
Le RequestHandler reçoit la requête HTTP depuis le FrontController, l'analyse et retourne les informations utiles au FrontController.
Il peut être étendu pour gérer différents types de requêtes (XMLRPCRequestHandler par exemple).
InterceptingFilter
Les filtres d'interception encapsulent tout le traitement pré-métier: gestion de session et d'authentification par exemple.
Chaque filtre prend en argument le filtre suivant, qu'il executera une fois son traitement propre terminé, constituant ainsi une chaine de responsabilités (Chain of Responsability).
Action
L'object action encapsule tout le traitement métier. On en trouvera donc en règle générale une grande quantité de ces objets (UserAddAction, UserDelAction, etc).
L'Action peut faire appel à d'autres objets qui ne sont pas inclus dans le schéma pour des raisons de clarté.
En cas d'erreur dans le traitement, l'Action invoque un ErrorHandler.
Une fois le traitement terminé, l'Action invoque une vue.
ErrorHandler
Le gestionnaire d'erreur traite les erreurs qui lui sont passées par l'Action.
Une fois l'erreur traité, le gestionnaire d'erreur invoque une vue.
LogHandler
Exemple d'objet aidant le gestionnaire d'erreur, le LogHandler permet d'écrire les erreurs dans des fichiers journaux.
View
La vue (View) détermine les données renvoyées au client. Cela peut-être l'affichage d'une interface graphique (HTMLView, XULView, etc), mais aussi des données formatées (CSVView, XMLRPCResponseView).
La vue à utiliser est déterminée par l'Action, et reçoit ses données des objets de transfert (TransfertObject).
TransfertObject
Les objets de transfert sont de simples conteneurs d'informations. Ils reçoivent leurs informations des objets de données (DataObject) et les distribuent aux vues (View).
Leur utilité première est de maintenir la séparation entre la couche modèle (Model Layer) et la couche vue (View Layer): ils font le lien entre les deux sans contenir aucune logique métier.
DataAccessObject
L'objet d'accès aux données encapsule toute la logique d'accès aux données. Il peut être étendu pour utiliser d'autres sources de données que celle initialement prévue (IniDataAccessObject par exemple).
DataObject
Les objets de données encapsulent la logique de manipulations des données. Ils contiennent par exemple les actions CRUD (Create Read Update Delete).
Au final
Au final, ce pattern est plus simple que je ne l'appréhendais, disons que la majeure difficulté de l'apprentissage de la POO est, à mon sens, la terminologie spécifique employée. Une fois qu'on a saisi le sens des termes, c'est tout de suite plus clair.
Bon sinon, j'étais parti pour implémenter ce joli petit schéma, et puis je me suis rendu compte d'une chose à propos des filtres d'interception. A posteriori, je pense qu'ils auraient plus leur place dans la continuité du RequestHandler plutot que dans celle du FrontController. Pourquoi ? Et bien ces filtres sont, à priori, spécifique à un type de requête. Par exemple, on ne va pas gérer l'authentification d'un utilisateur de la même manière selon qu'on reçoit une requête HTTP standard ou (par exemple) une requête XMLRPC. Non ? Vous en pensez quoi vous ?
Comments
Par exemple, on ne va pas gérer l'authentification d'un utilisateur de la même manière selon qu'on reçoit une requête HTTP standard ou (par exemple) une requête XMLRPC. Non ? Vous en pensez quoi vous ?
Ben, si j'ai compris le chose (et c'est pas évident que ce soit le cas !), les objets sont indépendant les uns des autres... non, je m'exprime mal... ils sont dépendant, mais ils ne sont pas dépendant des données recues par les autres objets... hum, c'est guère plus clair.
bon, pour ta question, le protocole utiliser, la requete utilisée, etc... c'est du ressort du RequestHandler. Il traite tout ca et pouf, il répond au FrontController et, comme tu le dis dans ta présentation: "Selon la réponse du RequestHandler, le FrontController décide de l'action à invoquer"
Moi, je le vois comme ca: Je suis le FrontConrtoller, je me recois une requete en pleine tronche. Bon. Mon pote RequestHandler a l'air plus réveillé que moi, alors je lui soumet la requête. Il lit tout ca, le tourne dans tous les sens qu'il veut et me dit ce qu'il en pense. En fonction de sa réponse, ben je décide (pasque bon... c'est moi le chef quand meme !) de l'action à faire.
Alors?
Ton article est très intéressant, merci, il m'a fait comprendre pas mal de chose sur les MVC. Je suis en train de développer un CMS basé sur PHP5/PEAR/XML (depuis 1 an) qui fonctionne bien mais est complexe à mettre en oeuvre et devient complexe à faire évoluer car il s'est alourdit au fil du temps. Bref je vais développer la version 2 qui sera encore plus poussé au niveau de MVC et utilisera plus de package PEAR (j'espère), peut-être des packages pear made at home.
Un topic intéressant sur les MVC en PHP sur le forum de hardware.fr et mon post (en page 3) qui décrit plus mon projet. http://forum.hardware.fr/hardwarefr/Programmation/Model-View-Controller-Architecture-applications-PHP-sujet-77425-3.htm#t1213668 @+