|
Model / View / Controler (MVC)
Crée le : 17/12/2010
|
Modifié le : 27/01/2011
|
Par : Proteus
|
Vue : 169
|
Commentaire(s) : 0
|
|
Introduction Lorsque vous avez une application qui possède plusieurs interfaces utilisateur, vous vous heurtez à différents problèmes. Maintenance, Communication, Lisibilité, Séparation du code. Le Design Pattern MVC est là pour aider le développeur à mettre en place des couches de codes qui permettent de trouver des solutions à ces problèmes. Prenons un exemple simple vous avez 3 vues qui vous renvoient certaines informations. Ces informations proviennent de la même table sur la même base de données. Si vous êtes dans un schéma standard et que vous effectuez une modification de votre table, vous n’aurez pas de modification de vos IHM (Interfaces) tant que vous n’aurez pas rechargé votre application. L’implémentation du modèle MVC permet de déclencher des méthodes définit dans une interface pour des vues qui se sont enregistrées dans une liste de client à informer. MVC est un pattern composé. Il est composé du design Pattern Observer (qui permet de provoquer l’update des vues à la disposition du Modèle) et le Design Pattern Stratégie implémenté dans le modèle en cas de nécessité (il permet d’implémenter une notion d’objet avec un couplage faible afin de ne pas tomber dans les limites de l’Héritage). Il a plusieurs objectifs :
Comme vous le verrez tout au long de ce tutorial, l’implémentation de MVC dans vos applications permet de la séparer votre code en plusieurs couches. Vous vous rendrez compte par la suite que la maintenance d’une application sous ce modèle est nettement plus aisé. Je suis conscient qu’il existe, sur la toile, un certain nombre de sites qui traitent du sujet. Mais il était important pour moi d’exposer ici ma vision de MVC. Modèle Il contient toute la partie données et toute la logique d’accès à votre base de données. Ici cette séparation d’accès aux données permet de modifier votre base de données sans avoir à modifier la vue de votre application. Dans ce pattern le modèle a également pour but de déclencher la mise à jour des vues qui s’y sont abonnées. Il notifie les vues enregistrées pour qu’elles déclenchent une mise à jour de l’affichage, son rôle :
Contrôleur Il contient toute la logique métier. Cette classe a pour but de contrôler les données qui sont envoyées à votre modèle afin de s’assurer, par exemple, que les données correspondent bien aux attentes du modèle. Pour le développeur, la classe Contrôleur représente une grosse partie du travail de l’application. Le contrôleur n'effectue aucun traitement, il n'effectue qu'un travail d'analyse pour vérifier la qualité des données qu'il fournit au modèle, son rôle :
Vue / Vues Elles sont la représentation graphique de votre application. Pour être sûr que vous ne faites pas d’erreur dans le codage de votre pattern, il vous suffit de partir du principe que la vue ne contient que très peu de ligne de code, elle ne doit contenir aucune logique mais simplement une représentation graphique des données que lui fourni votre contrôleur. Dans ce pattern vous devez également garder à l’esprit que votre vue ne demande pas sa propre mise à jour de données mais qu’elle est déclenchée par le Modèle, son rôle :
Comment ca marche ? Comme nous l’avons vu plus haut, la première chose que l’on doit faire c’est de créer pour notre exemple 1 vue (Winform), 1 classe Modèle et 1 classe Contrôleur. Une fois c’est trois classes en place. Nous pouvons entrer dans le vif du sujet. Maintenant vous savez que c’est le modèle qui doit déclencher une mise à jour de la vue. Pour effectuer cet appel notre vue doit implémenter une méthode que nous allons créer dans une interface. En utilisant le système d’héritage, nous allons hériter toutes nos vues de cette interface. Afin de faire cela proprement nous allons créer une Interface que nous allons appeler « IView » dont le code sera le suivant : « MVC\Interfaces\IViews.cs » using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MVC.Interfaces
{
public interface IViews
{
void Update();
}
}
Coté Modèle, dans notre exemple, nous allons juste simuler une fausse base de données déjà chargées. « MVC\Models\Model.cs » using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using MVC.Interfaces;
namespace MVC.Models
{
public class Model
{
#region Variables
private static Model instance;
private ObservableCollection stringCollection = new ObservableCollection();
private ObservableCollection viewCollection = new ObservableCollection();
#endregion
#region Proprietes
public static Model Instance
{
get
{
if (instance == null)
instance = new Model();
return instance;
}
}
public ObservableCollection StringCollection
{
get { return stringCollection; }
set { stringCollection = value; }
}
#endregion
#region Constructeurs
public Model()
{
stringCollection.Add("Ligne 1");
stringCollection.Add("Ligne 2");
stringCollection.Add("Ligne 3");
}
#endregion
#region Methodes
#region Private
private void UpdateView()
{
foreach (IViews View in viewCollection)
View.Update();
}
#endregion
#region Public
public void Add(string Value)
{
StringCollection.Add(Value);
UpdateView();
}
public bool Suscribe(IViews view)
{
if (!viewCollection.Contains(view))
return false;
viewCollection.Add(view);
return true;
}
public bool UnSuscribe(IViews view)
{
if (!viewCollection.Contains(view))
return false;
viewCollection.Remove(view);
return true;
}
#endregion
#endregion
}
}
Alors ici il y a plusieurs choses qu’il convient d’expliquer les Variables, il y en a trois :
Le Constructeur : dans notre classe il est privé, pour qu’on ne puisse l’instancier que par sa propriété Static. Dans le constructeur, nous avons un chargement de données dans notre variable data. Les Méthodes :
Coté Contrôleur, il faut mettre en place la stratégie de contrôle qui va contrôler les données avant de demander au modèle d’effectuer une mise à jour des données. « MVC\Controllers\Control.cs » using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MVC.Controllers
{
public class Control
{
#region Constructeurs
public Control() { }
#endregion
#region Methodes
#region Private
private bool CheckData(string ValueString)
{
if (ValueString.Contains("123"))
return true;
return false;
}
#endregion
#region Public
public bool AddData(string ValueString)
{
if (!CheckData(ValueString))
return false;
Models.Model.Instance.StringCollection.Add(ValueString);
return true;
}
#endregion
#endregion
}
}
Ici on effectue simplement un contrôle de la donnée avant de demander au modèle de l’ajouter dans la base. Et enfin la Vue, qui va être l’interface utilisateur et qui va afficher les données et surtout qui va implémenter l’interface IView. « MVC\Views\MainWindow.xaml.cs » using System.Windows;
using MVC.Interfaces;
namespace MVC.Views
{
public partial class MainWindow : Window, IViews
{
#region Variables
private Controllers.Control controller = new Controllers.Control();
#endregion
#region Proprietes
public Controllers.Control Controller
{
get { return controller; }
set { controller = value; }
}
#endregion
#region Constructeurs
public MainWindow()
{
InitializeComponent();
}
#endregion
#region Methodes
private void CommandButtonAdd_Click(object sender, RoutedEventArgs e)
{
bool result = Controller.AddData(TextBoxValue.Text);
if (!result)
MessageBox.Show("Rejet de votre valeur", "Check Data", MessageBoxButton.OK, MessageBoxImage.Error);
TextBoxValue.Text = "";
}
public void Update()
{
ListBoxData.ItemsSource = Models.Model.Instance.StringCollection;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Models.Model.Instance.Suscribe(this);
Update();
}
private void Window_Closed(object sender, System.EventArgs e)
{
Models.Model.Instance.UnSuscribe(this);
}
#endregion
}
}
Comme pour le modèle il faut ici expliquer les différentes lignes de codes :
Conclusion Le design pattern MVC est un « must » dans les patterns de conception à connaître. En l’implémentant vous résoudrez un grand nombre de problèmes auxquels vous pourriez vous heurter pendant votre phase de développement. J’espère que l’exemple évoqué ici était suffisamment clair, dans le cas contraire n’hésitez pas a me contacter pour plus d’information. |
||||