AngularDart

En ce moment, j'essais d'apprendre Dart, le langage fortement typé inspiré de Java que Google espère voir remplacer Javascript un jour. Et bien ce que je ressens en ce moment est exactement la même chose que lorsque j'ai découvert Angular :

…mais en bien plus puissant. C'est à dire que quand j'ai découvert AngularDart et ses @Component, la courbe est immédiatement montée très haut, bien plus haut que le "Neat" mais elle est retombée très rapidement dans le négatif quand je me suis rendu compte à quel point c'était chiant de travailler avec un langage fortement typé sur du web.

Alors pour ce premier épisode, qui sera j'espère suivi de nombreux autres, voici ce qui m'a fait monter au 7° ciel de l'apprentissage.

AngularDart est une version de Angular pour le langage Dart. Dart est un langage très inspiré de Java et C++ qui est capable de compiler du Javascript. Google propose avec son SDK une version modifiée de Chromium, nommée Dartium, accompagnée d'une VM Dart permettant d'éxécuter nativement du code Dart. Ainsi, avec le SDK Dart, on peut builder une application qui saura s'éxécuter avec la VM Dart si elle est présente tout en proposant un fallback en javascript pour les (futurs) vieux navigateurs. En théorie, c'est très intéressant et ça fait rêver : combien de développeurs conversateurs Java ont peur de javascript à cause de son laxisme sa puissante modularité ? C'est ce que promet Google avec Dart. Bon le soucis, c'est que depuis que Google a annoncé Dart, en 2011, de belles choses sont arrivées côté JS, notamment AngularJS, un framework magique qui permet de redécouvrir Javascript et de donner un cadre à tous les développeurs du dimanche qui contribuent à donner une mauvaise réputation à Javascript. Même si Dart possède toujours ses qualités, il reste un langage avec très peu de librairies comparés à ce qu'on peut trouver en Javascript tant côté client que côté serveur. Alors déjà, j'étais moyen chaud pour me mettre à JavaDart… Et puis… j'ai découvert AngularDart !

AngularDart… et qu'est-ce-qu'il a de plus que AngularJS d'abord ? Si on met de coté les gains théoriquement dus à Dart, pas grand chose. Et pourtant, il y a une avancée fondamentale au niveau de l'architecture qui permet de placer AngularDart comme une version intermédiaire entre AngularJS 1.x et AngularJS 2.0. AngularDart n'a pas de directive. Les directives d'AngularJS sont des éléments qui posent polémique car ils sont plusieurs choses à la fois : attributs, balises html, commentaires et peuvent faire tout et n'importe quoi… et surtout, ils sont destinés à être remplacés par les WebComponents dans les années à venir. Et c'est sur ce point que AngularDart a pris une belle avance sur son grand frère. Il n'existe donc pas de directive, mais à la place, nous avons des @decorator et des @component.

Le premier se présente sous la forme d'un attribut html et son but est de décorer la balise sur laquelle elle est appliquée pour lui ajouter des fonctionnalités. Coté AngularJS, ng-click serait donc un @decorator. Cette classe permettra donc principalement d'écouter des évènements ou de modifier les attributs de l'élément (comme ajouter ou supprimer des classes ou des styles).

Le second permet de créer ses propres balises html. Mais la différence avec AngularJS, c'est que son implémentation est largement inspirée des WebComponents et surtout, il génère du ShadowDom ! Alors de quoi s'agit-il ? Tout d'abord au niveau de l'implémentation, le @Component propose de spécifier un template sous la forme d'un fichier html, une feuille de style sous la forme d'un fichier css et une implémentation logique de façon bien séparée. C'est exactement ce que proposent les WebComponents même si la forme est différente. De la même façon que le feront les WebComponents, le DOM généré par le @Component est en fait un ShadowDOM. Le ShadowDOM est un DOM masqué à l'utilisateur. Un bon exemple est le lecteur vidéo par défaut de votre navigateur quand il rend une balise <video />. Quand on inspecte la source, on ne voit que la balise <video /> alors que son rendu nécessite moults éléments de DOM pour afficher l'interface et ses boutons.

ShadowDom video

Si on imagine un composant <pouet/> qui affiche "pouet" avant et après son contenu, nous aurions cette implémentation :

<header>Pouet</header>  
<content></content>  
<footer>Pouet</footer>  

Mais le navigateur ne montrerait que ça :

<pouet>Kikoo</pouet>  

C'est le ShadowDOM. Et c'est ça qui a fait monter ma courbe de feelings très haut. À tel point que j'ai vraiment eu envie d'apprendre Dart immédiatement. Sauf que…

Ben Dart c'est pas facile quand on fait du web. J'imagine que pour faire du serveur, ça doit être plus facile, mais voilà, je butte sur un problème de base, qui est une formalité en Javascript, mais qui me fait perdre un temps fou en Dart. Le problème est le suivant : J'ai un champs avec un ng-model (prout). J'ai du texte dans un paragraphe qui binde un attribut de mon controlleur (pouet). J'aimerais que cet attribut affiche la valeur du champs + 12. En javascript, c'est très simple : $scope.pouet = +$scope.prout + 12;. Mais en Dart, c'est une autre paire de manche. Si on fait ça, paf, exception : il est interdit d'additionner un String et un Int. Et oui, car le champs est typé lui aussi et renvoie un String. Il faudra penser à le convertir préalablement en nombre. C'est ce que j'ai fait avec le + dans la version JS, donc rien de choquant pour le moment. Mais alors quel type de nombre ? Un entier obligatoirement car on additionne pas non plus un entier et un flottant. Du coup, on va utiliser int.parse(pouet) et bien penser à le try catcher des fois que l'utilisateur tape autre chose qu'un entier, genre un flottant… Oui mais si on le veut vraiment ce flottant ? Merde. Alors on va peut être utiliser la classe num qui est la classe parente de int et double ? num.parse(pouet)? Bah non, car selon la valeur de pouet, il instanciera soit un int, soit un double, mais pas un num dont on se fout de ce qu'il est (num.parse('12') => int 12, num.parse('12.1') => double 12.1). Donc dans tous les cas, on se retrouvera à d'abord vérifier le type de pouet avant de l'additionner, soit à 12 si c'est un int, soit à 12.0 si c'est un double, et puis dans le second cas, vu qu'on va devoir absolument retourner un String, puisque le champs est de type String, il faudra en plus enlever le ".0" inutile et moche que l'utilisateur ne s'attendait pas à voir. Bref. Je m'y prend surement mal et je serais ravi que vous m'orientiez vers des ressources qui me permettront d'avancer, mais là, je suis tout en bas du graphique. Et j'ai hâte de me taper la prochaine montée fantastique !

Hadrien

Hi, I'm a french Javascript Lead Developer, Web Architect from Toulouse, France. I've worked for 12 years for many projects with YUI, AngularJS, Aurelia.io and now React and React native.

Toulouse, France https://hadrien.eu