Quel est le meilleur framework MVVM et faut-il écrire son propre framework ?

Quel framework MVVM choisir pour un nouveau projet ? Cette question revient assez souvent sur les différents groupes Facebook des communautés de développeurs XAML. Prism, Mvvm Light et beaucoup d’autres font souvent débat… Personnellement, je vais peut être vous surprendre mais depuis que je me suis penché avec Thomas sur la question d’MVVM pour notre livre sur le sujet, je part souvent sur un framework MVVM développé à la main.

 

Quel framework choisir ?

Bien sûr, c’est la question que je me pose à chaque nouveau projet : utiliser son propre framework ou en utiliser un existant?

Cela dépend de chaque projet et au final, le choix sera plus au niveau du “contexte projet” que de la “technique”. Il arrive en effet assez souvent que nous choissisions sur un framework “connu” afin de faciliter le transfert de compétences avec nos clients ou pour utiliser un framework qu’ils connaissent déjà sur d’autres projets plutôt que parcequ’il propose quelque chose d’unique.

Pour moi, un framework MVVM est un outil qui va faciliter notre développement et apporter notamment une structure à votre code, une façon de faire commune à tous les développeurs du projet. Le design pattern MVVM est une théorie et le framework est une “implémentation” de celle-ci.

 

Pourquoi utiliser son propre framework ?

Devons-nous réinventer la roue ? Non, bien sûr que non mais certaines fois il est intéressant d’avoir sa propre implémentation que l’on peut modifier à souhait.

 

Arguments pour :

  • Plus de souplesse: quelque chose ne vous convient pas ? Modifiez-le! Vous voulez faire quelquechose pas tout à fait respectueux du pattern MVVM car une contrainte technique vous l’impose : pas de soucis !
  • Vous êtes libre de votre architecture et de votre implémentation. Certains frameworks imposent leur façon de faire. Si vous écrivez vous même votre code, vous choissisez ce qu’il vous convient le mieux!
  • On n’ajoute que les composants dont l'on a réellement  besoin et il n’y a pas de composants qui viennent “parasiter” notre code.
  • Vous possédez le code. Cela est rarement le cas mais pas de problèmes de licence si vous écrivez vous même le code.
  • Pas de problèmes de maintenance ou de montée en version. Certains frameworks ne suivent pas tout à faire en temps –réél les nouveaux frameworks. Avec votre propre framework, vous le faites dès que vous en avez besoin.
  • Il n’y a plus de “composants magiques” puisque le code source est disponible. C’est donc plus simple de comprendre le comportement que peuvent avoir vos composants.

 

Arguments contre :

  • Il faut réinventer la roue : Les composants dont vous avez besoin sont à réécrire. Bien sûr, au fil du temps vous commencerez à avoir votre propre base de code et que des copier-coller à faire.
  • Entrée sur le projet plus longue : un nouveau venu sur le projet doit comprendre votre framework et il n’aura pas forcément de tutoriaux sur internet pour l’aider.
  • Maintenance à votre charge : c’est à vous de maintenir votre framework et de connaitre la plateforme et ses différentes évolutions.
  • Il faut bien maitriser le pattern MVVM : vous êtes en roue-libre et il est facile de s’écarter du pattern MVVM :)

 

Comment implémenter les fonctionnalités “classiques”

Souvent le débat tourne autour de quelques fonctionnalités liée au pattern MVVM.

J’aimerais ici vous expliquer comment j’y réponds techniquement et je l’espère simplement.

S’il en manque, parlez en dans les commentaires !

Navigation

La navigation est pour moi quelque chose de très lié à la partie “vue” d’une application. Souvent la difficulté est que c’est les view models qui doivent la piloter.

Pour répondre à cette problématique, j’ai pour habitude de faire un service de navigation qui expose les différentes méthodes de navigation. Il y a alors une méthode par “page” et même dès fois plusieurs méthodes par page en fonction des contextes que l’on souhaite lui passer. Je trouve que cela a ces avantages :

  • Les ViewModels ne connaissent pas l’implémentation de votre service de navigation : couplage faible = cool !
  • L’exposition d’un jeu “limité” de méthodes avec des paramètres fixés permet de figer le passage de paramètres. Cela facilite la maintenance et cela permet de mieux savoir d’où les navigations vers une page sont déclenchées car on passe toujours par ce point d’entrée.

 

Voici un exemple de code :

public class NavigationService : INavigationService
{

    public class NavParamNames
    {
        public static string IsUserLovingPink = "IsUserLovingPink";
    }

    public void NavigateToHomePage(bool IsUserLovingPink)
    {
        var parameter = string.Format("{0}={1}", NavParamNames.IsUserLovingPink, IsUserLovingPink);
        App.RootFrame.Navigate(typeof(BlankPage1), parameter);
    }
}

 

Design Time

J’adore cette fonctionnalité, cela nous fait gagner un temps fou pendant l’intégration du design. Pour le faire dans son propre framework c’est relativement simple en réalité.

Voici un extrait de mon ViewModel de base :

 public ViewModelBase()
 {
     if (DesignMode.DesignModeEnabled)
     {
         GenerateDesignData();
     }
 }

 protected virtual void GenerateDesignData()
 {

 }

Oui… je ne passe pas par Blend pour me générer un fichier XAML de données de design time. Dans chacun de mes ViewModels, je vais pouvoir overrider la méthode GenerateDesignData et écrire du code pour me générer des données de design. Cette partie de code ne sera bien sûr executée que si le ViewModel est utilisé dans un designer. Cela reste aussi compatible avec Blend.

C’est un peu plus contraignant mais je trouve cela intéressant de se forcer à avoir des données à jour lorsque je fais évoluer mon ViewModel. De plus même un développeur ne connaissant pas Blend saura mettre à jour du code C# pour avoir des données de design time.

 

Dans mon XAML, je n’ai rien de particulier à faire si ce n’est déclarer mon ViewModel comme DataContext!

<Page
    x:Class="AppDemoMVVM.BlankPage1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AppDemoMVVM"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.DataContext>
        <local:MainViewModel />
    </Page.DataContext>
</Page>

Il y a aussi le cas des DataTemplates ne connaissant pas “leur ViewModel” et pour cela j’utilise le prefixe “d” de cette manière (coucou Michael) :

<DataTemplate x:Key="MonDataTemplate">
    <Grid>
        <d:Grid.DataContext>
            <local:ViewModelChild />
        </d:Grid.DataContext>
    </Grid>
</DataTemplate>

 

Messages à afficher à l’utilisateur ?

De la même façon que pour la navigation, je préconise l’utilisation d’un service de messagerie implémentant  souvent une interface très simple avec quelques méthodes.
L’implémentation de ce service pourra elle sans problème accéder à la vue pour utiliser des contrôles en particulier ou utiliser tout simplement des MessageDialog.

 public class MessageService : IMessageService
 {
     public Task DisplayErrorAsync(string title, string description)
     {
         return new MessageDialog(title, description).ShowAsync().AsTask();
     }
 }

 

Conclusion

Je pourrais prendre le temps de vous montrer des idées d’implémentations pour chaque composant nécessaire dans l’implémentation du pattern MVVM mais cela n’est pas le but de l’article.

Le message que j’aimerais faire passer c’est qu’il n’y a pas forcément un Framework MVVM mieux que les autres et qu’il est même parfois facile d’utiliser son propre framework. Dans chaque cas, il faudra étudier les pours et les contres pour choisir ce qu’il y a de plus adapté et ne pas avoir d’apriori sur un framework.

 

L’important c’est de respecter cette recette de cuisine qui fait que chaque développeur connaissant le pattern si retrouvera.

 

Bon code !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus