Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Le Web 3.0 = Pas de Web ?

[new:30/05/2012]En attendant de pouvoir sérieusement vous parler de WinRT, je m’intéresse beaucoup en ce moment à l’avenir du développement, tant pour les développeurs que les éditeurs dans la période très troublée que nous vivons depuis deux ans. Depuis plusieurs mois je vous fais part de mes observations, de mes doutes, de mes conseils et j’espère vous aider par mes réflexions à vous forger votre propre opinion. Souvent en décalage avec la pensée unique de l’instant, mes prévisions choquent parfois certains lecteurs. Force est de constater que le Web, donc HTML, a des soucis à se faire et j’en veux pour preuve de nombreux évènements qu’il faudrait être fou d’ignorer...Plus...

HTML 5 : la tragique fin d’un buzz

[new:30/04/2012]HTML 5, l’un des plus gros buzz sur du vaporware des vingt dernières années... Ce buzz prend fin de façon tragique. Il faut rapidement s’en rendre compte pour prendre les bonnes décisions pour le futur de vos développements !Plus...

Silverlight : accéder à l’IP du client (version 2)

[new:30/06/2011]Accéder à l’IP du client est parfois nécessaire, Silverlight étant une technologie côté client tournant dans une sandbox cette information ne lui est pas accessible. Dans un précédent billet je vous ai montré la façon classique, via un service Web, d’obtenir l’IP du client. Aujourd’hui je vous propose une astuce d’un style très différent.Plus...

Quand browsers et proxies jouent à cache-cache avec vos Xap...

[new:30/06/2011]Lorsqu’on travaille avec Silverlight on peut facilement devenir fou à cause d’un proxy ou d’un browser dont le cache est mal géré. En vous resservant un vieux Xap sans vous le dire, vous avez l’impression que votre session de debug ne sert à rien ou bien vos utilisateurs vous décrivent des bugs pourtant réglés depuis un moment... Dans tous les cas un proxy (ou un browser) est en train de jouer à cache-cache avec vos Xap et vos nerfs !Plus...

Le retour du spaghetti vengeur

Le code spaghetti est de retour ! Fuyez braves gens !

Sous-titré : Du Rififi dans le Xaml.

Avertissement au lecteur : ce billet, bien que bâti sur un fond technique préoccupant et une expérience réelle, utilise un formalisme un peu romancé. Ne cherchez pas d’extraits de code ici. Mais si vous avez un peu de temps, laissez vous porter par l’histoire. Si vous êtes pressés, revenez plus tard lire ce billet !

Genèse d’un malaise

Comme vous le savez je suis un passionné de WPF et de Silverlight, la puissance de Xaml servi par un Framework aussi riche que .NET et des outils de qualité comme Blend ou Visual Studio ne peuvent laisser de marbre (comment peut-il y avoir encore des gens travaillant sous Java ou Delphi ?). J’en suis tellement passionné que j’évangélise à tour de bras, ici et ailleurs, et que mes compétences autant techniques que de gardien des brebis égarées me valent d’avoir l’honneur d’être Microsoft MVP, notamment en 2010 pour les technologies de développement d’applications clientes (Client Application Development, “CAD”" MVP).

Bref, si je dis tout cela c’est pour faire comprendre que bien que cultivant mon objectivité comme un joyau précieux garant de la liberté de mes neurones, je suis plutôt “pro” Microsoft et que, bien entendu, cela peut déplaire à certains comme en séduire d’autres… La diversité du monde en fait sa richesse, isn’t it.

Et un partisan de Microsoft, MVP de surcroît, fan de Silverlight, ne dira jamais le moindre mal de sa technologie fétiche… Et soyez-en convaincu je ne briserai pas cette loyauté, essentielle à mes yeux, mais il faut pourtant savoir tirer les sonnettes d’alarme de temps en temps. D’ailleurs c’est une question de crédibilité, que vaudrait un expert sans liberté de parole ni de pensée… Et puis au fond vous verrez que c’est bien plus, comme à chaque fois, l’humain qui en prend pour son grade dans ce récit que les outils, innocents, par nature.

Tout cela pour parler franchement d’un risque, d’une dérive, et surtout d’un grand danger : le retour du code spaghetti ! Et, comble de l’infamie, la peur de cette tare qu’on croyait du passé, je ne la brandis pas à propos de langages ésotériques comme F#, ou de solutions vieillissantes comme Java. Non. Le drame est bien là : c’est de WPF et de Silverlight dont je veux vous entretenir, et ce, au travers d’une anecdote récente.

J’ai fait il y a quelques temps un audit dont je tairais, vous le comprendrez aisément, le nom du client visité ainsi que la date exacte. Au demeurant une société ni trop jeune pour n’être pas assez structurée, ni trop vieille pour en être devenue ringarde. Une entreprise de bonne taille, assez dynamique et assez typique de ma clientèle, se targuant de posséder une équipe de développement à la pointe du progrès, la preuve, puisque maniant les balises Xaml avec la même dextérité que la truelle l’est par un vrai maçon diplômé.

Le trait n’est pas forcé, il n’y en a nul besoin. Ce fut au début un audit “classique” c’est à dire durant lequel j’ai vu du code “normal” donc assez médiocre. Je dis “normal” au sens de la loi normale statistique ce qui signifie que grâce à  messieurs Laplace et Gauss il m’arrive de voir des choses épouvantables comme de pures merveilles, mais que ces deux cas représentent un pourcentage faible au deux bouts de la cloche… Je ne savais pas encore que j’allais atteindre le bout de la cloche. Le mauvais. Bien entendu.

Espèce de spaghetti !

Le code “normal” est médiocre généralement. C’est finalement une définition en soi. Le code exceptionnel, étant, par le même genre de raisonnement, plus rare. C’est finalement une lapalissade. Donc, en général, je vois du code médiocre, donc normal (dans l’autre sens c’est intéressant aussi, non ?).

Et j’appelle médiocre un code qui se caractérise par plusieurs aspects distinctifs très techniques que je détaille avec moult délicatesse dans mes rapports d’audit pour expliquer les choses en y mettant les formes mais qui se résument en général à quelques cas généraux qu’on pourrait caractériser très doctement. Je m’exprimerais ici de façon bien plus directe puisqu’on est “entre nous” :

  •  
    • La “putain” c’est à dire le code sur lequel tout le monde est passé, sauf le train et vous, mais ça, c’est même pas sûr, puisque vous êtes là… C’est du code typique des boîtes où les gens sont mal payé et où les salariés défilent plus vite qu’une hirondelle dans un ciel de printemps…
    • Les migrations de migrations de portage d’intégration (de milles sabords, version 24 bis modifiée E). En général du code qu’on trouve dans les administrations. Avec des documentations de plusieurs centaines de pages, que personne n’a jamais lu bien entendu.
    • Le code mille-feuille. Savoureuse pâtisserie constituée de tant de couches qu’on ne peut les compter, comme les pattes du iule (autrement appelé mille-pattes). C’est un peu un mélange des deux précédents mais en plus structuré que le premier (beaucoup plus, et c’est la son problème) et en moins documenté que le second (beaucoup moins, et c’est aussi là son problème). C’est du code de SSII “in” avec de vrais morceaux de “nouvelles technos” dedans.
    • Le code “start-up”, celui-là est bourré de technos innovantes, hélas non maîtrisées, peu documentées et en bêta ne tournant que sur les versions US de l’environnement. Un code d’essayiste pur travaillant pour la beauté du discours qui va autour plus que pour l’efficacité, des gens qui devraient être en agence de pub plutôt que devant un environnement de développement.
    • Le code à papa, ou l’objet est utilisé comme du C procédural. C’est le code C# écrit par de vieux delphistes ou cobolistes reconvertis sur le tard par exemple.
    • Le code d’ingénieur, un des pires. Sortant de l’école et voulant montrer ses muscles en complexifiant tout et l’enrobant dans une prose technique pleine de sigles bizarres et de référence à des bouquins lus de lui seul et de ses potes de promo. Quand il arrêtera de sucer son pouce, il deviendra un bon développeur sévèrement burné comme disait Tapie. Mais en attendant son code c’est l’enfer…
    • Et enfin, le célèbre, le magnifique, le code spaghetti, marquant l’incompétence à maîtriser la complexité du sujet. Celui-là est typique des mauvaises équipes, tous contextes confondus.

Il y en a bien d’autres dans mon bestiaire, en 20 ans d’audit vous imaginez ce que j’ai pu voir (heureusement je rencontre aussi des équipes compétences et même parfois de l’excellent code, sinon ça serait désespérant !).

Et WPF et Silverlight dans tout ça ?

C’est là que je voulais en venir, mais il fallait bien passer par ce détour pour vous plonger dans l’ambiance trouble de cette descente aux enfers binaires. Sinon cela aurait été d’une platitude redoutable. Un peu de lecture ça change des extraits de code en Xaml. Justement. Parlons de lui et de ce dernier audit (qui n’est pas le dernier, confidentialité oblige comme je le disais plus haut). Disons que c’est assez récent pour être en Xaml mais pas suffisamment pour être en Silverlight 3.

Qu’avait ce code qui vaille ce billet un peu particulier ?

Le code qui rend fou

il m’a rendu fou. Tout simplement ! Et en plus il m’a filé les chocottes !

WPF et Silverlight sont des technologies merveilleuses, Xaml a un pouvoir descriptif exceptionnel à tel point qu’il permet d’économiser beaucoup de code behind.

Malgré le génie des équipes MS ayant travaillé sur le Framework j’aurais malgré tout préféré que cette révolution se fasse à 100% dans le respect du paradigme objet et du fortement typé. Or ce ne fut pas totalement le cas, et si je comprends bien les contraintes techniques sous-jacentes qui ont interdit cet idéal, certains choix sont hélas autant de portes ouvertes sur des risques que je viens de palper de près. Et ça fait peur.

Il y a en premier lieu l’architecture. Il ne suffit pas de prendre Prism et ses Dll pour avoir un bon logiciel. Il faut comprendre et maîtriser la chose. Ce qui ne s’improvise pas. Mais il y a pire, car plus lié à la technologie elle-même.

Par exemple, prenez la syntaxe du Binding, en Xaml donc. Vous avez une balise, vous la complétez d’une propriété et là, au lieu de mettre une valeur, vous ouvrez des accolades américaines suivies du mot Binding, le tout entre guillemets, une simple chaine de caractères. Quant à ce qu’il y a après le mot Binding, je suis convaincu qu’aucun aficionado de WPF ou de Silverlight n’est capable de me citer de tête toutes les combinaisons possibles et astuces disponibles. Parfois  c’est {Binding} tout court, parfois c’est une longue phrase intégrant imbriquées d’autres accolades faisant référence à des ressources statiques ou dynamiques, des paramètres, des convertisseurs, etc… Une puissance énorme, un peu comme les expressions régulières : puissant mais pas très clair (et c’est un euphémisme). Pas clair, on peut s’y faire… mais pas clair et pas fortement typé ni même contrôlé, c’est là que la chute aux enfers commence…

Le code que j’ai audité était bourré d’element binding, de datacontext pointant des conteneurs de services avec des indirections dans tous les sens “pour la souplesse”. Quand MVC et MVVM ne sont pas compris, mieux vaut tout mettre en procédural dans le code-behind de chaque fiche, c’est plus simple à débugger ! Le pire c’est que chacun dans l’équipe y allait de sa petite couche, de sa petite modification. Et je fais du “refactoring” par là, et je refactore par ici… Oui mais voilà, dans les balises Xaml ça commence à danser le cha-cha-cha toutes ses chaînes de caractères non contrôlées, tous ces paramètres de convertisseurs qui ont évolués sans qu’on ait mis à jour les références dans le Xaml, ces ressources statiques et d’autre dynamiques dans des dictionnaires chargés dynamiquement !

Le soft ne tenait plus que par un fil qu’un joyeux drille a du couper juste avant que je n’intervienne. Dommage. Je n’arrivais même pas à dépasser un ou deux écrans avant que ça me pète à la figure. Même avec des outils très intelligents comme NDepend, comprendre le soft était virtuellement impossible.

Quant à savoir d’où vient “le” problème ! C’est le soft lui-même tout entier qui était “le” problème… Ainsi que ceux l’avaient écrit (et ceux qui les dirigent, car un mauvais soft est toujours la cause d’une mauvaise direction bien plus que de mauvais développeurs).

En fait, le Binding Xaml est une porte ouverte sur l’inconnu. Une feature d’une grande puissance, sans laquelle beaucoup du charme disparaîtrait, mais assez déraisonnable dans cette implémentation libre sous forme de chaînes de caractères non compilées. La porte sur le néant, l’incontrôlé, et pire : l’incontrôlable. Un trou noir syntaxique. La damnation du testeur envoyé moisir au purgatoire des pisseurs de ligne. Et l’enfer de l’auditeur.

le Binding au pays des X-Files

Le Data binding Xaml est une jungle syntaxique pas très bien … balisée et totalement déconnectée de toute forme d’analyse à la compilation. du “Late Bugging” comme je m’amuse à appeler cette stratégie de type “late binding”, principe de ligature tardive utilisé d’ailleurs en d’autres endroits et même sous d’autres frameworks. Pire que les Dynamic de C# 4 (pratiques mais dangereux), pire que F# (stimulant mais pas industrialisable), le Binding de Xaml est un gouffre à bugs, un chien fou s’il n’est pas tenu en laisse fermement.

En réalité un marteau ne pourra jamais être jeté aux fers (!) pour le meurtre de qui que ce soit. Un marteau est un outil, et même s’il a servi et servira encore dans de nombreux crimes, un outil est un objet sans âme, sans conscience et donc sans responsabilité. Même un fusil mitrailleur est un objet innocent, même un canon de 105 ou une bombe atomique sont plus innocents que l’agneau qui vient de naître et qui, comme tout être vivant, et à la mesure de son intelligence, portera le poids de la responsabilité de ses agissements. Un outil de développement restera donc à jamais hermétique à tout procès d’intention. A celui qui s’en sert de le faire correctement.

Il en va de même de Xaml, de son data Binding et de bien d’autres de ces facettes. La responsabilité incombera toujours à l’humain qui tient le marteau. A l’informaticien qui tient la souris. Au développeur qui tape un code affreux.

Mais certaines features de Xaml, certains choix conceptuels comme l’utilisation de chaînes de caractères non contrôlées et non parsées à la compilation sont à mon sens des erreurs. Si des projets comme celui que j’ai audité et dont je vous parle ici devenaient courants, nul doute que cela signerait l’arrêt de mort de WPF et de Silverlight. La faute aux mauvais développeurs ? Pas seulement. A ceux aussi qui ont décidé de programmer Xaml de cette façon trop ouverte, trop permissive. On voit bien comment Silverlight a été verrouillé dès le départ par Microsoft. Si le moindre virus, le moindre phishing avait été réalisé avec Silverlight 1 ou 2 c’en était fini des espoirs portés par cette technologie. Microsoft a été méfiant pour préserver l’avenir de la technologie et c’est une bonne chose. Ce que j’ai vu dans le projet WPF dont je parle ici, c’est un peu de la même nature, mais à l’inverse : Microsoft n’a pas verrouillé Xaml comme cela a été fait avec Silverlight. Et si de tels détournements se généralisent c’est toute la technologie qui trinquera. D’ici un an environ, lorsque les projets lancés ces derniers temps seront finalisés, et qu’il faudra compter ceux qui n’aboutiront pas ou qui ne marcheront jamais bien, la note peut être salée pour Xaml. Microsoft a pris un sacré risque en faisant des choix de conception comme celui des balises non compilées (et dans lesquelles même Intellisence se prend les pieds dans le tapis).

Déjà sous Delphi je voyais souvent ce genre de code spaghetti avec des variables globales référencées n’importe où, des fiches utilisant des variables d’autres fiches jusqu’à créer des chaines de dépendances ingérables. J’ai vu des codes de ce type ne pouvoir jamais aboutir. Il m’est même arrivé une fois de réécrire en 15 jours proprement à partir de zéro un soft développés en 1 an par deux personnes sans le dire au client histoire que les 15 jours d’expertise qu’il m’avait payés servent à quelque chose… Je tairais ici le nom du client (une administration). J’étais plus jeune et je voulais me prouver des choses certainement, mais personne ne l’a jamais su jusqu’à ce billet (et encore vous en savez peu!). En tout cas ce projet là je l’ai sauvé. Mais être un pompier de l’ombre n’est pas ma vocation. Les gars étaient malgré tout étonnés ne pas vraiment s’y retrouver dans “leur” code. Amusante situation. Je n’avais rien gardé de “leur” code :-) Mais le soft marchait…

Mais avec Xaml, et une puissance décuplée, je viens de voir des horreurs du même genre alors que depuis des années, je commençais à trouver que C# incitait plutôt à faire du code “correct”, le niveau étant globalement meilleur que celui que je voyais sur Delphi. Et patatras ! Xaml arrive avec ces chausses-trappes dans lesquels les développeurs s’engouffrent. La faute à Xaml ? Pas totalement, mais si tout était typé et contrôlé à la compilation certaines mauvaises utilisations ne seraient pas possibles. Après tout, le fortement typé en soi ça ne sert à rien si on suppose que tous les développeurs sont “bons” ! Mais tous les langages modernes tentent de l’être car on sait que l’humain est faillible. En créant une brèche incontrôlable dans un édifice aussi beau de Xaml, ses concepteurs ont fait un pari risqué. Celui que tous les développeurs sauraient maîtriser le potentiel sans tomber dans ses pièges. Un pari forcément perdu d’avance.

Vision d’horreur

Ce que j’ai vu est donc indescriptible. Un peu comme si j’essayais de décrire Cthulhu. Ceux qui ont essayés sont souvent morts avant de finir d’écrire son nom (ah Lovecraft…) !

Imaginez vous un logiciel de 250 fiches WPF environ utilisant de l’ADO.NET, des bouts de LINQ to SQL, et des nouveautés en Entity Framework, le tout à la sauce Prism / MVC (mais en ayant lu le manuel certainement à l’envers car Prism c’est très bien !) avec des tentatives d’inversion de contrôle (et des dérapages non contrôlés) farci d’un code Xaml bourré de Binding renvoyant vers on ne sait quoi (et hélas pas contrôlé à la compilation), le tout planqué dans 4 ou 5 couches DAL, BOL pré-BOL, post-BOL, et j’en passe, histoire de faire court. La note s’élève a 6000 jours/homme (5 ans/homme environ). Pas un truc gigantesque mais qui commence à faire mal au budget malgré tout.

Agrémentez le tout de deux systèmes de versionning dont aucun n’avait vraiment une version complète du soft, des essais épars de tests unitaires avec MbUnit et VSTS. Vous obtiendrez le tableau. Une œuvre qui dépasse le classicisme habituel de ce point de vue, plus proche du Cubisme que de l’Hyperréalisme tout de même, avec au moins la bonne volonté de faire des petites choses (du mauvais testing prouve au moins qu’on a essayé de tester, ce qui est encore bien rare…). Mais l’enfer est pavé de bonnes intentions, c’est un peu ça le problème.

Le code était impossible à maintenir, les problèmes de performances impossible à cerner sans y passer plus de temps qu’à toute refaire, le code Spaghetti, avec un grand S avait frappé de son coup de poignard vengeur et lâche dans le dos. Une complexité non maîtrisée qui tel l’horizon d’un trou noir aspirait irrémédiablement le bon code vers l’enfer central laissant le hasard faire le tri entre les chemins à prendre… Démêler l’écheveau n’était pas possible, pas plus que de formuler des guidelines sérieusement applicables dans un tel contexte ni aucun conseil pour se sortir d’une telle situation.

Vous imaginez peut-être l’horreur qu’a été l’écriture du rapport d’audit. Entre dire une vérité que personne n’était prêt à entendre et mentir sachant que peu importe ce que je dirais cela passerait mal et qu’au fond mieux valait ne pas trop déplaire… Mon éthique a tranché, j’ai dit la vérité. En l’enrobant. Des heures passées à réécrire deux fois, dix fois certains paragraphes. Ils ne s’en douteront jamais… Et au final un rapport qui sera peut-être classé au fond d’un tiroir car personne ne voulait vraiment savoir ce qui n’allait pas. La remise en question d’un tel échec dépasse de loin le cadre technique et peu de gens savent admettre leurs erreurs, surtout quand toute la chaîne hiérarchique de la base au sommet doit participer à ce questionnement.

Le salaire de la peur

La peur dont je parlais plus haut, les chocottes que cet audit m’a données, c’est d’être confronté au fleuron de la technologie informatique, à des choses en lesquelles je crois car elles marquent un réel progrès et que (bien utilisées) elles permettent justement un code limpide. Cet audit a brisé ce fantasme en me rappelant qu’un marteau pouvait servir au meilleur, comme au crime. Xaml, WPF et Silverlight n’échapperaient pas à la règle et il faudra être vigilant. Surtout que l’avalanche de technologies et de patterns (WCF Ria Services, Entity Framework, MVVM, Prism, …) rendent presque impossible la maîtrise de tous ces sujets. Je suis payé pour ça. Au minimum 50% de mon temps est passé en autoformation pour apporter un conseil éclairé sur les technos à venir. Ce sont les 50% vendus qui financent cette formation et cette recherche permanente. Comment un développeur qui fait ces 48h (35 de base + le dépassement obligatoire non payé car il est aux “cadres”) peut-il se former à tout cela en travaillant sur d’autres projets la journée ? C’est impossible. Et cela créé une situation très dangereuse. Technologie sophistiquée + manque de formation = code spaghetti !

David Vincent au pays des tags

Il était donc urgent de vous en parler, d’attirer votre attention sur certaines dérives, car dans une moindre mesure, je sais, je l’ai vu chez d’autres, ces chausses-trappes savent s’ouvrir sous les pieds des développeurs les mieux formés et les mieux intentionnés !  Je les ai vues, et je dois convaincre un monde incrédule…

Ma mission, que j’ai acceptée (forcément avant de voir, on a pas vu…), était de faire un audit de pré-release. C’est à dire de venir faire le point sur l’état de la situation, les derniers fameux “boulons à serrer” en quelque sorte, et surtout de venir signer un satisfecit au DI, très fier de son bébé (Rosemary’s baby plutôt que Dora de TF1 au final), afin qu’il puisse faire monter sa prime de fin d’année je suppose.

Hélas, déception et vilenie. Ce n’est pas avec le prix d’un audit (fort raisonnable, devis gratuit sur simple demande) qu’on achète ma conscience. Il m’a donc fallu trouver les mots et les formules diplomatiques pour rendre un audit policé et mesuré sur cet édifice in-maintenable, voué à l’échec et bon à mettre à la broyeuse. Ce n’est pas la partie la plus difficile, car tout rapport d’audit se doit d’être policé et tourné de façon neutre et technique. Même si parfois on a envie de crier “bande de nuls !”, non, ce n’est pas bien, on ne le fait pas…

Que les futurs clients ne s’affolent pas trop, ce que je raconte aujourd’hui est malgré tout à classer dans les exceptions, le fameux bout de la cloche de la courbe Normale. Même si je ne suis que rarement content du code que je vois, on est, heureusement en moyenne, assez loin de l’horreur qui justifie le présent billet !

O Tempora, O Mores !

Parfois je rêve, j’imagine un monde où l’un de ces clients m’appellerait en me proposant un pont d’or pour lui avoir ouvert les yeux et l’avoir empêché de plonger plus encore tant qu’il était encore temps… Mais ce n’est qu’un rêve, bien entendu. Je suppose que je n’entendrais plus parler de ce client comme de quelques autres dont, les années passant et les vœux annuels restant sans réponse m’ont forcé à une résignation réaliste. Comme le chantait l’artiste, “il a dit la vérité, il doit être exécuté” !

Hélas, les temps ne sont pas à la prise de conscience ni à la bravoure. Nous vivons une époque de lâches où chacun ouvre son parapluie pour que les gouttes en atteignent d’autres. Forcément celui qui est au plus bas de la pyramide se prend tout sur la figure. Souvent c’est le développeur qui trinque pour une chaîne hiérarchique défaillante qui n’a pas fait son métier et qui n’assume pas ses responsabilités. Un développeur n’est jamais coupable seul d’un mauvais code, c’est toute la chaine de commandement qui faillit.

Il y a encore un rêve que je fais et que j’aimerais voir se réaliser avant ma (encore lointaine) retraite : que les entreprises fassent intervenir un conseil, un auditeur avant que l’irréparable ne soit commis, pas après pour constater les dégâts ! … ça serait tellement mieux et plus gratifiant pour moi et mes confrères ! Conseiller, orienter, former, en un mot aider, c’est tout de même plus chouette que de passer pour le père fouettard et l’inspecteur des travaux finis !

Faut-il brûler Xaml ?

Certes non.

Mais ce que je veux qu’il vous reste de ce récit hallucinant autant que réel, c’est que Xaml est utilisé par certains comme un langage dans le langage. Un moyen de vider le code-behind de son C# pour remplir des balises ésotériques. Un langage dans le langage avec son Binding qui est, telles le sont les poupée Russes, encore un langage dans le langage.

A vouloir tout faire par binding, à tout dynamiser, à appliquer tout Prism et le chargement dynamique des modules, la découvertes des plugins avec MEF, le tout mis en forme façon MVVM, sans compter les ruses purement graphiques du templating sous Blend, des DataTemplate à double face pivotante en 2,5 D, à vouloir appliquer tout cela dans un seul soft sans avoir pris les 2 ou 3 ans nécessaires à acquérir la parfaite maîtrise méthodologique pour faire marcher tout cela ensemble, on peut facilement arriver à une situation désastreuse. Encore plus facilement que sous C, encore plus que sous Delphi, pire que sous Windows Forms. Tout cela n’était que de l’amateurisme face aux dérapages délirants que WPF et Silverlight peuvent permettre… Comment faire des tests unitaires parlants sur des balises de Binding imbriquées à un tel point que même Intellisense de VS s’y perd ?

L’extrémisme essayiste est un fléau dans notre métier. Il m’a toujours effrayé, mais il a toujours eu sa sanction “naturelle” : une technologie qui finit par être si mal utilisée créée une telle publicité négative qu’elle tend à disparaître. Je ne voudrais pas que cela arrive à WPF et à Silverlight qui apportent tant d’autres progrès !

Il faut sauver le soldat Xaml !

Pitié pour Xaml, un bon geste pour WPF et Silverlight : ne laissez pas des sagouins faire du mal à toutes ces belles technologies que Microsoft nous offre depuis quelques années. Laissez leur une chance, celle que les développeurs deviennent plus matures et mieux formés aux méthodologies qui vont avec. Ne commettez pas le crime d’être complice de ce genre de chose. Intégrer les technologies les unes après les autres, ne sautez pas d’une bêta à l’autre sans avoir l’assurance que vous maîtrisez la précédente !

Mieux vaut une application Silverlight fonctionnant avec un Service Web classique et dont les champs sont connectés par code, qui marche et qui est maintenable, qu’une élucubration technologique improbable et non maîtrisée qui s’écroulera comme un château de carte au premier éternuement du premier bug venu…

Un peu de sérieux…

Il ne s’agit pas d’une invitation à la méfiance, encore moins au passéisme. Non, c’est une invitation au professionnalisme : n’utilisez que ce que vous maîtrisez.

Si vous maîtriser le top de la techno, allez-ci, franchement. Si vous avez un petit doute : faites joujou dans une machine virtuelle et produisez du code que vous comprendrez à 100% et surtout que d’autres pourront comprendre pour le maintenir, le faire vivre dans les années à venir.

Le code Kleenex coûte cher, il dévalorise notre métier et les outils que nous utilisons.

Le code spaghetti peut assassiner une technologie.

Codez bien. Formez-vous bien.

Et faites auditer vos projets avant, pas après.

Et Stay Tuned, j’aurais des trucs plus légers à vous dire la prochaine fois !

Silverlight 3 : Styles Cascadés (BasedOn Styles)

Toujours dans ma petite série sur les nouveautés de Silverlight 3 je vais vous présenter aujourd'hui une feature plaisante : les styles cascadés.

En soi rien de nouveau à l'ouest puisque c'est le principe même des feuilles de styles CSS (qui y puisent d'ailleurs leur nom). Mais le CSS s'applique à quelques éléments simples HTML alors que là nous parlons de styles Silverlight, c'est à dire d'objet complexes pouvant définir tout un visuel, animations comprises.

[silverlight:source=/SLSamples/BasedOnStyle/BasedOnStyle.xap;width=405;height=150]

Dans l'application Sivlerlight 3 ci-dessus (fonctionnelle, ce n'est pas une capture écran), vous voyez 4 boutons. Tous sont des boutons standard du framework.

  • Le premier, intitulé "Base SL" possède le style Silverlight par défaut
  • Le second, "Normal" est décoré par le style "BoutonNormal"
  • Le troisième "Gros" est décoré par le style "BoutonGros"
  • Et le quatrième "Alarme" est décoré par le style "BoutonGrosAlarme"

Visuellement c'est plutôt moche, je vous l'accorde, mais le but du jeu est de voir l'effet du cascading styling...

Le style "BoutonNormal" est défini comme suit :

<Style x:Key="BoutonNormal" TargetType="Button">
     <Setter Property="Width" Value="90" />
     <Setter Property="Height" Value="30" />
     <Setter Property="HorizontalAlignment" Value="Left" />
     <Setter Property="VerticalAlignment" Value="Bottom" />
     <Setter Property="BorderThickness" Value="2"/>
</Style>

Là où les choses deviennent plus intéressantes, c'est dans le style "BoutonGros" ci-dessous où l'on voit apparaître l'attribut BasedOn qui permet de fonder le style courant sur celui qu'on indique :

<Style x:Key="BoutonGros" 
         BasedOn="{StaticResource BoutonNormal}"
         TargetType="Button">
  <Setter Property="Width" Value="180" />
  <Setter Property="Height" Value="60" />
  <Setter Property="FontFamily" Value="Comic Sans MS"/>
</Style>

Enfin, le dernier style se fonde lui-même sur le précédent par le même mécanisme, le niveau de cascading n'étant pas limité. On peut voir notamment que le changement de famille de fonte introduit dans le style "BoutonGros" s'est propagé au style "BoutonGrosAlarme" (fonte Comic).

<Style x:Key="BoutonGrosAlarme" 
         BasedOn="{StaticResource BoutonGros}"
         TargetType="Button">
  <Setter Property="Width" Value="160" />
  <Setter Property="Height" Value="40" />
  <Setter Property="FontSize" Value="18"/>
  <Setter Property="FontWeight" Value="Bold"/>
  <Setter Property="Foreground" Value="Red"/>
  <Setter Property="BorderThickness" Value="4"/>
  <Setter Property="BorderBrush" Value="#FFFF0202"/>
</Style>

Voilà, c'est tout simple, mais cela peut radicalement simplifier la création de gros templates pour des applications. Tous les avantages du Cascading Style Sheet de HTML dont l'intérêt ne se démontre plus, mais appliqué à des objets et à la sophistication de Silverlight. Que du bonheur...

Bon Styling,

...Et Stay Tuned !

Silverlight 3 : L'Element Binding

L’Element Binding est une nouvelle feature de Silverlight 3 déjà présente sous WPF.

L’Element Binding définit la capacité de lier les propriétés des objets entre eux sans passer par du code intermédiaire. Cette possibilité existait déjà sous WPF, on la retrouve désormais sous SL3.

Pour simplifier prenons l’exemple d’un panneau d’information, par exemple un Border avec un texte à l’intérieur. Imaginons que l’utilisateur puisse régler l’opacité de cette fenêtre par le biais d’un Slider. (ci-dessous l'application exemple pour jouer en live).

[silverlight:source=/SLSamples/EBinding/EBinding.xap;width=452;height=240]

On place quelques éléments visuels sous le Border (ici des rectangles) afin de mieux voir l’effet du changement d’opacité.

Trois méthodes s'offre à nous pour régler le lien entre le Slider et l'opacité du Border. J'appellerai la première "méthode à l'ancienne", la seconde "méthode du certifié" et la troisième "méthode Silverlight 3". Les trois ont leur intérêt mais si vous êtes très pressé vous pouvez directement vous jeter sur la 3eme solution :-)

Méthode 1 dite « à l’ancienne »

Le développeur Win32 habitué aux MFC ou à des environnements comme Delphi aura comme réflexe immédiat d’aller chercher l’événement ValueChanged du Slider et de taper un code behind de ce type :

MonBorder.Opacity = MonSlider.Value ;

Ça a l’avantage d’être simple, efficace, de répondre (apparemment) au besoin et de recycler les vielles méthodes de travail sans avoir à se poser de questions…

Méthode 2 dite « du certifié »

Ici nous avons affaire à un spécialiste. Son truc c’est la techno, suivre les guide-lines et écrire un code qui suit tous les dogmes de l’instant est un plaisir intellectuel. Parfois ses solutions sont un peu complexes mais elles sont belles et à la pointe de la techno !

Conscient que la solution « à l’ancienne » a un petit problème (en dehors d’être trop simple pour être « belle », elle est one way, le slider modifie l'opacité du border mais l'inverse ne fonctionne pas) il va chercher une solution objet élégante répondant à l’ensemble des cas possibles couvrant ainsi le two way, considération technique trop technophile pour le développeur du cas précédent.

Ici forcément ça se complique. C’est techniquement et intellectuellement plus sexy que la méthode « à l’ancienne » mais cela réclame un effort de compréhension et de codage :

Il faut en fait créer un objet intermédiaire. Cet objet représente la valeur du Slider auquel il est lié lors de son instanciation. Quant à l’objet Border, sa propriété Opacity sera liée par Data Binding standard à l’objet valeur.

Voici le code de la classe de liaison :

public class ValueBinder : INotifyPropertyChanged
       {
             public event PropertyChangedEventHandler PropertyChanged;
             private Slider boundSlider;
             public ValueBinder(Slider origine)
             {
                    boundSlider = origine;
             }
 
             public double Value
             {
                    get { return boundSlider==null?0:boundSlider.Value; }
                    set {
                           if (PropertyChanged!=null)
                                  PropertyChanged(this,
                                    new PropertyChangedEventArgs("Value"));
                           boundSlider.Value = value;
                    }
             }
       }

Cette classe, ou plutôt l’une de ses instances, servira a représenter la valeur courante du Slider. Ce dernier est lié à l’instance lors de la création de cette dernière (voir le constructeur de la classe ValueBinder ci-dessus).

Comment utiliser cette classe ?

La première chose est qu’il faut en créer une instance, cela peut se faire dans le code XAML ou bien dans le code behind de la façon suivante (dans le constructeur de la page par exemple) :

var valueBinder = new ValueBinder(slider);

Maintenant il suffit dans le code XAML de lier les deux objets à la valeur de la classe intermédiaire, par Data Binding :

Côté Slider, le code est :

<Slider x:Name="slider"Value="{Binding Value, Mode=TwoWay}"/> 

Côté Border :

<Border x:Name="borderInfo"Opacity="{Binding Value, Mode=TwoWay}"> 

Ne reste plus qu’à rendre visible l’objet intermédiaire par exemple en en faisant la valeur courante du DataContext de l’objet LayoutRoot :

LayoutRoot.DataContext = valueBinder;

Et voilà ! Ne reste plus qu’à compiler et vous le plaisir de voir que l’opacité du Border change bien lorsque le Slider est déplacé.

La chaîne est la suivante : la modification de la position du Thumb entraîne dans le composant Slider la modification de la valeur de la propriété Value. Comme celle-ci est liée par Data Binding TwoWay à la propriété Value de l’objet intermédiaire cette propriété va se trouver modifiée dans le même temps. Comme le Setter de la propriété notifie le changement de valeur de la propriété (la classe implémente INotifyPropertyChanged) et comme la propriété Opacity du Border est elle aussi liée par Data Binding à la propriété Value de l’objet intermédiaire, le Border sera « prévenu » du changement de valeur et sa propriété Opacité sera immédiatement modifiée pour recevoir la valeur courante de Value de l’objet intermédiaire ! C’est pas fun tout ça ? (hmmm j’en vois un qui suit pas là bas au fond… !).

Vous allez me dire, TwoWay, on veut bien te croire mais on ne le voit pas là … Pour l’instant cela se comporte exactement comme la première solution, juste qu’il faut avoir un niveau de certifié pour comprendre…

C’est pas faux. C’est pourquoi je vais maintenant ajouter un petit bout de code pour faire varier la valeur de la propriété Opacity du Border. Le plus simple est de gérer la roulette de la souris dans le Border :

<Border x:Name="borderInfo"MouseWheel="Border_MouseWheel"> 

Et dans le code behind :

private void Border_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) 
             { 
                    borderInfo.Opacity += e.Delta/1000d; 
                    e.Handled = true;
             }

Il suffit maintenant de faire rouler la molette au dessus du Border pour en changer l’opacité. Le TwoWay ? Regardez bien : le curseur du Slider avance ou recule tout seul… Pour éviter que la page HTML contenant le plugin Silverlight ne se mette à scroller il faut bien entendu indiquer que l'événement est géré (Handled=true) ce qui est fait dans le code ci-dessus.

Cette solution est élégante, complète mais complexe. Elle reste l’approche à préconiser dans tous les cas du même type car, on le voit bien, si la première solution est simple, elle n’est pas complète. Complexifier par plaisir est un mauvais réflexe, mais ne pas voir qu’une solution est trop simpliste est aussi un défaut qu’il faut fuir !

Bref, sous Silverlight 2 la solution présentée ici est une bonne solution. Sous Silverlight 3 qui supporte le Binding direct entre éléments (comme WPF) nous allons pouvoir faire plaisir à la fois au développeur du premier cas et à celui du second :

Méthode 3 dite « Silverlight 3 »

Comment marier le reflexe (plutôt sain) du premier développeur de notre parabole de vouloir faire vite et simple avec l’exigence intellectuelle (tout aussi saine) du second qui implique de faire « complet » ?

Pour illustrer l’Element Binding de façon simple, prenons un Scrollbar en mode horizontal et un Slider en mode vertical.

Et regardons le code XAML de leur déclaration :

<ScrollBar x:Name="scrollA"Value="{Binding Value, ElementName=sliderB, Mode=TwoWay}"/> 
 
<Slider x:Name="sliderB"Value="{Binding Value, ElementName=scrollA, Mode=TwoWay}" /> 

Et c’est tout ce qu’il y a à faire pour obtenir une solution complète, élégante, sans code behind et très facile à mettre en œuvre ! Merci Silverlight 3 !

En début de billet vous pouvez jouer avec les deux dernières implémentations (je n’ai pas implémenté la méthode 1) .

Vous pouvez aussi télécharger le code du projet (Blend 3 ou VS2008 avec les extensions SL3) : elementBinding.zip (61,43 kb)

Pour d'autres nouvelles, Stay Tuned !