InfoQ FR a interviewé Matthieu Mezil, expert C# français animant régulièrement des conférences sur la méta-programmation, pour faire le point sur le développement de son Framework WAQS, Web Async Queryable Services, avant son départ vers les États-Unis et son intégration aux équipes de Microsoft Corp.
InfoQ FR : La méta-programmation est un ensemble de techniques auquel certains aiment recourir fréquemment ; d'autres s'en passent de façon générale pour construire leurs applications. De quels genres de super pouvoirs puis-je disposer en ayant recours à la méta-programmation ? A côté de quoi est-ce que je passe si je n'utilise pas ces techniques ?
Matthieu Mezil : On peut déjà se reporter à la définition. Il y a deux aspects importants de la méta-programmation : la génération de code et le fait d’analyser le code comme de la donnée. On peut faire les deux, c’est par exemple ce que fait un compilateur. Avec la méta-programmation, on peut travailler sur une autre dimension, au delà du “design time” et du “run time”. Personnellement, j’exploite cette dimension pour travailler à un niveau d’abstraction plus élevé que celui de mes langages et frameworks habituels.
De là, lorsqu’on part de ce niveau d’abstraction pour générer du code par exemple, le code généré présente moins de défauts car il s’appuie sur des patterns éprouvés. Si le méta-code a été produit par un expert du domaine, des développeurs moins aguerris à ce domaine en particulier pourront profiter de techniques qui leur sont difficilement accessibles sans cela.
Le résultat est plus robuste mais aussi souvent plus homogène. On peut se fixer des conventions et faire en sorte qu’elles soient respectées, d’autant plus lorsqu’on ajoute des techniques d’analyse de code pour nous aider en ce sens. Tout cela est intéressant pour le travail en équipe, permet d’utiliser au mieux les spécialités de chacun, de se concentrer sur ce qui a de la valeur et de mieux maîtriser la complexité du projet sur la durée.
Généralement, lorsqu’on pense à la méta-programmation, on pense à la productivité. Mais au delà de cela, il y a ces aspects tout aussi importants que sont la qualité et la maintenabilité. Je pense que le travail du développeur devient plus intéressant aussi, par exemple lorsque les parties les plus rébarbatives du code sont générées pour lui.
InfoQ FR : Tu développes WAQS, que tu qualifies de méta-framework. Qu’est-ce que cela signifie pour toi ?
Matthieu Mezil : Quand on utilise un framework, on récupère des libraires, on les référence dans notre projet et on y fait appel de façon classique. Cela peut présenter des problèmes de customisation. Comment faire pour le personnaliser, pour l’étendre ou modifier son comportement lorsque ce n’est pas prévu pour ? Comment faire pour que tel framework, fait pour donner des réponses génériques, profite de telle possibilité d’optimisation spécifique à mon contexte ? Prenons Entity Framework par exemple. Entity Framework ne connaît pas mon modèle d’entités. Il découvre tout à “runtime”.
WAQS propose une approche différente, celle d’intervenir sur la dimension de la méta-programmation dont je parlais tout à l’heure. Pour continuer sur la comparaison avec Entity Framework, une partie de la génération de code est dépendante du modèle d’entités. Or, lors de la génération, WAQS a connaissance du modèle et peut donc le prendre en compte afin de générer des méthodes spécifiques au domaine et optimales. On ne paie plus le coût au runtime.
D’une façon générale, WAQS s’appuie sur l’analyse et la génération de code pour générer un framework à l’intérieur de votre projet. Le code généré peut être personnalisé directement dans le meta-code qui est accessible et modifiable ou à travers des points d’extension, comme des méthodes partielles par exemple. Tout est ouvert. WAQS est donc un méta-framework dans le sens où c’est un framework qui génère des frameworks.
InfoQ FR : Peux-tu donner un exemple de bénéfice apporté par WAQS ?
Matthieu Mezil : C’est simple, avec WAQS, je peux travailler plus simplement avec mon domaine et mon modèle d’entités, sans duplication de code. Le développeur écrit sa règle métier une fois, elle sera analysée pour générer un code utilisable côté client et côté serveur. Toute la plomberie est prise en charge par WAQS.
Prenons deux exemples.
Imaginons que nous sommes dans le cadre d'un développement 3 tiers classique et que nous nous intéressons au montant total d’une commande. Nous allons certainement vouloir ajouter une propriété Total en lecture seule sur l'entité Order. Pour porter l'information, cette propriété devra se trouver côté serveur et côté client. Par ailleurs, l'information doit être recalculée côté client pour que le montant soit mis à jour sur l'interface lorsque la commande change. Il y a aussi des règles métier qui sont appliquées côté serveur sur le montant total. Et on va peut-être vouloir faire des requêtes sur les commandes en s'appuyant sur ce montant. On commence à voir que la logique de calcul va être dispersée et dupliquée partout. Autant dire que ce fonctionnement pourtant « standard » n’est pas bon en termes de qualité et de maintenabilité. En effet, le code étant dupliqué dans les différentes couches de l’application, il faudra repasser partout et tout retester le jour où l'on veut changer la formule de calcul.
Avec WAQS, on va simplement définir une méthode d’extension GetTotal sur la classe Order. À partir de cette simple méthode, WAQS va générer la propriété Total côté client et serveur, en générant la logique des PropertyChanged côté client. De plus, WAQS fournit également un provider LINQ côté client et serveur permettant l’utilisation de la propriété Total. Ainsi, il n’y a pas de duplication du code écrit. Si vous voulez mettre à jour la logique de calcul du Total, il suffit de mettre à jour la méthode GetTotal et de regénérer le code.
Prenons un autre exemple avec les méthodes de validation. La validation peut s’avérer complexe dès lors que l’aspect concurrentiel entre en jeu, notamment pour les développeurs juniors. Même quand le code est correct, l’intention de la validation est souvent noyée dans du code technique, rendant le code difficile à relire et ce, quelque soit la qualité du code écrit.
Avec WAQS, on va définir une méthode ne prenant pas en compte l’aspect concurrentiel et, de cette méthode qui sera donc plus facile à écrire, à relire et donc à maintenir, WAQS va générer le code complexe incluant la gestion de la concurrence.
InfoQ FR : Quels sont les outils de la méta-programmation en .NET ? Comment les utilises-tu ?
Matthieu Mezil : Les outils classiques pour générer du code sont les templates T4, que j’utilise beaucoup, Razor ou encore les DSL Tools.
Pour intervenir au runtime, la méthode la plus connue est la Reflection pour l’analyse du code. On a également la possibilité de compiler du code à la volée avec CodeDom ou en émettant de l’IL (Langage Intermédiaire) avec des instructions Emit. Une autre façon consiste à utiliser les Expressions LINQ pour analyser du code (la version IQueryable de LINQ fonctionne comme ça) mais aussi pour construire des Expressions qu’il sera ensuite possible de compiler, toujours au runtime.
Dans le domaine de l’analyse de code, on parle de plus en plus de Roslyn, notamment depuis la Build (Build Developer Conference 2014 de Microsoft). Roslyn donne accès à des API du compilateur, aux arbres syntaxiques et à la sémantique ainsi qu’à des fonctionnalités qu’on trouve dans Visual Studio comme le Rename par exemple. Dans le cas de WAQS, je n’utilise pas Roslyn tout seul mais dans des T4 ou NuGet afin d’analyser le code du développeur, le modifier et l’enrichir dans le processus de génération de WAQS.
NuGet, qu’on connaît bien pour la gestion des dépendances, peut aussi être considéré comme un outil de la méta-programmation. En effet, je l’utilise pour ajouter des commandes PowerShell pouvant prendre des paramètres avec Intellisense dans la console Package Manager Console de Visual Studio. Dans WAQS, j’exploite cela pour ajouter de l’outillage dans Visual Studio. On peut ainsi faire de Visual Studio un environnement encore plus puissant.
Tous les outils / technologies évoqués ont leur intérêt propre, je les utilise tous à l’exception de Razor, CodeDom et des DSL Tools, dans le cadre de WAQS. Séparément, ils sont intéressants dans quelques cas d’utilisation bien précis mais tous ensemble, ils offrent une puissance insoupçonnée par la plupart des développeurs sans laquelle je n’aurais pas pu faire WAQS.
InfoQ FR : Il existe des solutions sur le marché qui proposent une meilleure productivité grâce à la génération de code, pourquoi ne connaissent-elles pas une adoption plus large, d’après toi ?
Matthieu Mezil : Je ne partage pas la vision de la plupart de ces solutions du marché. En effet, la plupart du temps, ces solutions essayent tout simplement de fermer les yeux sur les problématiques réelles du développement. Parfois, celles-ci proposent de générer l’application en partant d’un modèle établi par des fonctionnels. D'autres proposent une approche s’appuyant sur un éditeur graphique. Dessiner des boîtes et des flèches n’est pas intéressant pour un développeur. Le développeur se sent à l'étroit dans un éditeur graphique : le formalisme est plus restreint que dans le langage cible et il est difficile d’y définir des règles métier complexes ou de modéliser des domaines riches.
Beaucoup de solutions génèrent du code en partant du principe que comme tout est généré, il n'est pas important d'obtenir du code qui ne correspond pas aux bonnes pratiques, notamment en ce qui concerne les abstractions. Ces solutions qui ont pour but de générer l’application sont très rapidement limitées en flexibilité. Ceci est également valable pour un certain nombre de technologies dont les démos nous montrent une super productivité mais pour lesquelles la réalité est tout autre dès lors qu’on sort du mode RAD.
Un autre point important : de façon plus générale, les solutions qui proposent de la génération en boîte noire ne sont pas satisfaisantes. S’il y a quelque chose qui n’est pas adapté dans le moteur, voire un bug, on est coincé.
Pour résumer, l’expérience pour le développeur est primordiale. WAQS n’a pas été pensé pour rendre les développeurs obsolètes mais pour leur rendre service. Afin de répondre à cet objectif, le code généré est propre, répond à des patterns éprouvés et correspond au code que j’aurais pu écrire à la main si je n’avais pas eu WAQS. De plus, WAQS assure la continuité dans l’expérience de développement, on reste dans son environnement, on écrit du C#, du LINQ etc.
Les contraintes imposées à la conception aussi sont mal vues par les développeurs. C’est encore un avantage de WAQS : le développeur est libre, il peut par exemple partir sur du MVVM ou du MVC et il s’appuiera sur WAQS pour la tuyauterie. Il peut choisir précisément ce qu'il souhaite voir générer, couche par couche.
Il est vrai que convaincre les développeurs est un exercice délicat mais les résultats parlent d'eux-mêmes : un de mes clients m'a rapporté récemment avoir divisé par 2 son temps de développement et les performances de son application sont bien meilleures que celles qu’il aurait obtenues s’il avait utilisé directement Entity Framework.
InfoQ FR : Le côté magique qui peut rebuter les développeurs, n’est-ce pas ?
Matthieu Mezil : Tout à fait. De mon point de vue, 98% des développeurs n’ont aucune compétence en méta-programmation et, même si j’ai pu observer un réel intérêt lors des nombreuses conférences que j’ai animées sur le sujet, la plupart des développeurs considère le terme de méta-programmation comme un gros mot qui fait peur. Mais en fait, la méta-programmation, c’est juste du code ! Quand je donne des formations sur le sujet, ces mêmes développeurs se rendent compte que finalement, ce n’est pas si complexe que ça. Pas plus tard qu’aujourd’hui, un de mes clients à qui je donnais une formation sur le méta-code de WAQS m’a dit la phrase suivante : « Finalement, après avoir utilisé Roslyn on s’aperçoit que ce n’est pas si complexe que ça et le méta-code de WAQS paraît beaucoup plus accessible ».
Par ailleurs, les développeurs sont craintifs à l’idée d’utiliser une technologie qu’ils imaginent extrêmement complexe à cause de ce côté « magique ». Ils imaginent que cela va apporter une complexité énorme sur leur projet alors que la réalité est tout autre. Si on prend async / await, ça a un côté magique et personne ne considère que ça va apporter une complexité non maîtrisée à ses projets. Bien entendu, il est plus facile de faire confiance à Microsoft qu’à une personne qui développe toute seule sur ses nuits, cependant, je pense que cet argument n’est pas recevable et qu’il tend plutôt à prouver une difficulté de beaucoup de développeurs à remettre en cause leur façon de travailler.
Je vais même aller plus loin et me permettre un parallèle probablement excessif mais qui n’est pas dénué d’intérêt pour autant. Si on regarde l’évolution de la programmation depuis les cartes perforées jusqu’à C# en passant par l’assembleur, le C et le C++, on s’aperçoit qu’au fil du temps, on a régulièrement inventé de nouveaux langages qui apportent toujours plus d’abstraction de façon à gagner en productivité et en maintenabilité. Je pense que Roslyn ouvre la voie à un nouveau mode de programmation toujours basé sur cet objectif d’amélioration de la productivité et de la maintenabilité et que WAQS en est le premier exemple.
InfoQ FR : Quels sont tes plans pour WAQS ?
Matthieu Mezil : Aujourd’hui, les clients que je suis utilisent WAQS dans le cadre d’applications WPF, ASP.NET MVC, Windows 8 / Windows Phone 8 mais aussi iOS et Android via Xamarin avec une version cliente PCL.
Pour le 3 Tiers, WAQS utilise WCF aujourd’hui. Un objectif à moyen terme serait d’intégrer également une version Web API, voire peut-être OData.
Dans le cadre d’ASP.NET MVC, seule la partie serveur est utilisable aujourd’hui. Un de mes objectifs à plus long terme serait de faire un client JavaScript.
Aujourd’hui, WAQS est open source et téléchargeable depuis NuGet. La documentation se trouve sur waqs.codeplex.com. Cependant, afin de m’aider à réaliser mes plans, je suis en train de réfléchir à l’ouverture du développement de WAQS à la communauté. Dès lors, les contributions seront les bienvenues.