SOMMAIRE

Envie d’aller plus loin ? Échangez directement avec l’un de nos experts.

De plus en plus, les utilisateurs souhaitent avoir des applications mobiles bourrées de fonctionnalités avec des dizaines d’écrans. Cependant, nous les développeurs, aimerions que le code reste simple à gérer. C’est pourquoi le choix de mettre en place une architecture MVVM (Model-View-ViewModel) pour une application mobile nous semble naturellement judicieux.

Le présent article, présente une implémentation de l’architecture MVVM pour une application mobile développée en .NET MAUI.

.NET MAUI : késako ?

.NET MAUI est un Framework fourni par Microsoft (disponible à partir de .NET6), multiplateforme conçu pour créer des applications natives sur iOS, Android et Windows à partir d’une seule base de code partagée. Il représente l’évolution de Xamarin.Forms.

Une application MAUI, est développée avec C# pour la partie logique et XAML pour la partie UI (User Interface).

XAML, ou eXtensible Application Markup Language, est un langage de balisage déclaratif utilisé principalement dans l’écosystème .NET pour définir l’interface utilisateur (UI) des applications, y compris celles développées avec .NET MAUI. Tout comme XML, XAML utilise une structure hiérarchique avec des balises, par exemple :<Button Content= »Cliquez ici » Width= »200″ Height= »50″/>.  Cette balise représente un bouton avec un texte, une largeur et une hauteur définies.

XAML est spécialement conçu pour décrire les éléments visuels, leurs propriétés, et la disposition des interfaces. Contrairement à XML, qui est un format générique pour structurer des données, XAML est spécifiquement orienté vers la création de vues et d’interfaces interactives, facilitant ainsi le lien entre l’UI et la logique métier dans les applications.

Qu’est-ce qu’une architecture MVVM ?

En général, l’expérience de développement .NET MAUI consiste à concevoir une interface utilisateur en XAML, puis à utiliser du code-behind pour gérer la logique de l’application. Le code-behind fait référence au fichier C# qui contient le code associé à une page XAML, permettant de répondre aux événements utilisateurs, comme les clics de boutons.

Cependant, à mesure que les applications s’agrandissent, la maintenance devient plus complexe. Par exemple, le lien étroit entre les contrôles de l’interface utilisateur et la logique métier peut augmenter le coût des modifications de l’interface et rendre les tests unitaires plus difficiles.

Le ViewModel est un concept d’architecture logiciel qu’on utilise dans la plupart des applications complexes pour garder un code simple. Il consiste à séparer la logique métier et la logique présentation d’une application de son interface utilisateur. Il offre la possibilité de résoudre de multiples problèmes de développement et de simplifier le test, la maintenance et l’évolution d’une application. Il permet également une amélioration significative des possibilités de réutilisation du code.

Le modèle MVVM se compose de trois éléments essentiels : le modèle (Model), la vue (View) et le modèle de vue (ViewModel). Chaque élément a un but différent. Le schéma suivant illustre les liens entre les trois éléments.

La View : contient le code qui permet de faire la présentation graphique de l’interface utilisateur.

Le Model : pour la gestion des données. Ainsi, le modèle peut être considéré comme une représentation du modèle de domaine de l’application, qui comprend généralement un modèle de données avec une logique métier et une logique de validation.

Les Views : doivent communiquer avec les ViewModels et donc ont le droit de les connaitre. Or, les objets du modèle ne doivent pas connaitre les vues. Il doivent donc trouver un moyen d’envoyer des signaux pour que les vues soient capables de se rafraichir. Cette règle permet d’avoir plusieurs vues indépendantes les unes des autres et qui utilisent les mêmes objets du modèle. A ce stade-là, si on contente de faire cette séparation ce qui marche déjà très bien, au bout d’un moment on risque de créer des vues un peu intelligentes avec beaucoup de code difficile à maintenir. Il va falloir donc trouver un moyen d’extraire le peu d’intelligence qu’on avait tendance à mettre dans la vue et de le mettre ailleurs. C’est à ce moment qu’on ajoute un nouvel élément (classe) associé à la vue. Cet élément contient un code neutre et agit comme un mini-contrôleur dédié.

Lorsque la vue doit effectuer une action, comme afficher des textes, elle consulte ce mini-contrôleur. Ce dernier se charge de récupérer les informations dans le modèle et de les rendre disponibles pour la vue.

La vue va aussi surveiller son contrôleur pour être capable, dès qu’il y a une modification des données qui se passe au niveau du contrôleur, de se rafraichir. Avec cette implémentation, on va donc pouvoir enlever toute intelligence de la vue et que celle-ci reste la plus « bête » possible. En terme de dénomination, ce « petit contrôleur associé à la vue », on l’appelle ViewModel.

Exemple d’application de l’architecture MVVM pour une application .NET MAUI.

Prenons un exemple très simple, on veut développer une application avec une seule page de login. Mais avant de commencer le développement, voyons voir la structuration d’un projet .NET MAUI qui respecte l’architecture MVVM avec Visual Studio et .NET 7.

  • Dans le dossier ‘’Models’’, nous allons créer une classe ‘’User’’ qui va contenir les informations nécessaires pour qu’un utilisateur puisse se connecter à l’application, à savoir : UserName et Password.
  • Les classes de modèle sont généralement utilisées conjointement avec des services. Ainsi, nous allons ajouter un dossier Services dans le projet où nous créerons un fichier ‘’UserService’’. C’est dans ce service que nous implémenterons la logique d’authentification.
  • Dans le dossier Views, nous allons créer un fichier ‘’LoginView’’ (ContentPage) qui correspond à la vue et qui va contenir le code XAML de toute la partie graphique et communique avec son ViewModel avec ce qu’on appelle Data Binding (cf. paragraphe suivant).
  • Dans le répertoire ViewModels, nous allons créer une classe ‘’LoginViewModel’’ qui concrétise le ViewModel qui va gérer toute l’intelligence de la partie graphique.

Voici à quoi ressemble la structure finale de notre future application :

Connexion entre le ViewModel et la View

Chaque View possède une propriété appelée BindingContext. Le BindingContext désigne le contexte de données auquel la vue se lie, généralement un ViewModel, ce qui permet à la vue d’accéder aux propriétés et aux commandes définies dans ce ViewModel via ce qu’on appelle Data-Binding.

Le data-binding est un mécanisme qui permet de lier automatiquement les propriétés des objets de la View aux propriétés des objets du ViewModel. Cela facilite la synchronisation des données entre l’interface utilisateur et la logique métier sans avoir à écrire de code pour chaque mise à jour. Dans le cadre de l’architecture MVVM avec .NET MAUI, plusieurs types de data binding peuvent être utilisés :

  • One-Way Binding (liaison unidirectionnelle) : les modifications dans le ViewModel se répercutent automatiquement sur la View.
  • Two-Way Binding (liaison bidirectionnelle) : les modifications dans la View et le ViewModel sont synchronisées dans les deux sens. Ce type est souvent utilisé pour les contrôles interactifs, comme les champs de saisie.
  • One-Time Binding (liaison unique) : les données sont liées une seule fois lors de l’initialisation et ne changent pas, même si le ViewModel est mis à jour.
  • Default Binding (liaison par défaut) : le type de liaison utilisé dépend du contrôle ou de la propriété cible dans la View.

Ces différentes options permettent de répondre à des besoins variés tout en respectant les principes de séparation des préoccupations propres à l’architecture MVVM.

La copie d’écran suivante illustre comment on peut associer la vue graphique de login à son ViewModel de type LoginViewModel :

Avec la déclaration entourée en rouge dans la code XAML de la page LoginView, on crée une liaison entre l’interface utilisateur LoginView et le ViewModel LoginViewModel. Ainsi, les champs d’entrés pour la saisie du username et du password sont respectivement liés (binded) aux propriétés ‘’Username’’ et ‘’Password’’ qu’on a définies dans LoginViewModel.

L’action ‘’clique’’ sur le bouton ‘’Login’’ déclenche l’exécution d’une méthode définie également dans LoginViewModel.

Zoom sur la classe LoginViewModel

1- L’exemple d’implémentation du ViewModel ci-dessus, utilise le package NuGet .NET Community MVVM Toolkit (cf. le premier lien dans la liste des références à la fin de cet article). Ce package, met à notre disposition la classe ‘’ObservableObject’’ qui est destiné à être utilisé comme base de nos objets ViewModel ou tout objet qui doit déclencher des notifications de modification.

2- Le package Community MVVM Toolkit fournit également l’attribut ‘’ObservableProperty’’ qui s’applique aux champs dans les objets qui héritent de ObservableObject et qui permet de générer des propriétés observables à partir de champs annotés.

3- ‘’RelayCommand’’ est un attribut qui permet de générer des propriétés de commande de relais pour des méthodes annotées. Les méthodes annotées avec cet attribut seront déclenchées par des contrôles graphiques dans l’interface utilisateur (par exemple : un clique sur un bouton ou sur un élément dans une collection).

On peut très bien choisir de ne pas utiliser le package NuGet Community MVVM Toolkit et opter pour l’implémentation de l’interface INotifyPropertyChanged, qui permet d’obtenir un fonctionnement similaire. Toutefois, cela entraînerait non seulement un code volumineux et difficile à maintenir, mais aussi une quantité significative de « boilerplate code », c’est-à-dire du code répétitif à travers les différents ViewModels. Cela peut rapidement rendre le projet lourd et complexe à gérer et à maintenir . La copie d’écran suivante présente l’implémentation de INotifyPropertyChanged :

Nous pouvons constater que l’utilisation package NuGet .NET Community MVVM Toolkit nous permet de simplifier considérablement notre ViewModel grâce aux générateurs de source. Les générateurs de source génèrent du code qui est additif à nos objets existants. Pour cette raison, tout objet utilisant un générateur de code devra être marqué comme partial.

Remarque :

L’implémentation traditionnelle de INotifyPropertyChanged utilise le mécanisme de réflexion qui est un processus coûteux en termes de performance, car il implique des vérifications au moment de l’exécution. Les générateurs de source, quant à eux, génèrent le code à la compilation, ce qui évite complètement la réflexion et améliore ainsi les performances de l’application.

La copie d’écran suivante, présente le résultat final de notre application

En conclusion

L’architecture MVVM permet de séparer la logique métier et la logique de présentation d’une application de son interface utilisateur (UI). Cette séparation permet de résoudre de nombreux problèmes de développement et de simplifier le test, la maintenance et l’évolution d’une application. Il offre également une amélioration significative des possibilités de réutilisation du code. De cette manière, il est plus aisé pour les développeurs et les concepteurs d’IU de collaborer lorsqu’ils développent leurs parties respectives d’une application.

Tandis que le package NuGet est un excellent moyen de normaliser et de simplifier notre code de ViewModel. Il offre d’excellentes implémentations de composants MVVM standard tels que ObservableObject et RelayCommand.

Envie d’aller plus loin à propos de l’architecture MVVM ?

‣ Fonctionnalités du kit de ressources MVVM

‣ Modèle-vue-vue modèle (MVVM)

‣ Qu’est-ce que .NET MAUI ?

Architecture Logicielle

Ne ratez plus aucune actualité avec la newsletter mensuelle de SoftFluent

Newsletter SoftFluent