Dévelopement

Prism pour Xamarin.Forms 7.0 releasé

Dot.Blog - sam, 20/01/2018 - 16:09

En ce début d’année (que je vous souhaite excellente bien entendu) voici une release attendue, Prism pour Xamarin.Forms 7.0. Elle apporte de nombreuses améliorations que je vous propose de découvrir…

Prism pour Xamarin.Forms

Inutile de vous faire perdre un temps précieux en présentations que j’ai déjà écrites dans les mois précédents à propos de ce toolkit MVVM indispensable. Je renvoie donc le lecteur intéressé à la liste des articles qui abordent le sujet notamment une série en 7 parties sur le toolkit lui-même.

.NET Standard

Cela était attendu depuis un moment, la bêta permettait déjà de se conformer à cette nouvelle utilisation de .NET mais c’est désormais releasé officiellement : Prism pour Xamarin.Forms supporte .NET Standard.

je ne vais pas là non plus vous en faire des tonnes sur ce que cela signifie et je renverrai là aussi le lecteur à mes articles sur .NET Standard pour en comprendre l’évident intérêt.

C’est en tout cas l’annonce la plus importante techniquement pour cette version 7.0 de Prism puisque comme vous le savez Visual Studio depuis peu de temps oblige à utiliser .NET Standard au lieu des PCL.

Nouveau Namespace pour l’IoC

Il était temps de simplifier et d’unifier tout cela… La version 7.0 offre une nouvelle API pour les conteneurs IoC qui est utilisée partout par le code du toolkit et qui s’offre aussi au développeur. L’un des gros avantages est que désormais la même API permet de traiter les conteneurs IoC dans Prism que cela soit sous UWP, WPF ou les Xamarin.Forms renforçant encore plus la portabilité du code entre les plateformes, associé au support de .NET Standard bientôt un même code identique pourra donc être utilisé sous toutes ces plateformes portant l’idée de l’universalité des Xamarin.Forms bien au-delà de leurs limites !

Les breaking changes

Certaines évolutions ne peuvent se faire sans un minimum de “casse”… Prism 7.0 en adoptant .NET Standard, en reformulant une API globale pour les conteneurs IoC et d’autres changements nécessaires n’échappe pas à la règle.

Bien entendu on retrouve ces “changements cassants” dans la sphère du conteneur IoC, forcément. Mais aussi l’API IModule, dans l’interface IPlatformInitializer, etc.

Autant dire qu’on ne prend pas un code écrit avec une ancienne version de Prism pour juste faire un update du package… On destinera la V7.0 aux nouveaux développements en laissant tranquilles ceux qui fonctionnent déjà avec les releases précédentes ! Toutefois les breaking changes sont localisés et bien documentés et il reste donc possible d’effectuer une mise à jour, mais en connaissance des effets…

Les améliorations

Bien que le but de la version 7 était principalement le support de .NET Standard et la clarification de l’API des conteneurs IoC elle s’accompagne de nouveautés qui ne sont pas sans intérêt.

On en retrouve dans le système de navigation notamment lorsqu’on navigue sur des onglets d’une page tabulée. C’est un cas de navigation un peu délicat à régler et les nouvelles solutions vont simplifier ce type de navigation.

Dans la même veine on trouve la génération automatique des tabulations et des pages tabulées lorsqu’on navigue vers une telle page.

La navigation a été au coeur des nouveautés et la possibilité de retirer une page de la pile de navigation a été ajoutée. Cela permet de répondre à certains scénarios (supprimer une page de login de l’historique une fois la personne identifiée par exemple).

Toujours au sein de la navigation il devient possible d’utiliser une navigation modale dans les liens profonds. S’il s’agit ici de scénarios déjà plus complexes il n’est pas si rare que cela de les rencontrer.

GoBackToRoot est une nouvelle fonction de la navigation, toujours elle !, qui permet comme son nom l’indique d’effacer toute la pile de navigation et de revenir à la page racine. Cela peut s’avérer très pratique.

Et pour terminer, sortons de la navigation pour une autre amélioration tout aussi essentielle : le support des propriétés complexes dans ObservesProperty ! C’est à dire qu’il devient possible d’observer la sous propriété d’une propriété (MaPropriété.SousPropriété.SousSousPropriété…). Cela simplifie encore plus ce merveilleux mécanisme que j’ai détaillé dans la série de 7 articles évoquée au début de cet article.

Conclusion

Comme toute release réellement importante il y a d’inévitables breaking changes à prendre en compte, mais le jeu en vaut la chandelle, Prism devient meilleur et tout le bénéfice va au développeur ! Il est vrai qu’au fil du temps cette mouture de Prism se complexifie un peu, MvvmLight sera certainement encore longtemps le moyen le plus simple de faire du MVVM pour ceux qui n’ont pas investi le temps nécessaire à la compréhension de Prism. Mais ne perdez pas de vue que sur de très nombreux points essentiels Prism va beaucoup plus loin que MvvmLight ou d’autres toolkit et que se passer d’un apprentissage ponctuel se reportera sur chaque instant perdu à chaque ligne de code du projet… Apprenez à vous servir de Prism, vous en tirerez rapidement avantage !

PS : J’en profite pour vous réitérer mes meilleurs voeux pour 2018 ! Comme disait le regretté Spock (Léonard Nimoy) : Live Long and Prosper !

Catégories: Dévelopement

Réduction de 30% jusqu’à ce soir sur le livre Xamarin.Forms !

Dot.Blog - lun, 08/01/2018 - 00:00

Ne ratez pas cette occasion avec le code BLUE3RTYde vous procurer mon livre sur les Xamarin.Forms ! Si vous l’avez déjà faites circuler l’info autour de vous

C’est LE livre sur les Xamarin.Forms en français, le 1er et le seul, tous les aspects sont abordés de la conception des UI bien entendu à la façon d’écrire des Apps qui respectent MVVM. Une référence indispensable pour qui veut se lancer dans le développement Mobile cross-plateforme en C#/XAML.

Son contenu est toujours et encore d’actualité et même plus que jamais et c’est le seul livre dont la mise à jour est permanente et gratuite via Dot.Blog !


Bonne Lecture !

Catégories: Dévelopement

Xamarin.Forms, Validation des données et Mvvm–Partie 2

Dot.Blog - mer, 22/11/2017 - 04:31

Après l’exposé du mécanisme de validation en partie 1 nous allons voir comment mettre en œuvre tout cela par code C#, XAML et en exploitant les effets natifs Android, iOS et UWP…

Résumé

Je renvoie bien entendu le lecteur à la Partie 1 pour comprendre de quoi je parle et voir l’animation en fin d’article qui montre tout cela en action. C’est tellement mieux de savoir où on va…

Rappel du principe

Le but du jeu consiste à valider des données saisies par l’utilisateur et ce d’une façon générique réutilisable facilement tout en offrant un retour visuel clair à l’utilisateur pour éviter ses frustrations et le guider sans qu’il n’ait à lire un manuel de 300 pages. Cela convoque de nombreuses compétences tant en C# qu’en XAML et qu’en injection de code natif pour chaque plateforme si l’on veut faire les choses correctement sur le plan visuel.

Rappel du fonctionnement

Le coeur du système de validation que je vous ai montré est basé sur une classe un peu spéciale qui contient à la fois la donnée à la valider (et à exposer à l’utilisateur) et less règles de validation. Le schéma était le suivant :


Maintenant que vous avez lu ou relu la partie 1, nous sommes prêt pour discuter de la mise en œuvre du système de validation…

Allez, parce que c’est vous, la petite animation de la partie 1 qui nous rappelle à quoi sert tout cela :

INPC

Partons de la base, le support de INPC. Comme je le disais dans la partie 1 la plupart des toolkits MVVM proposent une classe de base qui offre le support de INPC, vous pouvez utiliser cette classe si cela vous convient et que créer une dépendance forte entre votre code et une librairie externe ne vous fait pas peur ! Si demain vous transportez votre système de validation dans un autre projet qui n’utilise pas le même toolkit MVVM vous serez obligé de revoir une partie de votre code.

C’est pour cela que le mécanisme de validation sera basé sur une classe séparée du toolkit MVVM, SimpleObservableObject donc voici le code :

using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; namespace DataValidationDemo.Inpc { public class SimpleObservableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected virtual bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) return false; field = value; // ReSharper disable once ExplicitCallerInfoArgument OnPropertyChanged(propertyName); return true; } public void RaisePropertyChanged([CallerMemberName] string property = null) { // ReSharper disable once ExplicitCallerInfoArgument OnPropertyChanged(property); } } }


Comme on peut le constater c’est simple, mais pratique. La méthode Set<T> permet de modifier une propriété en testant la valeur précédente (pas de changement si égalité) tout en déclenchant INPC. Il n’est donc pas utile d’ajouter un appel à RaisePropertyChanged() sauf si on souhaite notifier une propriété en dehors de son setter.

ValidatableObject<T>

C’est le coeur du système de validation, et il n’est pas très gros :

using System.Collections.Generic; using System.Linq; using DataValidationDemo.Inpc; namespace DataValidationDemo.Validation { public class ValidatableObject<T> : SimpleObservableObject, IValidity { private List<string> errors = new List<string>(); private T innerValue; private bool isValid=true; public ValidatableObject(bool autoValidation) { AutoValidation = autoValidation; } public List<IValidationRule<T>> Validations { get; } = new List<IValidationRule<T>>(); public List<string> Errors { get => errors; set { if (Set(ref errors, value)) // ReSharper disable once ExplicitCallerInfoArgument RaisePropertyChanged(nameof(FirstError)); } } public string FirstError => Errors.FirstOrDefault(); public bool AutoValidation { get; set; } public T Value { get => innerValue; set { if (value.Equals(innerValue)) { var i = errors.Count; } if (Set(ref innerValue, value) && AutoValidation) Validate(); } } public bool IsValid { get => isValid; set => Set(ref isValid, value); } public bool Validate() { Errors.Clear(); Errors = Validations.Where(v => !v.Check(Value)) .Select(v => v.ValidationMessage).ToList(); IsValid = !Errors.Any(); return IsValid; } } }


Première constatation cette classe hérite de SimpleObservableObject donc elle participe au système INPC et elle peut ainsi être bindée à des éléments d’UI qui seront avertis des changements de valeur des propriétés. C’est un détail mais il est essentiel pour concevoir un système de validation dynamique et visuel.

La seconde chose qu’on remarque est le support de IValidity, cette interface est encore plus simple :

public interface IValidity { bool IsValid { get; set; } }

Elle permet d’étendre le découplage en permettant à un objet de type ValidatableObject d’être interrogé sur l’état de sa validité sans rien connaître d’autre. Selon les circonstances cela peut s’avérer très pratique et il ne coûte rien de l’ajouter puisque de toute façon il nous faudra implémenter la propriété IsValid qui jouera un jeu important au niveau de l’UI.

Enfin le troisième constat que nous pouvons faire est celui de la nature générique de la classe.

Pourquoi générique ? Car cette classe rappelez-vous va venir remplacer le type de toute propriété qui doit être validée. Or il est important de connaître le type de cette dernière. Et il ne semble plus question aujourd’hui d’écrire plusieurs classes, l’une pour supporter string, l’autre pour supporter double, etc, alors même que la généricité nous évite ce travail et cette répétition de code.

Ensuite nous trouvons les propriétés de ValidatableObject<T>, elles sont peu nombreuses mais ont toutes une importance cruciale.

Value par exemple est la donnée elle-même, celle qui serait utilisée directement comme propriété dans le ViewModel. C’est elle qui sera validée.

IsValid, déjà présentée, qui indique en permanence l’état de Value vis-à-vis des règles de validation. True, Value est valide, False, le contenu de Value ne répond pas aux règles de validation.

Validations est une liste de IValidationRule<T>, c’est à dire de règles qui permettront de valider le contenu de Value.

Errors, on le comprend facilement, est une liste d’erreurs, plus exactement de messages d’erreur. Lorsqu’une règle de validation est appliquée à Value si elle déclenche une erreur elle ajoute le message d’erreur qu’elle contient à cette liste. L’UI peut réagir aux changement de cette liste.

FirstError est une simplification de Errors qui ne retourne que la première erreur de la liste. Il est souvent peu réalisable d’afficher un ListView sous chaque champ pour afficher les “n” erreurs potentielles. Le plus souvent on ne peut afficher qu’une ligne, donc se limiter à la première erreur sera bien plus simple à gérer. Lorsque l’utilisateur aura corrigé sa saisie et que cette première erreur disparaitra, s’il en existe une seconde elle deviendra automatiquement FirstError à son tour et ainsi de suite. L’utilisateur suivra ainsi les consignes données par l’UI au fur et à mesure de ses corrections.

Il est tout à fait envisageable d’afficher Errors,  la liste complète des erreurs, tout dépendra du cas pratique précis et de la place disponible à l’écran ou même du temps qu’on désire passer au design XAML de la page (la liste peut apparaître uniquement dans le cas où il y a plus d’une erreur et uniquement lorsque le champ concerné possède le focus par exemple).

D’autres petits détails ont leur importance. Par exemple le fait de positionner IsValid à True dès l’initialisation de la classe. Cela est laissé à votre appréciation. Il faut brosser l’utilisateur dans le sens du poil, et psychologiquement il faut dire qu’arriver sur une fiche où tout est en rouge alors qu’on n’a pas commencé à saisir quoi que ce soit a quelque chose de violent, de négatif. En considérant que le champ est valide aucun avertissement ne sera affiché lorsque la page sera construite. Mais dès que l’utilisateur commencer sa saisie il sera averti de la première erreur qu’il commettra. C’est plus “soft”. Vous pouvez penser que cela comporte une faille, si l’utilisateur valide toute sa saisie sans rien avoir saisi du tout tous les champs seront considérés comme valides et le bogue n’est pas loin… Non, car nous verrons qu’avant de se terminer le ViewModel de la page forcera tous les champs à se valider pour savoir s’il peut ou non considérer l’ensemble de la saisie comme correct… Si on admet ce petit travail supplémentaire alors l’effet d’une fiche vierge sans erreur est tout à fait envisageable. D’ailleurs la principale erreur ici étant qu’un champ obligatoire reste vide. Or la validation forcée des champs en cas de validation de la page par l’utilisateur déclenchera les mécanismes visuels indiquant cette erreur.

Un détail sur lequel on pourrait donc parler longtemps… Mais passons à l’autre détail, la propriété AutoValidation qui doit être passée au constructeur.

Selon l’approche qu’on préférera et puisque tous les champs sont validés “de force” en sortie de la page, on pourrait se dire qu’il est inutile de valider chaque champ à chaque caractère tapé. Dans ce cas l’utilisateur découvrira ses erreurs à la fin de la saisie de toute façon. En passant AutoValidation à False nous autoriserons ce comportement.

Toutefois dans la majorité des cas il ne faut pas différer l’affichage des erreurs. Psychologie oblige là aussi. Rien n’est plus frustrant que d’avoir saisi toute une page de données et de recevoir un message d’erreur concernant le premier champ tout en haut et peut être hors de vue au moment de valider la page. Donc sauf cas exceptionnels les erreurs doivent être affichées immédiatement. C’est tout l’intérêt du système de validation proposé ici, sa réactivité et son rôle de guide pour l’utilisateur. Pour respecter cette dynamique AutoValidation sera ainsi laissé le plus souven tà True.

IValidationRule<in T>

Notre classe de validation et de transport de données (puisqu’elle contient à la fois la donnée et ses règles de validation) repose sur l’application de règles de validation à la donnée stockée “Value”. Les règles peuvent être de n’importe quel type, nous n’avons aucune raison de limiter leur héritage en en imposant un. C’est une excellente règle de développement…. Laissez toujours le choix si cela est possible au développeur '”final” (même si c’est vous) d’hériter ses classes de ce qu’il veut. L’héritage étant simple (non multiple) se servir de l’héritage bloque toute tentative d’hériter d’autre chose. Lorsqu’on conçoit certaines classes d’une application très liées aux aspects spécifiques de cette dernière l’héritage peut être un choix acceptable, mais lorsqu’on conçoit une classe très générique pouvant être utilisée potentiellement dans plusieurs applications il vaut mieux laisser la seule et unique possibilité d’hériter à la discrétion du développeur final. En choisissant d’utiliser une interface plutôt qu’une classe “de base” et puisque l’héritage multiple des interfaces est supporté, nous ne “grillons” pas la seule possibilité d’hériter qui existe.

C’est pourquoi puisque cela n’est pas obligatoire les règles de validation ne fixerons aucun héritage particulier en dehors du support de l’interface IvalidationRule<T>. A l’extrême certains futés pourrait se dire qu’une classe de type Person et une classe de type Car pourront chacune être une règle de validation pour leur propre type... Cela peut sembler être un avantage. Une classe définissant une entité, par exemple Person pourrait ainsi supporter IValidationRule<Person> ce qui permettrait pour valider une instance de Person de passer cette même instance comme règle de validation… Dans un tel cas toutefois la règle serait “complexe” puisqu’elle serait unique et devrait valider toute l’entité. Mais c’est concevable après tout. Sauf que…

Le sacro-saint principe du découplage doit s’entendre au sens le plus large possible. Et les bonnes pratiques de la Programmation Objet nous imposent la règle de “Single Reponsability” (ou SRP, Single Responsabilité Principle), la responsabilité unique. Une classe = une responsabilité. Ce principe de responsabilité unique impose donc de séparer les règles de validation des entités à valider. Et ce principe est tellement important qu’il est la première lettre du principe plus général appelé par son acronyme : SOLID. je renvoie ici le lecteur à mon article “Que savez-vous de S.O.L.I.D. ?” Une lecture saine et édifiante !

Bref, nous n’imposerons pas d’héritage, et nous ne pourrons pas éviter non plus les petits malins de faire du code spaghetti s’ils le veulent. Les lecteurs de Dot.Blog sont à l’abri de cette malédiction j’en suis convaincu !

Retournons à notre interface :

namespace DataValidationDemo.Validation { public interface IValidationRule<in T> { string ValidationMessage { get; set; } bool Check(T value); } }


Elle expose une méthode Check(T value) retournant True si la donnée passée est valide, False dans le cas contraire. Elle contient aussi une propriété ValidationMessage, une string qui sera fixée lors de la création de la règle. C’est ce message qui sera ajouté à la liste Errors de ValidatableObject et qui ainsi sera présenté à l’utilisateur. Le fait qu’il soit libre laisse la possibilité à l’application de traduire les messages au runtime par exemple.

Aucune disposition n’est prise en ce sens mais il est tout à fait possible de complexifier un peu les choses en laissant la possibilité d’utiliser une chaîne de format comme message. Dans ce cas il faudra modifier le code de ValidatableObject afin qu’il utilise String.Format en passant les bons paramètres. On peut penser à la valeur elle-même, mais elle est déjà sous les yeux de l’utilisateur… C’est pourquoi cette solution n’a pas été retenue ici. Mais dans d’autres contextes on pourrait explorer cette direction pour obtenir des messages plus précis tout en conservant la possibilité de les traduire en plusieurs langues.

Les plus attentifs auront remarqué le '”in” devant le T de IValidationRule<in T>. Il s’agit d’autoriser ici la contravariance parce qu’il n’y a pas de raison de se le refuser… L’octothorpe ça vous dit quelque chose ? Non ? … Alors lisez ce vieil article sur les nouveautés de C# 4.0 et vous saurez tout la covariance et la contravariance ainsi que sur l’octothorpe ! Un beau moyen de briller en société et de couper la chique à l’autre, là, machin truc, qui n’arrête pas de rouler des mécaniques à la machine à café !

Des exemples de règles

Dans notre application exemple nous simulons la saisie d’un login avec son mot de passe. Nous allons utiliser deux règles : l’une qui s’assure que la donnée n’est pas vide, cette règle sera utilisée par les deux champs, et une règle spécifique au champ Password qui s’assurera que ce dernier compte bien 8 caractères au minimum (c’est le cadre de l’exemple, les règles peuvent valider la donnée comme elles l’entendent).

Champ non null ni vide

Cette règle sera donc utilisée deux fois, avec deux instances différences, et deux messages différents (d’où l’intérêt d’un message librement fixé et non pas lié en dur à la règle). La classe de cette règle ne possède aucun héritage sauf celui de l’interface de validation :

namespace DataValidationDemo.Validation { public class IsNotNullOrEmptyRule<T> : IValidationRule<T> { public string ValidationMessage { get; set; } public bool Check(T value) { if (value == null) return false; return !string.IsNullOrWhiteSpace(value as string); } } }


Arrivé ici, il faut dire qu’il n’y a plus grand chose à coder… Surtout que tester une chaîne sur sa nullité ou sa “vidité” (abominable néologisme, pire que l’écriture inclusive !), .NET le fait déjà pour nous avec IsNullOrWhiteSpace.

Hériant de IValidationRule cette classe se contente d’implémenter le stricte nécessaire, la propriété ValidationMessage, et la méthode Check dont on ne commentera pas le code.

Toi ! Bon Mot de passe hugh !

C’est un peu la traduction en français du nom de la classe IsGoodPassword que nous allons voir ici… De l’anglais au rabais je m’en excuse.

namespace DataValidationDemo.Validation { public class IsGoodPassword<T> : IValidationRule<T> { public string ValidationMessage { get; set; } public bool Check(T value) { if (value == null) return false; if (!(value is string)) return false; var v = value as string; if (string.IsNullOrWhiteSpace(v)) return false; if (v.Length < 8) return false; return true; } } }


Que dire ici si ce n’est que c’est la même chose que précédemment, à la différence que le test compte les caractères et retourne False si le champ en contient moins de 8 ou qu’il est vide. Cela fait un peu double emploi avec la règle précédente mais “Au moins 8 caractères” oblige à tester aussi 0 caractère.

Conclusion de la partie 2

Et oui, il y aura une partie 3 ! je vous le disais en fin de partie 1, malgré la grande simplicité de tout cela il faut beaucoup expliquer, et même s’il n’y a rien de sorcier, il y a plein de petites choses qui comptent.

C’est long à lire, mais dîtes vous que c’est encore plus long à écrire !

Donc on se retrouve pour la prochaine partie, avec peut-être d’autres news plus courtes avant… de bonnes raisons de ….

Stay Tuned !

Catégories: Dévelopement

Xamarin.Forms, Prism, VS 2017 et .NET Standard

Dot.Blog - lun, 13/11/2017 - 23:06

Cela pourrait être une fable avec un peu trop d’acteurs mais le même récit un peu triste et à la fin une morale… En effet comme on dirait pour un statut amoureux sur Facebook “c’est compliqué” ! …

C’est compliqué !

En ce moment nous avons le droit à un petit festival de mises à jour de VS 2017, 15.4.2, 15.4.3 et ses amis qui suivent, avec chacun d’entre nous des expériences différentes (plantage complet, pertes de certaines fonctions ou alors tout va bien, mais dans ce cas là vérifiez tout de même ce que faisait votre compagne/on hier soir !).

Le plus fun c’est que cela s’ajoute à des mises à jour de Xamarin.Forms, de Prism, et toute la famille et que dans cette joyeuse effervescence vient s’inviter celui qu’on attend mais pas si vite : .NET Standard 2.0.

On s’imagine, non, on constate plutôt le fouillis que cela peut engendrer et ce n’est pas drôle pour tout le monde. Certains lecteurs savent de quoi je parle

Non, c’est pas compliqué, c’est le souk…

Il faut être franc, c’est le bazar. C’est pas compliqué, tout est simple, mais rien ne marche comme prévu.

Par exemple le template Prism prévu pour PCL se met à faire des projets .NET Standard mais qui ne compilent pas, par force. Il faut deviner qu’il y a une mise à jour du 11 novembre dernier qui est étudiée pour tourner sous .NET Standard. Elle créée ainsi du .NET 2.0 Standard aussi mais au moins ça marche.

Enfin… ça marche une fois. En tout cas j’ai réussi une fois à compiler et à avoir quelque chose sur le smartphone. En acceptant de perdre l’Intellisense sous XAML. Un peu dommage…

Mais ça ne marche plus la seconde fois. Les messages d’erreur sont assez abscons et on ne sait pas trop s’il faut tout reformater et réinstaller Windows ou juste fracasser son UC et aller à la pêche… C’est bien la pêche, c’est paisible, c’est cool…

Une solution docteur ?

Comme disent les médecins un rhume non soigné dure une semaine, et un rhume bien soigné dure sept jours…

Donc ici le mieux c’est de ne pas mettre à jour Visual Studio, conserver son environnement de développement stable, faire le gros dos, et attendre que “ça passe”, comme un gros rhume. Car comme à chaque fois qu’il y a un passage de flambeau comme .NET Standard 2.0 mieux vaut débrancher son PC d’internet pour ne faire aucune mise à jour et attendre une bonne année que ça murisse…

C’est dommage d’un autre côté de se passer des nouveautés de Xamarin.Forms qui évolue sans cesse.

Et puis c’est trop tard vous avez fait les mises à jour…

- “Il me reste combien de temps doc’ soyez franc…”…

- (le toubib montre sa main ouverte)

- Quoi ? 5 ans !!!

- …

- Comment çà 5 mois ? !

- …

- 5 jours ? !!!!

- (le toubib annonce chaque chiffre en pliant doucement chaque doigt) 5 – 4 – 3 …

C’est flippant hein ? Et bien c’est un peu ça en ce moment, mais ça va passer, faut pas s’en faire. Faut juste passer le coup de tabac sans finir à la mer…

La méthode russe

La méthode russe ? Da tovaritch développeur !

Comme chez les russes, on n’a pas de moyens mais avec de l’ingéniosité et trois bouts de ficelle on fait pareil que les américains avec un budget stratosphérique…

Donc on commence par se passer du luxe paresseux et bourgeois des templates de Prism.

A la russe, on va tout faire à la main !

Ensuite on oublie .NET Standard 2.0, c’est génial, ça devient la norme, mais laissons aux équipes de MS le temps de serrer les boulons qui se débinent un peu partout… On va pas se laisser démonter pour si peu ! … Heu si, ça se démonte même tout seul chef ! – J’ai vue seconde classe, j’ai vu…

La main plus sophistiquée qu’une fusée et pas de mises à jour à faire !

Donc on va reprendre calmement sans s’énerver, le cran est ce qui caractérise le mieux les héros. Et on va faire tout à la main, c’est pas si compliqué.

1 – Créer le projet (la solution)

Dans C# / Cross-Platform on choisit une application Xamarin.

On répond aux quelques questions habituelles (non de l’appli etc) ainsi qu’au dialogue demandant des détails sur le mode de création, là on préfère choisir le mode PCL.

On valide tout ça, on attend que Visual Studio ait créé tous les projets.

On obtient une belle solution Xamarin.Forms qui marche très bien.

Mais elle n’a pas encore Prism…

2 – Ajouter Prism à la mimine

Ajouter Prism n’est pas très compliqué mais quand on est habitué aux templates forcément on sent comme un vide… Car simple ne veut pas dire évident.

Les paquets

Première chose : vérifier que les paquets sont bien installés.

On va choisir Prism.Forms, puis Prism.xxx.Forms où xxx est le nom du conteneur IoC, DryIoc par exemple. Ensuite on installe xxx lui-même. On fait cela pour tous les projets

Les folders

On créée les répertoires Views et ViewModels dans le projet PCL.

Ensuite on déplace dans Views la MainPage.xaml et son code behind. Si on a déjà plusieurs pages on fait pareil pour toutes.

On n’oublie pas de corriger le namespace dans le code behind et dans la page XAML.

Le type de l’App

On va dans App.Xaml.cs et on change l’héritage. App devient un descendant de PrismApplication. Cette classe est définie dans Prism.xxx, c’est à dire qu’elle porte toujours ce nom mais est différente selon le conteneur IoC choisi. Le constructeur de la classe doit être changé aussi :

On vire tout le code de base qui ne sert plus à rien mais en revanche on override les deux méthodes OnIntialized() et RegisterTypes qu’on complète selon les Views et les ViewModels qu’on possède. Si on part d’un projet vierge on n’a pour le moment qu’une seule View, MainPage et pas encore de ViewModel ce qui va donner :

Dans cet exemple le conteneur est Unity. Il est vrai que Unity est cuit, fini, plus maintenu et lent… Oui mais ne l’enterrons pas si vite ! Je sais qu’une version 5 est en cours de préparation qui pourrait relancer ce conteneur IoC dans la bagarre !

Bref, dans OnInitialized() on initialise… et dans RegisterTypes on enregistre les types … Celui de la page de navigation, toujours déclarée en premier et ensuite les pages à disposition, pour l’instant MainPage donc.

Au niveau des pages il n’y a plus rien à faire puisqu’il n’est plus nécessaire d’ajouter l’initialisation de AutoWire, sauf si on veut le mettre à False, ce qui certainement très rare.

Les ViewModels

Si vous venez de créer la solution, forcément il n’y en a même pas un. Il faut le créer (au moins pour MainPage).

Pour cela il suffit de créer une classe qui s’appellent MainPageViewModel, le suffixe permettant le lien automatique avec la page. Cette classe descend de BindableBase fournie par Prism. En dehors de cela elle n’a aucune contrainte.

En général le constructeur utilise l’injection de dépendance pour récupérer le gestionnaire de dialogue, le service de navigation, mais tout cela est optionnel malgré tout.

Le ViewModel expose aussi des propriétés et des commandes, mais encore un fois c’est à vous de décider en fonction du besoin, ni les Xamarin.Forms ni Prism ne vous oblige à quoi que ce soit.

Le ViewModel de MainPage pourra donc ressembler à cette version minimaliste avec juste une propriété Titre exposée pour faire joli. On notera que la méthode indiquée marche aussi bien pour un projet en mode Shared plutôt qu’en PCL.

Les initialiseurs de plateforme

Là encore rien de bien méchant puisqu’il s’agit juste de créer une instance de la classe partagée App en lui passant en référence une méthode qui peut être utilisée pour ajouter dans le conteneur IoC des choses spécifiques à la plateforme en question. Souvent vide, cette section doit tout de même être déclarée :

Sous Android, dans la MainActivity, en fin de code on change un peu le code de l’appel à LoadApplication et on ajoute la classe d’initialisation :

Sous iOS et UWP c’est le même principe. Toujours avec une classe supportant IPlatformInitializer et sa méthode RegisterTypes généralement vide comme je l’ai dit.

C’est fini !

Et oui, c’est pas si compliqué que ça…

Conclusion

Au final on a une belle solution PCL fonctionnant sous .NET, généralement le profil 259, avec Prism, bref le grand pied bleu pour démarrer une App qui fera un succès !

Pour l’instant on laisse de côté le template Prism, l’ancien comme le nouveau, les mises à jour bizarres de Visual Studio, et on se tient à l’écart de .NET Standard 2.0 qui va devenir la norme, c’est en cours, mais franchement on voit que le chantier n’est pas totalement terminé. Si cela se trouve dans une ou deux mise à jour, c’est à dire dans quelques jours vu le rythme actuel (!) tout sera rentré dans l’ordre. Mais en attendant il faut bien avancer.

Avant Visual Studio était peu mis à jour. C’était parfois un peu long pour bénéficier des nouveautés mais on disposait de grandes plages de calme pour travailler et faire ce pour quoi nous sommes payé et non pour réparer les outils.

Désormais Visual Studio fait des mises à jour tout le temps, et des mises à jour du programme de mise à jour aussi. Dans cette intense bourdonnement forcément il y a plein de ratés et on a un peu l’impression que Visual Studio n’est plus qu’un logiciel en béta test permanent…

Ca va se tasser, mais c’est un peu pénible je l’accorde. .NET Standard 2.0 est une idée géniale pour fédérer tous les .NET sans tous les réécrire, mais mettre au diapason Visual Studio, les toolkits tiers, les templates, etc, ça ne peut pas se faire en deux jours. On aimerait que MS prenne un peu plus de temps pour nous livrer des choses utilisables et fiables, c’est certain.

Mais le magasin reste ouvert pendant les travaux !

Malgré ces petits soucis temporaires, on peut continuer à profiter de Visual Studio, de Xamarin.Forms et de Prism, juste en se servant de ses mains !

Stay Tuned !

Catégories: Dévelopement

Xamarin.Forms, Validation des données et Mvvm–Partie 1

Dot.Blog - sam, 11/11/2017 - 21:46

Comment valider les données ? Quel retour visuel donner à l’utilisateur ? Le tout en respectant Mvvm ? Tout un programme ! A suivre tout de suite sur votre blog préféré…

Validation des donnéesUn besoin fondamental

Valider les données n’est pas compliqué en soit mais c’est une obligation connue depuis toujours. On dispose déjà depuis longtemps de découpages des applications en couche métier (BOL, Business Object Layer), couche données (DAL, Data Access Layer), Services, même micro-services, etc. Et toutes ces couches sont capables de valider les données. La couche BOL peut en fonction de règles métier interdire certaines valeurs, la couche DAL peut elle filtrer les valeurs interdites (NULL non accepté pour un champ par exemple), la base de données elle-même peut refuser des clés étrangères non renseignées, etc...

Cette façon de découper une application en couches ayant des responsabilités précises peut toutefois amener à un éclatement des règles de validation. La base de données effectue des validations plutôt “défensives” visant à maintenir l’intégrité des données qu’elle stocke (un article sans référence n’est pas stockable). La couche BOL effectue des validations qui n’ont de sens que dans le cadre du métier (un véhicule de type moto ne peut avoir que deux roues), la couche DAL, intermédiaire, pose déjà le problème de savoir si ses validations n’empiètent pas sur le domaine du SGBD ou du BOL (un facture sans référence client peut relever de la protection de l’intégrité des données du SGBD ou bien avoir un sens fonctionnel particulier pour l’application par exemple pour servir de template pour les nouvelles factures). A vouloir trop bien faire on créée aussi une complexité difficile à gérer… Les tests ne sont pas centralisés, ils sont parfois redondants, et quand ils évoluent il n’évoluent pas identiquement dans tous les recoins de l’application laissant la porte ouverte à des bogues sournois difficiles à trouver, mais pas rares à rencontrer !

Valider les données est toujours très simple sauf exceptions. Techniquement tester un NULL, une valeur inférieure ou supérieure à une limite, etc, tout cela est du niveau débutant. Quelques fois les validations imposent des calculs, l’appel d’API externes, mais cela est plus rare et finalement guère plus complexe, juste plus lourd.

Valider n’est pas informer… et pourtant il le faut !

Mais le plus gros problème est de savoir où et comment ces validations sont faites et surtout quel retour l’utilisateur en aura. Car valider est une opération interne, encore faut-il qu’elle puisse être visible de l’opérateur (utilisateur) pour qu’il puisse corriger l’erreur, et voire mieux, ne pas la commettre !

Nous connaissons tous des logiciels programmés avec les pieds notamment sur le Web où il faut avoir saisi une page d’information puis valider pour se voir refuser cette validation avec un message du genre “les champs avec étoile ont des erreurs”. Et vas-y mon gars ! Retape toi la page à la recherche des fameuses étoiles souvent en corps 4 sous, dessus, à droite, à gauche du champs, faut chercher… Quant à la raison elle est parfois assez absconse.

Les programmeurs qui commettent de tels codes devraient être déchus du droit d’exercer…

Je pense que la plupart des sites de l’administration française au moins sont de ce type, mais pas que… donc on se garde bien de se moquer…

Comme on le comprend il ne suffit pas de se protéger en “validant” les données, encore faut-il “bien” les valider c’est à dire au bon moment et en faisant en sorte que cela soit le moins pénible pour l’utilisateur.

Lorsqu’en plus on doit respecter MVVM, c’est à dire découpler au maximum et rendre le code maintenable et testable automatiquement via du Unit Testing, cela peut compliquer légèrement la tâche du développeur. Mais c’est aussi pour cela qu’il est payé…

D’ailleurs l’avenir de l’informaticien se trouve dans les failles des IA : l’inventivité, la créativité, et une pensée globale, enrobante, que les IA de demain n’auront pas. Quant à celles qui seront douées de conscience, du sens artistique, d’une éthique, etc, on est toujours pour l’instant dans le domaine de la SF. De la SF pour les IA, mais une réalité pour le cerveau de l’humain !  L’informaticien qui fait son travail avec intérêt et passion est en quelque sorte déjà  une machine du futur !

Alors il se préoccupe de tout, il a de l’empathie pour les utilisateurs, il pressent leurs éventuelles frustrations et il évite la cognitive friction, il devance les difficultés à venir, les gomme, il est dès aujourd’hui et pour moins cher finalement, ce que la science arrivera peut-être à créer dans 50, 100 ans ou jamais. Il est cette machine du futur que j’évoquais. A lui de bien se servir de ses “super-pouvoirs” (et de savoir les vendre) !

Bien valider

Bien valider les données est donc à la croisée de plusieurs chemins, celui du fonctionnel, de la technique pure, du design, mais aussi d’une forme d’humanisme. Savoir se mettre à la place de l’utilisateur pour lui faciliter l’accès à une application est un acte d’amour vers l’autre ou au moins de l’empathie. Ceux qui détestent les utilisateurs, qui les critiquent sans cesse, ne sont pas de bons informaticiens. Ils oublient leur mission. Celle qu’une IA n’est pas prête de remplacer… Ceux-là seront les premiers à être remplacés, comme le furent les pupitreurs, les cobolistes et autres dinosaures du musée de l’informatique.

Bref, bien valider n’est pas qu’un boulot de codeur, c’est aussi un travail de design, de conception d’UI efficaces et vendeuses (voir ou revoir ma conférence aux Techdays “Concevoir des interfaces utilisateur efficaces et vendeuses”).

Comment valider les données ?

Par défaut les Xamarin.Forms n’offrent rien de spécial pour effectuer une validation de données, ni sur le plan du code, ni visuellement. Côté code on peut prendre le problème dans l’autre sens et se dire qu’en nous fournissant C# ils ont déjà fait le maximum… Et côté visuel en fournissant avec les Xamarin.Forms de nombreux moyens de personnaliser l’UI le boulot est fait là aussi.

En réalité Xamarin ne peut pas aller beaucoup plus loin, le reste nous incombe !

Et pour se plier à la réalité nous allons créer et mettre en place un système de validation…

Mécanisme de validation

La première chose à mettre en place est un mécanisme de validation suffisamment universel pour couvrir tous les besoins courants de validation, assez simple pour ne pas peser de trop sur le code et l’UI, mais assez complet pour simplifier la prise en compte visuelle de la validation (l’information à l’utilisateur).

On peut mettre en place de nombreux systèmes de ce genre en les adaptant au contexte de l’application, mais voici un schéma assez générique qui vous fournira une base de réflexion ouverte à toutes les améliorations que vous voulez :

(rappel : un clic sur l’image vous donne la version à 100 %)


Sur ce schéma on peut voir de nombreux acteurs qui sont :

  • Le contrôle Entry qui permet la saisie des données, données qui devront être validées et complétées par un retour visuel. On aurait pu choisir d’autres éléments d’UI mais le Entry est une sorte de base incontournable pour la saisie de données. Mais il n’est qu’un exemple, le principe présenté fonctionne avec d’autres contrôles.
  • Le ViewModel, pierre angulaire de MVVM, il aura forcément un rôle un jouer
  • SimpleObservableObject, classe servant à créer des classes filles supportant INPC (on peut utiliser toute autre classe à la place du moment qu’elle offre un support de INPC)
  • ValidatableObject<T> La classe qui permettra de créer des objets de validation, sujet même de l’article
  • Les règles de validation qui sont personnalisable pour chaque contrôle à valider.

L’astuce principale de ce “montage” est de substituer aux propriétés classiques exposées par le ViewModel des ValidatableObject<T>. C’est à dire que si la donnée est de type string, au lieu de proposer une propriété “public string NomDeFamille {get;} {set;}” on utilisera à la place une propriété “ValidatableObject<string> {get ….} {set …}”. Nous verrons le détail plus loin.

Pourquoi cette substitution ? Car la classe ValidatableObject<T> en plus de contenir la valeur (ici le nom de famille en string) va fournir les moyens de valider la donnée et de connaître le résultat de cette validation.

Retraçons maintenant la petite histoire racontée par le schéma ci-avant :

Un contrôle servant à saisir une donnée à valider, un Entry dans cet exemple, est databindé à une propriété du ViewModel. Cette propriété n’est pas exposée directement mais elle est encapsulée dans une instance de ValidatableObject<T>, T étant le type de la donnée (string, int…). C’est le ViewModel qui a la charge de créer cette instance à laquelle il fournit des règles de validation propres au champ considéré.

L’UI, via le contrôle, va obtenir l’état de la validation en interrogeant ce dernier depuis l’objet ValidatableObject<T> qui contient comme je le disais à la fois la valeur du champ, la donnée, mais aussi les outils pour le valider et des propriétés pour indiquer les erreurs éventuelles.

Les règles de validation sont des instances de classes supportant IValidationRule<T>. On écrit ces classes de telle façon à ce qu’elles valident une donnée de type T. Le mieux étant qu’une classe Règle ne valide qu’un seul aspect de la donnée. Par exemple une règle peut servir à tester si un string est Null ou vide. Si le champ doit en plus faire plus de 8 caractères on écrira une autre Règle acceptant le nombre de caractères dans son constructeur de telle façon à ce que cette règle puisse être réutiliser dans de nombreux contextes sans réécriture (principe DRY : Don’t Repeat Youself !).

Si un contrôle de saisie nécessite d’être validé par plusieurs règles elles seront ajoutées à l’objet ValidatableObject<T> qui gère une collection de règles.

Chaque Règle, lorsqu’elle est instanciée se voit fournir un message d’erreur à afficher. ValidatableObject<T> expose ainsi cette collection sous la forme d’une propriété ce qui permettra à l’UI de l’utiliser.

On comprend maintenant pourquoi ValidatableObject<T> se substitue au type de la donnée dans le ViewModel, cela permet à la View d’accéder à toutes ses propriétés. La propriété Value sera de type T, ce qui revient donc au même que de l’avoir ainsi déclarée directement. Mais depuis l’UI et sans violer MVVM il sera aussi possible d’accéder à la liste des erreurs éventuelles. Il sera même possible d’accéder à un flag IsValid sans cesse mis à jour indiquant si la donnée saisie est correcte. D’où l’intérêt de faire descendre ValidatableObject<T> d’une classe offrant le support de INPC.

On pourrait fort bien implémenter le support d’INPC directement. Mais puisque nous parlons dans un contexte MVVM nous savons que la plupart des toolkits de ce type offre un type de base, souvent utilisé pour créer les ViewModels. Dans mon exemple SimpleObservableObject est une classe “personnelle” afin de ne pas utiliser la classe de l’une ou de l’autre des librairies MVVM. Dans la pratique vous pouvez parfaitement utiliser une classe similaire déjà présente dans votre application ou bien celle fournie par le toolkit MVVM que vous allez utiliser.

Un peu de visuel !

Nous aussi nous avons besoin d’un retour visuel ! Et pour cela rien ne vaut une petite capture écran en Gif animé pour que vous compreniez ce que nous allons réaliser.

La capture ci-dessous montre :

  • La saisie d’un login qui ne peut être vide. Si c’est le cas le champ se souligne de rouge et un message d’erreur est affiché en dessous.
  • La saisie d’un mot de passe qui ne peut être vide mais qui aussi doit compter au moins 8 caractères. Les deux messages d’erreurs se succéderont (c’est un choix plutôt que d’afficher une liste disgracieuse c’est la première erreur qui est affichée. Au fur et à mesure que l’utilisateur corrigera il verra s’afficher la prochaine erreur et ainsi de suite jusqu’à ce que le champ soit ok).

Ca va aller assez vite pour éviter que le Gif ne soit trop gros, mais comme ça boucle vous pourrez saisir chaque étape tranquillement en attendant le prochain passage de la boucle …



L’animation ci-dessus est accompagnée d’un suivi de la souris, d’une barre de progression verte à droite (elle arrive tout en haut en fin de boucle) et au centre en bas de l’indication des touches clavier tapées. Cela grâce à l’excellent freeware ScreenToGif que je vous recommande chaudement au passage (il peut créer des vidéos au lieu de Gif, faire la capture de la webcam aussi, dispose de diverses options, bref c’est bien).

Conclusion déjà ?

Et oui, d’où les mots “Partie 1” dans le titre hein…

C’est un gros morceau cet article. Nous allons entrer dans les détails de la réalisation, des personnalisations du contrôle Entry via des Effects Xamarin.Forms etc.. Ca en fait du code et des explications…

Alors prenons une pause avant la partie 2 !

Donc.. donc…

…. Stay Tuned !!!

Catégories: Dévelopement

Les secrets du Data Binding Xamarin.Forms

Dot.Blog - dim, 05/11/2017 - 01:36

Le data binding est un mini langage dans le langage, il est puissant mais il ne dévoile pas tous ses secrets au premier coup d’oeil. En voici quelques uns…

Le Data Binding

Je ne vous ferai pas un long exposé sur sa nature, sa syntaxe et tout le reste, c’est un sujet que j’ai traité ici nombre de fois et qui fait l’objet d’un chapitre entier de mon livre sur les Xamarin.Forms tellement il y a à dire. Et preuve de la complexité et de la richesse du sujet je peux encore trouver d’autres choses à vous présenter aujourd’hui !

Tout ne sera pas forcément nouveau pour les lecteurs assidus de Dot.Blog ou ceux de mon livre mais il y a surement dans ce billet au moins un ou deux trucs que vous ne savez pas…

Compiler les data Bindings

La compilation du code XAML permet de gagner un peu de temps à l’exécution et de bénéficier d’alertes ou d’erreurs lors de la compilation ce qui rend cette option particulièrement intéressante.

Elle peut s’activer au niveau global ou page par page. Le plus simple étant de l’activer au niveau global d’un namespace, normalement celui de votre code partagé :


Mais cela n’est pas vraiment tout…

Il y a un second niveau d’astuce pour activer la compilation des bindings qui sinon restent calculés à l’exécution, notamment en MVVM où la View ne connaît pas la classe du ViewModel.

Ce niveau s’active en précisant le type de la donnée qui est bindée, ce qui semble naturel puisque s’il manque XAML est bien obligé d’attendre l’exécution pour le connaître et que justement c’est ce qu’on cherche à éviter en forçant une reconnaissance précoce. Et pour cela il faut utiliser x:DataType. Premier indice. Mais où ?

Le mieux est de le placer au plus haut niveau du code XAML, celui de la page par exemple, de telle façon à ce que toute la vue puisse en profiter. C’est à ce même niveau que se trouve l’initialisation du BindingContext.

Toutefois cela soulève un petit problème… si l’on respecte MVVM il n’est pas possible de lier la View au ViewModel, c’est mal. Je plaisante, il y a de bonnes raisons à cela que je ne développerai pas ici. Néanmoins cela ouvre débat puisque la View est conçue pour fonctionner avec des champs bien précis elle pourrait dans l’esprit connaître son ViewModel sans “trop” violer MVVM. Autant créer un lien entre un ViewModel et une View ou tout élément de l’IHM est indiscutablement une erreur, autant dans l’autre sens, on peut en discuter et je pense que cela peut se défendre (sauf dans un système idéal avec Unit Testing, mocking etc, mais franchement j’en vois ultra rarement des projets avec Unit Testing…). Mais restons fidèles à la ligne fixée par MVVM. D’ailleurs ce pattern autorise le lien direct entre une View et un élément du Model si cela est ponctuel et pour une View n’ayant aucune interaction (car une interaction impliquerait par exemple un bouton donc une commande donc du code, c’est à dire quelque chose qui doit absolument être dans un ViewModel, et ça ça ne se discute pas).

Si on essaye d’être un peu filou, le lien View –> Model est autorisé, mais pas View –> ViewModel. Ok. On peut considérer qu’une donnée exposée par le ViewModel est issue de la couche Model (c’est même une obligation. Du Model ou alors c’est un type de données .NET ce qu’on considèrera comme équivalent ici). Donc si ce n’est pas au niveau global de la page que l’on va créer un lien vers le type du ViewModel rien ne nous empêche de lier ponctuellement un élément de la View au type d’un élément du Model…

Vous captez la subtilité ?

Un petit exemple va aider. Considérons que dans la couche Model on dispose d’une classe Clients.Models.Deal décrivant une transaction. Et imaginons que le ViewModel expose une liste de Deal. Comme vous le constatez je ne vous parle pas un instant ni du nom de la propriété exposée ni de la classe du ViewModel, juste du type de la donnée provenant de la couche Model.

Pour afficher la liste la View va utiliser par exemple une ListView, le coup classique pourrait-on dire. C’est à ce niveau, là où se trouve le binding avec les éléments de la liste que nous allons injecter le type de la donnée affichée :

Dans l’ItemTemplate de la ListView, au niveau de son DataTemplate, on fixe le type affiché par ce dernier et le tour est joué ! XAMLC va pouvoir compiler le code XAML mais il va aussi pouvoir compiler le Binding puisqu’il connaît à l’avance le type qu’il aura à traiter !

C’est vraiment une bonne astuce car on a le meilleur des deux mondes, celui du early binding permettant à la compilation de faire son œuvre (notamment si la donnée affichée supporte INPC le compilateur effectuera bien le lien sur l’événement aussi), et celui du late binding au niveau du ViewModel ce qui permet de respecter totalement MVVM. La liaison View->Model étant autorisée.

Parallèlement vous aurez noté que le namespace XML (xmlns) fonctionne ici en utilisant “using” et non “clr-namespace”. Cela n’a rien de spécifique au binding compilé c’est juste une autre astuce XAML à connaître… Lorsque la référence est dans le même assembly cela ne sert à rien de se compliquer la vie avec un “clr-namespace”, un simple “using” est suffisant !

On note dans le code exemple que la ListView affiche les données via un contrôle personnalisé, une ViewCell dont le contenu est issu d’un ContentView. Inutile de préciser (si ? alors je le fais !) qu’on peut utiliser l’astuce du x:DataType à n’importe quel niveau de la hiérarchie, donc aussi à l’intérieur du ContentView. On s’assure ainsi une compilation totale et sans ambiguïté.

Les autres astuces

Il existe bien d’autres subtilités à connaître. L’utilisation du StringFormat par exemple ou des binding OneWayToSource en font partie, mais soit j’en ai déjà parlé, soit j’en parle dans mon livre, soit je vous en reparlerai car il faut en laisser pour plus tard !

Conclusion

Le typage des bindings dans la View doublé de la compilation XAML permet à XAMLC de générer un meilleur code, plus rapide à charger, et mieux débogué à la compilation. On peut bénéficier de tout cela sans violer les règles de MVVM, non pas qu’ils s’agissent de lois quasi divines mais parce qu’ils s’agit de règles de bon sens pour créer de bons logiciels.

Toutes les règles peuvent se contourner si le contexte le justifie, mais bien souvent si on réfléchit un peu plus on peut trouver des solutions qui tout en respectant MVVM permettent de bénéficier des petits avantages qu’une violation de la règle laissait espérer.

Et en agissant ainsi à chaque fois on se sert de MVVM non pas comme d’un texte sacré mais comme d’une éthique nous permettant de rester sur la voie. S’en écarter trop souvent, être trop permissif, c’est à coup sûr entasser au fil du temps tellement d’acrobaties que tout se cassera la figure.

Ici nous avons vu comment marier la compilation précoce de XAML avec les règles de MVVM. Produire un meilleur code sans faire de sacrifices…

Stay Tuned !

Catégories: Dévelopement

Adaptive Design et Xamarin.Forms

Dot.Blog - ven, 03/11/2017 - 20:13

Ecrire en cross-plateforme un seul code commun ne veut pas dire refuser toute adaptation au support ! Par exemple les techniques d’adaptive design pouvant être exploitées au sein d’une App Xamarin.Forms sont nombreuses…

L’adaptive design

Parfois confondu avec le Reactive Design, l’adaptive design vise à adapter l’UI au form factor utilisé, du petit smartphone à l’écran de télé ou de PC.

Le reactive design aurait plutôt une connotation plus technique, à savoir coder de façon à ce que l’App reste réactive, “responsive”’, en toute circonstance. De fait on entend aussi parler de Responsive design.

Hélas comme souvent avec toutes ses expressions et mots nouveaux pas deux personnes s’entendent sur le sens exact. Ainsi on parle parfois d’adaptive design ou de reactive design voire donc de responsive design pour désigner dans les trois cas la capacité d’une UI à s’adapter au form factor.

Ainsi, le lecteur intéressé par le concept et ses différentes mises en œuvre en XAML pourra certainement tirer profit de la lecture des articles suivants qui traitaient de cette question à propos de UWP (du C#/XAML pas très éloigné de celui des Xamarin.Forms). On notera qu’ils datent de 2015 mais comme je traite souvent de sujets bien avant qu’ils n’émergent tout cela reste très moderne ! (Par exemple ma série de 12 vidéos sur le cross-plateforme avec Xamarin et MvvmCross date tout de même de l’été 2013… bien avant que ce sujet ne devienne central et le contenu reste toujours à propos mise à part les différences mineures introduites par le choix du toolbox MVVM) :

UWP étant par nature cross-form-factor, les problèmes soulevés étaient déjà la mêmes que ceux que posent le cross-plateforme et pour les mêmes raisons (différences entre les form factors suportés).

Donc arrivé ici vous êtes totalement au point sur cette notion d’adaptive design, peu importe le nom exact qu’on lui donne, et ceux qui ne l’étaient pas se sont rués sur les articles en référence et ils sont maintenant au taquet ! On va pouvoir passer à ce qui nous intéresse aujourd’hui …

L’Adaptive Design avec les Xamarin.Forms

Ce ne sera pas un article théorique mais très pratique ! Donc au-delà de l’introduction qui posait le décor nous allons plonger directement dans des cas bien précis de mise en œuvre de l’adaptive design avec les Xamarin.Forms.

S’adapter à la taille des écrans

S’il existe bien un point d’entrée dans le monde concret de l’A.D. c’est bien celui qui concerne la connaissance de la taille de l’écran. C’est même la première chose à prendre en considération. On n’affiche pas tout à fait les mêmes informations en 320x480 (Iphone 3GS) qu’en 5120x2880 (iPac 27” retina 5k)…

Comme il n’existe pas de standard (ah le bon vieux du temps du CGA ou du VGA !) on trouve même toutes les possibilités intermédiaires ou presque. A cela s’ajoute bien entendu la densité en pixels qui elle aussi modifie totalement la façon d’interpréter la taille écran en pixels.

Il s’avère que les Xamarin.Forms fonctionnent sur un mode proche du pixel effectif de UWP. Par défaut les XF utilisent DIU (Device Independant Unit). Ce qui nous arrange bien puisque nous n’avons donc pas à prendre en compte la densité, les pixels retournés par les XF le font déjà (pour plus d’information voir la documentation “Daling with sizes” sur le site Xamarin – vous noterez que ces aspects de tailles, de pixels et de fontes sont abordés dans mon livre sur les Xamarin.Forms).

Pour s’adapter à la taille de l’écran il faut ainsi obtenir la mesure en pixels, mesure qui sera donnée en DIUs par Xamarin.Forms.

Le moyen le plus simple au sein d’une Page est d’enregistrer un handler pour l’évènement MainPageSizeChanged :



C’est un procédé simple et efficace permettant d’adapter la taille d’une image (l’exemple ci-dessus) par exemple. On notera toutefois qu’une interrogation au niveau de chaque page semble assez peu économe, la taille de l’écran ne risque pas de changer en cours d’exécution et obtenir celle-ci une fois pour toute dans App.xaml.cs par exemple peut être plus efficace.

Néanmoins il reste à gérer l’orientation de la device, ce qui change la taille écran retournée par l’événement indiqué. Si on veut être sûr de s’adapter à la taille de la device et même temps aux rotations qui modifient artificiellement celles-ci (la hauteur et la largeur sont simplement inversées) alors l’adaptation au niveau de la Page peut conserver un intérêt.

Répondre aux changements d’orientation

Lorsque la device est tournée du mode paysage au mode portrait, ou inversement, il y a une rotation automatique effectuée par défaut par les Xamarin.Forms. Cela est très pratique puisqu’il n’y a rien à faire. Enfin presque… car il est très rare qu’un écran conçu pour le mode portrait (le plus fréquent sur un smartphone) passe sagement en mode paysage sans que cela ne pose quelques soucis de mise en page !

On peut s’en tenir à l’idée précédente qui consiste à “écouter” les changements de taille de l’écran. Mais on peut aussi détecter directement le changement d’orientation de la device ce qui est parfois plus pertinent. L’un n’interdisant pas l’autre (connaître l’orientation et la taille écran en pixels DIU est plutôt complémentaire).

Les petits futés auront remarqués que sur une device donnée on pouvait d’ailleurs utiliser le même évènement ! Il suffit de regarder si la largeur est plus grande que la hauteur et on sait de façon sûre dans quelle orientation se trouve la device…

Dans l’exemple ci-dessus on modifie une variable booléenne quand la taille écran est changée. Selon les proportions hauteur / largeur on peut ainsi créer un flag isPortrait exploitable par le reste de la page.

Le code présenté jusqu’ici doit se comprendre comme du code d’UI, donc il se trouve dans le code-behind de la page concernée et non dans le ViewModel.

Une fois l’orientation connue il est possible depuis le code-behind de modifier la taille et la disposition des éléments à afficher, voire d’en cacher ou montrer certains. Dans l’illustration ci-dessous une partie de l’affichage qui se trouvait au-dessus de l’autre en portrait est plutôt affichée à gauche de cette dernière. Cela change radicalement l’aspect de l’App mais d’une façon si naturelle et évidente que l’utilisateur n’y pensera même pas (alors que sans ce changement je vous garantie qu’il ronchonnera à juste titre !) :

Prendre en compte le type de device

Dans la panoplie de base de l’A.D. il y a la taille de l’écran, son orientation mais aussi le type de la device !

On n’affiche pas les mêmes choses sur l’écran d’un smartphone et sur celui d’une tablette, peu importe l’orientation ou la taille en pixels, question de taille physique de l’objet tout simplement et notamment de la distance à la quelle l’objet se trouve des yeux de l’utilisateurs. Un smartphone est tenu très près, une tablette sera posée sur la table comme un écran de portable, un écran de PC sera à 30/50 cm environ, celui d’une télé bien plus loin, etc…

Les Xamarin Forms nous offrent un moyen simple de prendre connaissance du type de la device, par le biais justement de la classe Device et des informations qu’elle retourne.

Il existe quatre types de device qu’on peut tester par exemple dans un switch pour prendre les décisions appropriées :


On peut utiliser l’Idiom pour changer la taille des objets, de la fonte, pour modifier la mise en page, voire même pour appeler une page différente au moment de la navigation.

Il est même judicieux de prévoir la substitution d’éléments d’UI par d’autres. Ainsi par exemple une application de dessin proposant un Color Picker pourra gérer différents types de contrôles selon que la device est de type purement tactile (smartphone, phablet, tablette…) ou qu’il s’agit d’une machine disposant d’un outil de pointage plus précis (PC ou Mac et souris)

Utilisation du ContentView en Adaptive Design

Souvent pour s’adapter correctement à la device, sa taille, son orientation etc, il est nécessaire plutôt que des contorsions en XAML de concevoir son UI par blocs interchangeables.Dans ce cas l’outil le plus pratique est le contrôle ContentView.

En reprenant l’exemple du Color Picker on pourra ainsi concevoir une version simplifiée pour smartphone et une version plus complète pour les écrans plus grands. Charger l’une ou l’autre de ces versions selon le contexte est très simple comme nous l’avons vu dans les sections précédentes.


Ici la méthode AddColorPicker (dans le code-behind) instancie une version conçue pour le Touch ou pour la souris selon l’Idiom de la device.

Cette stratégie fonctionne très bien en MVVM puisque ce qui est de la responsabilité de l’UI peut être entièrement traité par le code-behind, le ViewModel n’ayant pas à connaître les aspects visuels.

Les pages personnalisées

En dernier recours il est tout à fait légitime de prévoir des pages totalement différentes selon les contextes. Mieux vaut une page pour le mode portrait et une autre pour le mode paysage qu’une seule page XAML totalement délirante accompagnée d’un code-béhind alambiqué et difficile à maintenir.

MVVM se satisfait très bien de cette situation puisque justement le ViewModel n’a rien à savoir de la View qui l’utilise.

Dans le cas le plus simple il suffit d’instancier le ViewModel en créant la Page, mais dans la réalité en utilisant une toolbox de type Prism par exemple l’implémentation sera légèrement différente. Voici la version simple :

Conclusion

De base les Xamarin.Forms nous donne tout ce qu’il faut pour faire de l’adaptive design. Il suffit juste de s’en servir !

Il existe bien d’autres techniques et d’autres astuces, certains contrôles comme les grilles ou les grilles relatives sont de précieux alliés. Toutefois souvent ces contrôles entraînent une complexification de la logique de la mise en page et rendent l’ensemble moins maintenable que des ContentViews différenciés ou même des pages différenciées.

A vous de bien choisir vos armes !

Stay Tuned !

Catégories: Dévelopement

Des UI super pros en Xamarin Forms

Dot.Blog - ven, 03/11/2017 - 01:58

Tout coder en cross-plateforme même les UI c’est fantastique, mais est-ce que les Apps ont un bon look ? Et est-ce possible d’obtenir un niveau pro juste avec du code commun ? Quelques exemples vous prouverons que oui…

L’UI, la reine du XXIème siècle

Si on commence à se préoccuper de l’UX car les utilisateurs veulent des applications faciles à utiliser sans manuel de 200 pages posé sur les genoux, l’UI est comme une reine flamboyante. Fille informatique du Design, elle se confond entre reine de beauté et vendeur d’encyclopédie à domicile… C’est elle la reine du XXIème qui sera designé ou ne sera pas !

L’apogée du consumérisme, la cristallisation de nos fantasmes, de nos envies et de celles qu’on nous impose à “l’insu de notre plein gré” !

Vendeur d’encyclopédie à domicile car une belle UI est vendeuse, elle vaut tous les baratins des meilleurs bonimenteurs (et il y a le mot “menteur” dedans !).

Reine de beauté car oui, pour séduire, comme dans certains quartiers louches, c’est la plus belle qui se vend le mieux… Donc pour vendre son baratin l’App se doit d’être belle et pour cela son enveloppe visible, telle une Nabilla de pixels, doit passer par un chirurgien esthétique qui la gonfle ici ou là d’effets hypnotiques (Nabilla c’est juste pour l’exemple mais je vous la laisse sans problème…).

Donc faire de belles UI est indispensable.

Or les Xamarin Forms en créant une abstraction au-dessus des systèmes natifs peuvent être vues comme une forme de limitation. Ce qui les relèguerait au rang d’outil pratique pour créer des prototypes ou des petites Apps internes.

Ce qui n’est bien entendu pas le cas.

Je ne listerai pas ici tout ce qui permet d’atteindre un haut niveau de perfectionnement des UI avec les Xamarin Forms mais ce ne sont pas les moyens qui manquent. En tout cas si vous faites une App qui est moche cela serait vraisemblablement plus révélateur de votre manque de don en design que du manque de possibilités offertes par les Xamarin Forms…

Des preuves ? Des idées ?

Nous sommes là pour ça aujourd’hui. Avoir des preuves que les Xamarin Forms permettent bien d’atteindre le niveau de séduction désiré. Et aussi pour avoir des idées à repiquer pour nos propres Apps.

Pour cela rien de mieux que de regarder ce que d’autres ont fait et qu’ils ont eu la gentillesse de bien vouloir partager. Car c’est en étudiant le code source d’Apps bien faites qu’on comprend le mieux comment exploiter les astuces et le savoir-faire qu’elles renferment.

BikeSharing

BikeSharing360 est une application fictive de gestion de parc de vélos partagés dans une ville. Gestion des utilisateurs, des disponibilités, interaction avec des Maps, beaucoup de choses à voir et à repiquer donc.

Cette App fonctionne sous Android, iOS et UWP elle montre principalement :

  • Les animations personnalisées en XAML
  • La personnalisation des Maps

Et on la trouve avec son code source ici : https://github.com/aloisdeniel/Microcharts.Samples

Bikr

Décidemment les vélos inspirent les designers ! Ici il s’agit de gérer l’activité d’un pratiquant de la petite reine. Si l’App semble bien dopée c’est certainement pour rester fidèle au sujet traité !

Cette App couvre aussi les trois mêmes plateformes et montre surtout comment exploiter les Charts avec SkiaSharp.

On trouve son code ici : https://github.com/Microsoft/BikeSharing360_MobileApps

GreatPlaces

Sorte de catalogue d’endroits remarquables, cette App utilise principalement une ListView avec fond transparent. Tournant sous les trois mêmes plateformes elle montre en particulier comment utiliser des ViewCell personnalisées.

Tournant sur les trois plateformes aussi cette App démontre principalement les ViewCell personnalisés.

On la trouve là : https://github.com/kphillpotts/XamarinFormsLayoutChallenges

InAnger

Il s’agit d’un ensemble d’exemples démontrant que Xamarin.Forms peut autoriser la conception de look & feel tout à fait modernes et attrayants. La plupart de ces exemples tournent sur Android et iOS, la plateforme UWP n’ayant pas été ciblée car les mises en page proposées sont typiquement pour smartphone (mais rien ne vous empêche de rajouter UWP à ces projets).

Trouver un véto (Find a Vet), Phoenix Peaks, Jobberr, Woofer… sont autant d’Apps individuelles qui chacune montre des techniques de mise en page efficaces.

On retrouve l’ensemble ici : https://github.com/awolf/Xamarin-Forms-InAnger

Instagram

Pic et pic et Instagram ! Mais là pas besoin de choisir puisque les 3 plateformes sont ciblées. On y démontre principalement les Entry personnalisés pour la saisie et le contrôle Circle Images permettant d’afficher des images dans des cercles, présentations très à la mode sur smartphone.

Le source est à télécharger ici : https://github.com/adamped/Instagram


Social Media

Concevoir une page de type profil de réseau social qui a un look moderne, c’est un exercice limitatif mais qui saura vous inspirez (par exemple profils utilisateurs dans une App LOB, trombinoscope…).

Parmi les techniques démontrées on trouve :

  • Entête incurvée
  • Image de profil qui vient se placer sur l’entête

On trouve le code ici : https://github.com/kphillpotts/XamarinFormsLayoutChallenges

KickassUI.RunKeeper

Une App pour sportifs, version Xamarin Forms de RunKeeper.

Android et iOS sont ciblés (on peut difficilement aller courir son jogging avec un PC sous le bras…).

Les points principalement démontrés sont :

  • Les Tabs personnalisées
  • L’utilisation de fonte personnalisées
  • Le Carrousel
  • Les Maps personnalisées
  • L’utilisation d’un logo personnalisé

Le code est à disposition sur github comme le reste : https://github.com/sthewissen/KickassUI.Runkeeper

KickassUI.Spotify

Une version Xamarin Forms de l’App Spotify bien connue.

Parmi les choses intéressantes montrées par cette App :

  • La barre de navigation translucide
  • Fond d’écran flouté
  • Slider personnalisé

Et le code : https://github.com/sthewissen/KickassUI.Spotify

KickassUI.Twitter

Dans la même série une version Xamarin.Forms de l’App Twitter pour Android et iOS.

Des choses intéressantes à voir :

  • Le bouton d’action flottant sous Android
  • L’icône personnalisée dans la MasterDetailPage
  • Les Tabs avec couleur personnalisée

Un code source à examiner ici : https://github.com/sthewissen/KickassUI.Twitter

Timeline

Une gestion d’activités dans le temps. Idée à reprendre pour l’agenda d’une journée de congrès, les étapes d’une journée de voyage, la répartition avec horaires des cours d’une journée de classe… Les idées ne vous manqueront pas j’en suis certain !

Les trois plateformes sont ciblées et on peut voir quelques techniques comme l’utilisation des Header et Footer de la ListView et les ViewCell personnalisées.

Un projet sur github que les autres : https://github.com/kphillpotts/XamarinFormsLayoutChallenges

Xamarin.NetFlix

Comme son nom l’indique, une App Xamarin.Forms qui reprend le fonctionnement de celle de NetFlix.

Des choses à voir comme :

  • La gestion d’une liste horizontale
  • La barre de navigation transparente sous Android et iOS
  • L’effet de paralaxe
  • Les listes multi-colonnes

Le code source : https://github.com/jsuarezruiz/xamarin-forms-netflix-sample

Facebook

un autre grand classique refabriqué en Xamarin.Forms. Des idées à reprendre comme :

  • la Slide bar à droite
  • La disparition de la barre de navigation
  • Les animations du bouton Like


Le code à étudier : https://github.com/XAM-Consulting/FacebookForms

Movies

Et pour finir quelque chose d’assez différents dans les cibles supportées ! En effet, Movies est une application utilisant une UI GTK sous Xamarin.Forms ciblant Linux, macOS et Windows. Le cross-plateforme c’est aussi ce genre d’Apps…

L’intérêt se trouve ici bien entendu dans l’utilisation de GTK et des cibles supportées ainsi que :

  • L’utilisation intelligente de la MasterDetailPage
  • Les Maps
  • Les thèmes GTK
  • L’utilisation de la base de données en ligne The Movie Database

Un code source à télécharger et étudier : https://github.com/jsuarezruiz/xamarin-forms-gtk-movies-sample

Conclusion

Ce n’est pas une conclusion mais un commencement ! Avec les Xamarin.Forms et un peu d’imagination on peut tout réaliser, en cross-plateforme natif. On peut faire du beau, du vendeur, de l’original, sans non plus écrire des tonnes de code natif planqué sous la moquette… Bien utilisés les contrôles et les niveaux de personnalisation offerts permettent d’atteindre presque tous les objectifs. Et si code natif il doit y avoir, il est clairement séparés du reste, bien identifié et lui aussi écrit en C#/.NET tout en bénéficiant de 100% de l’API de la cible.

Il est clair qu’ici on se retrouve avec la même problématique que sous WPF, Silverlight ou UWP. Avec les contrôles de base, un développeur peu doué en design produira des applications ternes ressemblant à un utilitaire Windows 95 ….

On ne peut pas tout savoir faire, le design est un métier. Il ne faut hésiter à se faire aider par un designer professionnel ou un infographiste pour concevoir le look & feel d’une App.

Le problème en réalité n’est ni l’outil ni de ne pas savoir créer des designs magnifiques, c’est celui de ne pas savoir se faire aider sur ce qu’on ne sait pas faire.

Alors si vous n’arrivez pas à produire des UI très originales sachez utiliser les compétences d’un spécialiste et concentrez-vous sur votre métier, à savoir comment implémenter de telles UI en C# et en XAML. Ca sera déjà beaucoup, et avec le temps peut-être vous viendra-t-il une certaine aptitude à produire vous aussi des UI de luxe.

Et si vous êtes déjà un développeur touché par la grâce du design, alors inspirez-vous de tous les exemples présentés ici et éclatez-vous !

Bon design

Stay Tuned !

Catégories: Dévelopement

Convertisseur Json vers C# en ligne

Dot.Blog - jeu, 05/10/2017 - 18:47

Convertir du JSON en classes C# immédiatement exploitables peut se faire à la main, mais c’est ennuyeux, long et il est facile de faire des erreurs. Une petite astuce très simple pour aujourd’hui : QuickType.

JSON

JSON est un format de sérialisation plus que populaire. Pour des tas de raisons assez peu rationnelles à mon sens, mais c’est ça la mode, il est devenu plus “hype” que XML tout en faisant la même chose et en étant presque aussi verbeux. La mode a ses mystères que la raisons ne saurait connaître aurait pu dire le poète…

Quoi qu’il en soit JSON c’est bien, efficace, ça marche, et c’est beaucoup utilisé. D’excellentes raisons de s’en servir. Mais aussi d’être confronté qu’on le veuille ou non à ce format.

Donc JSON c’est comme XML, des balises, des attributs, des imbrications pour les collections, etc. La différence majeure c’est un peu la même qu’entre Pascal Objet et Java, dans l’un on écrit en toutes lettres Begin/End pour un bloc de code, dans l’autre on utilise des accolades { et } et le développeur croit avoir pondu un code plus court, exploitant ainsi la pensée magique à l’œuvre chez l’humain de base.

Sauf que les fameuses accolades qu’on dit “américaines” ne portent pas ce nom pour rien : elles sont accessibles directement sur un clavier QWERTY mais réclament toute une gymnastique sur un clavier AZERTY, un peu dans le style de ce qui faisait la moquerie de la combinaison CTRL-ALT-DEL. Mais ce dernier est mal car datant d’une époque où les français avaient encore une âme et un jugement sur les excentricités yankies, les accolades américaines c’est bien car ça date de l’époque où l’Aile ou La Cuisse est devenu un nanar, Coluche est mort et McDo a enfin réussi à envahir le pays devenu depuis une province des USA. En gros rappelez-vous quand dans notre monde moderne, tout ce qui est américain datant de moins de 30 ans est le bien et que le reste est généralement le mal, voire le mal absolu. C’est simple à piger en fait.

Du coup, il faut sérialiser en JSON pour être cool.

Or .NET avait plutôt été pensé pour la sérialisation XML. Ce qui était logique. Et quelques attributs bien placés sur une classe existante suffisaient à pouvoir la sérialiser / désérialiser sans trop de soucis.

Mais comme comme rien n’est parfait, JSON est alors venu s’insérer dans les quelques failles du support XML de .NET (un peu lent et ne gérant pas bien certains cas, null, références circulaires…). Et il s’avère surtout qu’un jour est né la fameuse librairie NewtonSoft.JSON. Rapide, performante, couvrant plus facilement les collections, les imbrications, les références circulaires, etc.

Ainsi est né l’avènement de JSON même sous .NET.

Sérialiser est une formalité, en XML comme en JSON, cela produit un fichier texte lisible facilement et transmissible via HTTP ou TCP par exemple. Et c’est devenu l’une des façons de s’en servir la plus fréquente.

Mais à la réception… ça se corse un peu.

Désérialiser JSON

XML ou JSON sont des formats texte décrivant des objets avec leurs attributs et leurs valeurs. Désérialiser est donc une opération consistant à instancier des objets en mémoire.

Autant lorsqu’on sérialise le problème ne se pose pas (puisqu’on sérialise un objet existant, son existence ne pose pas de question), autant lorsqu’on désérialise se pose la question de l’existence des classes qui vont donner naissances aux fameuses instances, le résultat de la réhydratation.

Au sein d’une même application utilisant JSON ou XML comme support de sauvegarde (état de l’application, préférences utilisateurs…) la question ne se pose toujours pas, les classes sérialisées existent donc et sont réutilisées pour désérialiser.

En revanche le problème devient plus épineux lorsqu’une application reçoit de l’extérieur des données exprimées en JSON. Ces données n’ont pas forcément d’équivalent sous forme de classe dans le code. Et c’est un cas très fréquent.

Donc cela est souvent nécessaire.

Une étape essentielle s’impose alors : transformer du JSON en classe(s) pour enfin pouvoir désérialiser ce dernier…

Le faire à la main est possible comme je le disais mais c’est peu pratique et cela laisse la porte ouverte à des erreurs.

Création de classes automatique

Le plus simple serait de partir d’un exemple de texte JSON et de le traduire en une classe C# (ou autre) puisque JSON tout comme XML est auto-descriptif. D’autant que les petits objets sont simples à convertir à la main mais que les utilisations de JSON dans les web services se fait plutôt par le biais de réponses très verbeuses. Prenez les événements Github par exemple,c’est presque une vingtaine de classes dont certaines avec des dizaines de propriétés.

Il faut un outil automatique pour cela.

QuickType

Il existe déjà un site web json2csharp.com dont j’ai déjà parlé qui remplit à merveille cet office. Mais il est très simple et ne supporte que C#.

Il y a aujourd’hui un service beaucoup plus complet qu’on trouve sur https://quicktype.io

Cela ressemble à ça :

Avec des petits plus notamment le choix du langage comme C#, TypeScript ou Java. Mais on peut aussi extraire le schéma ce qui peut être très utile (validation de données par exemple avant réhydratation).

Mieux le code généré peut être légèrement adapté selon qu’on le veuille plus compact, fidèle à C# 5 ou 6, qu’on préfère des arrays ou des List<T> etc.

Conclusion

Rien de bien extravagant dans QuickType, mais comme JSON est incontournable, autant utiliser les bons outils qui font gagner le plus de temps (pour déguster son McDo tranquillement) !

Les canicules sont terminées mais on oublie souvent qu’il faut en hiver aussi beaucoup s’hydrater. C’était le conseil santé du jour (sponsorisé par NewtonSoft.JSON et par Coca-Cola en associant avec la World Company).

Hydratez-vous et Stay Tuned !

Catégories: Dévelopement
S'abonner à Sleepy SME agrégateur - Dévelopement