Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

MAUI : MVU vs MVVM

En voilà un sujet qui va faire couler beaucoup d’encre ! MVU contre MVVM… Faisons le point !

MAUI

J’ai déjà commencé à en parler et cela va devenir le sujet principal je pense d’ici la fin d’année… Microsoft App UI, raccourcit en MAUI, est donc un système d’UI pour construire des Apps chez Microsoft. MAUI remplace les Xamarin.Forms et en reprend l’essentiel à part quelques namespaces qui changent et bien entendu l’organisation de la solution qui n’a plus qu’un seul projet pour gérer toutes les cibles natives à la fois. Voilà en gros, même en très gros, un résumé ultra rapide de ce qu’est MAUI pour ceux qui auraient passé le temps de la pandémie cachés dans une grotte.

J’aurai bien entendu l’occasion de revenir sur MAUI et ses principes de fonctionnement dès qu’il sera officiellement sorti et qu’il sera possible de faire des Apps en mode production avec le produit. Certains pourrait reprocher ce qui semble être de la frilosité de ma part. Il est vrai que je vous ai habitué à parler de tas de technos Microsoft bien avant leur sortie officielle. Alors pourquoi pas MAUI ? Simplement parce que je me suis rendu compte que mes lecteurs attendaient de moi de “l’utile tout de suite”, certes ils sont curieux et avides de savoir ce que sera la futur, d’où ce billet quelques autres, mais les articles qui marchent le mieux sont ceux qui répondent à de vrais besoins immédiats ou qui aident à comprendre des technos ou des concepts qui impactent leur travail quotidien. Pour MAUI j’ai donc préféré adopter le rythme de mes lecteurs, j’en parlerai (et beaucoup) une fois que tout le monde pourra l’utiliser sans risquer de mettre sa machine en vrac ou de déstabiliser son environnement de développement avec des béta pas toujours évidentes à désinstaller proprement (je l’ai vécu tant de fois que je sais de quoi je parle).

Mais que les plus pressés ne s’inquiètent pas, la sortie officielle est toujours prévue pour novembre 2021, c’est à dire dans quelques semaines…

MVVM vs MVU

Justement, voici un cas concret de concept pas très clair pour tout le monde qui mérite qu’on s’y arrête un peu. MVU c’est quoi ? Et quel rapport avec MVVM ?

Découpage architectural d’une App

Tous ces patterns ont pour objet d’organiser l’architecture d’une application. MVVM est une version “spéciale XAML” de patterns comme MVC ou MVP (Model-View-Controller et Model-View-Presentation). MVVM valant pour Model-View-ViewModel.

Le but est de découper l’architecture d’une application en bloc logiques assurant un ensemble de fonctions bien défini. Et cela pour clarifier l’écriture du code, le rendre plus facilement testable, etc. Je ne vais pas ici entrer trop dans les détails car j’ai écrit une masse d’articles et même de livres autour de MVVM. J’y renvois le lecteur soucieux de creuser la question.

La différence entre ces patterns est donc la façon de découper l’application, le nombre et la fonction de chaque “bloc”.

Aucune stratégie n’est meilleure que l’autre, fuyez ceux qui veulent vous le faire croire ! Ces patterns sont différents mais sont tous sérieux et utilisés tous les jours par des tonnes de développeurs dans le monde. Il se trouve juste que, par habitude souvent, par choix parfois, certains utilisent l’un ou l’autre de ces patterns. On retrouve ainsi MVC plus souvent en Java, l’habitude, la pression du “groupe” expliquent mieux cela qu’un choix délibéré et raisonné. De même MVVM s’est imposé sous XAML et tout le monde a suivi.

On peut bien entendu avoir des préférences, se sentir plus en résonnance avec l’un ou l’autre de ces patterns. On peut faire un choix conscient et volontaire d’en utiliser un plutôt qu’un autre. Tant que vous vous sentez en phase avec la logique sous-jacente d’un pattern alors la vie est belle, utilisez-le !

Donc tout cela n’est qu’une façon de découper une App. On peut même parler de découplage. Si le résultat de ces patterns est un découpage du code, l’une de leur motivation première est le découplage.

Découpler quoi ? En général il s’agit de découpler les différentes fonctions d’un code et de gérer les interactions entre celles-ci. L’affichage (la Vue), la partie chargée de gérer l’état d’une vue ou d’une partie de l’application, la notion de services, etc. On tombe alors sur des notions encore plus proche du code comme l’injection de dépendances, les commandes, etc.

Une fois qu’a posé cela, on sait maintenant, même de façon assez sommaire, à quoi servent ces patterns.

Deux d’entre elles vont nous intéresser plus particulièrement ici : MVVM et MVU.

MVVM

Model-View-ViewModel.

Comme je le soulignais plus haut j’ai écrit tellement sur ce pattern que je ne vais m’étendre de trop. C’est le pattern XAML par excellence, qui a donné d’ailleurs naissance à des tas de toolkits différents comme MvvmLight, Prism, Caliburn, FreshMvvm, TinyMvvm, et bien d’autres !

Mais pour cet article reposons juste les grandes bases sous la forme d’un schéma :

image

Comme on le voit, et comme son nom l’indique, MVVM découpe l’application en blocs, dont trois sont essentiels : les vues, les modèles et les VueModèles.

La Vue à pour rôle d’afficher l’UI et d’attendre les commandes données par l’utilisateur. Le VueModèle est là où se trouve le code qui va gérer la Vue, répondre à ses commandes, modifier son état qui sera reflété par la Vue notamment par l’utilisation du Binding XAML. Quant au Modèle son rôle est de gérer les data au sens large.

Le schéma montre les interactions entre les différents blocs. Bien entendu le couple Vue/VueModèle sera répété autant de fois qu’il existe de Vues dans l’App. Le ou les Modèles sont généralement communs.

Le but de MVVM est de matérialiser une séparation claire des rôles, rendre chaque partie testable isolément, faciliter la réutilisation du code et maintenir le code dans un état “sain” pour éviter une dette technique trop lourde.

MVVM a été conçu avec XAML et le Binding en tête, c’est ce qui le rend si particulier et surtout c’est ce qui explique qu’on ne retrouve pas ce pattern en Java ou autre plateforme de développement. La raison n’est pas que les autres développeurs n’aiment pas MVVM, c’est tout simplement qu’ils ne peuvent pas le mettre en œuvre car en son cœur il y a le Binding XAML, un aspect bien particulier propre à Microsoft.

La mise en œuvre pratique de MVVM fait que la Vue (ou les Vues) est écrite en XAML et qu’elle utilise du binding sur des propriétés publiques d’un VueModèle qui est écrit généralement en C# mais ce n’est pas une obligation. Il en va de même du reste de l’application comme les Modèles, les services etc.

MVU

Model-View-Update

Tel qu’on a posé le décor MVU est donc un pattern “concurrent” de MVVM, MVC, MVP… Ce n’est donc qu’une autre façon de découper l’application en différents blocs qui portent des noms semblables pour les deux premiers (Model et View). Mais le troisième élément n’est pas un bloc mais plutôt un mode de fonctionnement, Update.

Regardons le schéma suivant :

image

On semble avoir des choses proches, des vues, des modèles et un truc un peu bizarre, Update.

En réalité c’est tout qui est différent Smile Sauf la Vue éventuellement et encore…

Le principe de base de MVU est l’immutabilité. Rien ne peut avoir d’effet de bord sauf une commande. La Vue est écrite en C# ou autre dans un mode “fluent” où tout se suit avec des points de déclinaison. Alors là déjà c’est une grosse différence, pas de XAML toute l’UI est écrite à la main en code…

Le modèle est en première approximation l’équivalent du ViewModel en MVVM. Mais vraiment de loin par temps de brouillard… En effet, sous MVVM le ViewModel est une sorte de mini application à lui tout seul : il calcule, il modifie les données (via le Model), les interroge, prend des décisions, bref tout ce qu’on entend en général du travail d’un programme en informatique. Or sous MVU le Model ne sert qu’à une seule chose : préserver l’état courant de la Vue et offrir des commandes. Le modèle tourne autour de la notion de fonctions et non de procédures car l’immutabilité est la règle d’or.

Selon le schéma, si vous regardez attentivement, vous allez voir que rien n’est semblable à MVVM ici… La Vue écrite en code C# ou F# affiche les états exposés par le Modèle. Jusqu’ici ce n’est pas si éloigné. Mais lorsqu’une commande est exécutée c’est le bloc Update qui est invoqué. Ce qu’il va faire c’est exécuter la commande, ce qui risque de modifier l’état du Modèle et comme celui-ci n’est pas modifiable Update va retourner une nouvelle copie modifiée par la commande. Le Modèle étant une nouvelle instance la Vue va afficher les changements mais uniquement ce qui est différent, un peu comme le mode Hot Reload Xamarin.Forms en design time, mais là on parle bien du runtime…

Donc MVU est avant tout un choix philosophique, celui de l’immutabilité si chère aux langages fonctionnels comme F#. Ce pattern nous vient de Elm, une plateforme de développement fonctionnelle.

Ceci explique donc cela. La notion de fonction à la place de procédures, l’immutabilité comme idée fixe et centrale, l’utilisation de messages au lieu du binding XAML (et pour cause il n’y a pas de XAML en Elm ni dans MVU), et toutes ces petites bizarreries qui font que MVU semble étrange. C’est une étrangeté que le pattern tient du monde dans lequel il est né, le fonctionnel.

Alors MVVM ou MVU pour MAUI ?

Tout cela est bien joli, mais dans quelques semaines il va falloir se décider pour coder sous MAUI ! MVVM ou MVU ? That is the question !

En fait non, il n’y a pas question à mon avis.

Si vous souhaitez réutiliser votre code et votre savoir-faire Xamarin.Forms, WPF, UWP vous voudrez utiliser MAUI en mode XAML, c’est à dire en tant qu’évolution naturelle des Xamarin.Forms.

Si vous êtes un essayiste ou un convaincu des bienfaits de l’immutabilité et que vous êtes à l’aise avec les langages fonctionnels et que XAML n’est pas votre tasse de thé (et vous n’avez aucune expérience forte à porter non plus) dans ce cas optez pour MVU. C’est beau, clair et net et totalement adapté à l’esprit fonctionnel.

De fait il apparait qu’il n’y a pas vraiment de choix ni de question à se poser, les deux patterns et surtout ce qu’ils impliquent sont deux mondes différents réclamant une adhésion et une habitude à leurs fondements. XAML d’un côté, code C# ou F# uniquement de l’autre, logique découplage fort avec binding d’un côté, messages et immutabilité de l’autre, etc, les différences sont telles que la comparaison devient même difficile à justifier. On ne compare pas des choux et des lapins apprend-t-on en maths en primaire… Ici on a bien affaire à deux choses si différentes que les comparer ne fait pas sens. Tout simplement.

Conclusion

Il est assez facile de conclure aujourd’hui … Si vous vous inscrivez dans un historique, dans une réutilisation de votre savoir-faire Xamarin.Forms, vous continuerez d’utiliser MVVM sous MAUI c’est une évidence, le coût d’un changement ne se justifiera pas.

Si vous arrivez à MAUI depuis un autre horizon, Microsoft ou même de plus loin encore, alors il faudra trancher entre les avantages de XAML et de la programmation plus traditionnelle et ceux du “tout code”, de “l’esprit fonctionnel”, et de l’immutabilité. Vous utiliserez alors très certainement F# plutôt que C# pour être cohérent.

Deux situations, deux profils, deux patterns. Dans l’absolu tout le monde aura le choix, dans la pratique le choix n’existera pas…

La dernière question est de se demander malgré tout si les avantages de MVU, du fonctionnel et tout ça, si le jeu n’en faut pas la chandelle ? Si vous n’avez aucun code legacy Xamarin.Forms à faire vivre et à faire évoluer la question est légitime. Les langages fonctionnels ont des tas de choses intéressantes à proposer. Le principe de l’immutabilité est une pure merveille pour le debug et les tests. Certains feront peut-être ce choix “quoi qu’il en coûte”. Mais ils seront peu nombreux, j’en prends le pari !

D’ici là, plus longtemps à attendre pour la sortie officielle de MAUI et tout ce que j’aurai à dire à son propos ! Alors…

Stay Tuned!