Dot.Blog

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

Un « projet zéro » MAUI réaliste partie 1/5 – Création du projet et MVVM

Faire un Hello World c’est sympa, mais faire un tour plus réaliste incluant le testing et le reste c’est encore plus sympa ! Suivez-moi pour une série / cours de 5 papiers autour d’une App, de A à Z

Plus loin qu’un Hello World

Au début de cette saga sur MAUI je vous ai montré l’inévitable Hello World (ref papier #3 23/9/22), il fallait bien se mettre en jambes. Mais si on allait un peu plus loin ? Par exemple en voyant tous les aspects d’une App réelle, mais tout en restant simple.


Un cours presque complet. Il ne sera pas possible de tout voir en détail, mais cette série en 5 épisodes est en réalité un mini cours plutôt complet qui abordera tous les aspects essentiels de la création d’un projet MAUI réaliste. MVVM, l’injection de dépendance, les tests unitaires, etc, nous verrons tout cela et bien plus encore. Alors accrochez vos ceintures, on décolle !

Le projet de base

Le point de départ de notre saga est bien entendu la création d’un projet MAUI utilisant le template par défaut fourni par Microsoft. Pour cela pas de redite inutile je vous renvoie aux articles précédents ainsi qu’à celui consacré à l’Hello World, on ne va pas le refaire ici, c’est quelque chose d’acquis. Je renvoie ainsi ceux qui aurait loupé cet épisode au papier du Hello World.



Passer la vitesse supérieure

Bon, nous avons notre projet de base mais c’est assez peu réaliste, il marche, il fait des choses (le compteur qui s’incrémente) mais il ne respecte pas les bonnes pratiques et est trop simple pour prétendre être un Hello World véritablement sérieux.

Il nous manque plein de choses. Mais on va garder un code ultra simple pour chacune. C’est plutôt la structure générale et les bonnes pratiques que nous allons voir pour créer un « projet zéro ». Par exemple il nous manque tout ce qui concerne MVVM, ou bien le Unit Testing. Bref ce qui est nécessaire pour se rapprocher un peu plus d’une véritable App MAUI. Je ne vous parlerai pas de tout à la fois, bien d’autres articles viendront compléter ce premier pas, déjà ceux de la série lancée aujourd’hui de 5 billets, puis tous ceux à venir et même tous ceux déjà existant !

MVVM

Je parlais de MVVM à l’instant et de papiers déjà écrits… coïncidence (ou pas) j’en ai écrit plein sur ce sujet notamment les récents sur le Microsoft MVVM Toolkit (série en 5 parties) et beaucoup d’autres avant traitant de ce sujet, et même de la comparaison entre MVVM et MVU dont vous avez peut-être entendu parlé dans le cadre de MAUI… Tous ces articles sont tagués MVVM dans Dot.Blog et pour en voir toute la liste il suffit de cliquer sur ce lien https://www.e-naxos.com/Blog/?tag=/mvvm .

Pour les paresseux qui ne veulent pas tout reprendre à zéro (il a tout de même environ 70 articles dans Dot.Blog tagués MVVM !!!) voici en quelques mots de quoi il s’agit :

Dans une App bien écrite nous devons séparer notre code pour améliorer la maintenance et les tests (plus d'informations sur les tests dans cette série de 5 articles). Un pattern très utilisé dans le monde C#/XAML est MVVM né à l’époque de WPF et qui a connu des tas d’implémentations différentes dans des Toolkits célèbres comme Mvvm Light, Caliburn, Prism et bien d’autres. Ce pattern assez proche de Model-View-Controller (MVC), et qui signifie Model-View-ViewModel, nous dit que :

  • Le Modèle (Model, le premier M de MVVM) contient nos informations brutes sur le domaine qui peuvent provenir de diverses sources de données et nos règles métier. 
  • Le ViewModel (le second V et le dernier M de MVVM) récupère généralement le Modèle via un service pour assurer encore plus l’isolation du code. Le ViewModel prépare ensuite les informations à afficher et réagit aux commandes de l’utilisateur qui lui sont passées par la Vue. Il contient donc la « glu » entre le Modèle et la Vue, c’est-à-dire la gestion des flux de données entre ces deux pôles et celle des interactions avec l’utilisateur.
  • La Vue (View, le premier V de MVVM) affiche ce qui se trouve dans le ViewModel et transmet les interactions de l’utilisateur à ce dernier.

La séparation des préoccupations ici est que

  • La Vue ne sait pas comment le ViewModel obtient ses informations.
  • Le ViewModel ne sait pas comment le Model obtient ses informations.
  • Le ViewModel ne sait pas quelle Vue lui est connectée.
  • La Vue ne peut pas contenir de code ni de règles métier. Elle ne peut contenir que du code lié à l’UI.
  • Le ViewModel ni le Modèle ne peuvent intervenir sur l’UI.

Cela nous permet d'apporter des modifications de code à la Vue, au ViewModel et au Modèle de façon indépendante autorisant des équipes différentes à travailler sur chacune de ces parties sans risque de bogues et cela facilite grandement le Unit Testing de chaque partie. 

Au départ l’idée était surtout de séparer la partie UI de la partie code proprement dit, donc d’un côté des graphistes construisant l’UI et de l’autre des développeurs créant le code. Naissait un nouveau métier, Intégrateur, un développeur un minimum doué pour l’UI qui s’occupait de brancher tout cela. C’était un schéma idyllique jamais appliqué dans la réalité en raison du profil incongru de l’Intégrateur (qui dit rare dit cher et les patrons n’aiment pas ça…). Mais des débuts de MVVM il nous reste surtout aujourd’hui l’idée principale d’un couplage lâche. Ce dernier concernant autant le code que les Vues, les ViewModels, les Modèles, les Services, etc.

Un aspect important de MVVM est ainsi de savoir comment lier les champs de la Vue au ViewModel car le circuit de l’information n’est pas unidirectionnel. L'utilisateur interagit avec la vue, par exemple en cliquant sur un bouton pour incrémenter un compteur. Cela met à jour les données stockées dans le ViewModel (et éventuellement transmises au Modèle).

Cependant, nous pouvons également mettre à jour les valeurs par programmation directement dans le ViewModel, et nous voulons que ces valeurs s'affichent dans la vue. Il s'agit d'une liaison bidirectionnelle. Autre situation semblable : le Modèle peut changer (un SGBD, un capteur de smartphone…) et ce changement doit être reflété par la Vue. D’ailleurs dans sa version « souple » MVVM autorise une Vue à se connecter directement à un Modèle sans passer par un ViewModel s’il n’y a aucune interaction de l’utilisateur. Ce cas est très rare et bien entendu dans une App bien structurée toutes les Vues utilisent un ViewModel même s’il est vide (ce qui est exceptionnel donc).

Pour assurer ce découplage fort dans nos projets nous n’allons pas réinventer la roue à chaque fois. Et même au sein d’un même projet de nombreuses choses vont devenir répétitives. Pour cela XAML nous offre un système de liaison de données (Data Binding) puissant. Mais ce n’est pas assez pour assurer une couverture totale de MVVM. Il nous faut ainsi un Toolkit qui va proposer tout le nécessaire. Il y a eu beaucoup de ces Toolkits dans l’histoire de XAML, celui que nous allons utiliser avec MAUI est le Microsoft MVVM Toolkit. Il a été conçu pour remplacer Mvvm Light qui était le plus utilisé, tout en le rendant plus performant et plus moderne (avec l’aide de son créateur qui a participé aux premiers pas du Toolkit Microsoft).

Bien entendu dans cette petite série de 5 billets pour réaliser un Hello World plus réaliste nous allons balayer plein de concepts comme MVVM, il n’est pas possible de détailler chacun. Même la séparation en 5 parties ne le permet pas. Je renvoie donc le lecteur aux articles déjà écrits sur le sujet, de façon générale ou spécifique (comme la présentation du Toolkit Microsoft).

Ajouter un ViewModel

Cette digression autour de MVVM nous amène en toute logique à l’ajout d’un ViewModel à notre App de base (celle créée au départ par le template de Visual Studio).

Que fait l’App pour le moment ? Pas grand-chose c’est certain, mais c’est un Hello World… Quand l’utilisateur clique sur le bouton, le compteur est incrémenté, ce que la Vue reflète.

Nota : le code source zippé sera diffusé avec l’épisode 3 ainsi que le 5.

Comment le fait-elle ? Mal ! Et doublement même ! D’une part la Vue connecte l’évènement du clic du bouton directement à son propre code behind (MainPage.xaml.cs), d’autre part ce code agit directement sur la Vue sans passer par un ViewModel. Mais ce n’est qu’un template.

Il nous faut avant toute autre chose casser ce couplage fort entre l’UI et le code, donc ajouter un ViewModel. Ce dernier va être construit avec les briques fournies par le Microsoft MVVM Toolkit.

Pour commencer il faut ajouter le paquet du Toolkit à notre projet.



On notera que le Microsoft.Toolkit.Mvvm, au départ isolé, a été intégré au Community Toolkit, toutefois il reste sous la forme d’un paquet séparé car chacun peut choisir d’utiliser un autre Toolkit MVVM sans pour autant se passer des services du Community Toolkit ni avoir deux Toolkits MVVM dans l’App dont l’un ne servirait pas…

C’est donc aujourd’hui le paquet CommunityToolkit.Mvvm qu’il faut ajouter au projet.

Vous savez ajouter un paquet à un projet, je vais vous laisser faire on gagnera un peu de temps.