WebApp Programmation OrienteeComposant

WebApp et Programmation Orientée Composant

Par Audrey le 23 décembre 2014

 Lecture 4 minutes

Chez Synolia, nous développons des applications web complexes, comme Heidi par exemple. Pour y parvenir nous recourrons régulièrement à des concepts comme MVC, POO et POC, délégation d’événements, tests unitaires, etc.

Ainsi, nous nous sommes penchés sur AngularJS afin d’évaluer ce framework et de voir si nous devions bâtir nos applications avec. Sans trop entrer dans le détail voici une image qui résume assez bien notre sentiment sur l’usage d’un framework par rapport à une librairie.

framwork

Naturellement, nous privilégions le développement d'outils pour nous aider à construire nos applications, car ceux-ci répondent précisément à nos besoins, et apportent une meilleure maîtrise de l'application. Nous apprenons beaucoup en les fabriquant, et préférons apprendre à faire qu'apprendre à utiliser.

AngularJS est très riche et parfaitement adapté au développement d'applications web. Il offre un certain nombre de fonctionnalités qui le rende comparable à Flex.

Ce que l'on aime :

  • son côté programmation déclarative,
  • l'injection de dépendance,
  • le data-binding,
  • le MVC,
  • et bien d'autres choses...

Pour autant, si l'on y regarde de plus près, tout n'est pas systématiquement bon à prendre.

Utiliser AngularJS c'est aussi accepter un cadre de développement or, chez Synolia, nous sommes assez grands pour le fixer nous même. Ici AngularJS devient donc plus une contrainte qu'un avantage. Pour rappel ce framework a été fait pour pallier à certaines lacunes du langage Javascript, en effet, le javascript (ES5) ne supporte ni les classes, ni les packages, ni le typage. C'est pour ces raisons que de nombreux développements de ce type se tournent vers TypeScript ou CoffeeScript.

Chez Synolia, nous avons choisi Haxe. Du coup, une partie du travail d'AngularJS ne nous est pas utile.

D'autre part ce framework travaille au runtime.
Cela a évidement un impact sur le poids et les performances de l'application mais, vous nous direz, si on y prête attention cela reste négligeable. Seulement voilà, pour nous, ce besoin n'existe pas.

Avec Haxe, nous avons une solution qui structure nos développements en amont. Derrière, c'est le compilateur qui vérifie le code, l'optimise et produit un javascript débarrassé du superflu.

En somme, c'est le besoin qui pilote nos développements et non nos outils.

C'est pour cela que nous avons choisi de prendre le meilleur d'AngularJS, d'en faire une librairie Haxe open source, et de baser nos développements dessus.

Directives et HTMLComponent

Nous avons été séduits par les Directives d'AngularJS.

L'idée de découper son application en composants et d'utiliser le html pour représenter la vue d'un model MVC est tout simplement parfaite.

Avec Flex4 nous avions la même chose avec un mxml pour la vue.

mvcPour en profiter en Haxe, nous avons créé HTMLComponent. Voici comment nous l'utilisons.

Prenons l'exemple d'un nouveau composant PictureItem. Nous faisons hériter notre classe de HTMLComponent et lui ajoutons un metatag @view pour lui indiquer quelle vue html utiliser.

@view('com/sakura/prestashop/item/PictureItem.html')
class PictureItem extends HTMLComponent {
public function new(parent:Element):Void {
super(parent);
}
}

Ensuite pour instancier notre composant depuis une autre voici comment ça se passe :
ListePicture.hx

var pictureContainer = Browser.document.getElementById(containerId);
var item = new PictureItem(pictureContainer);

Et voilà, je viens de créer un item dans une div.

Utilisation

Pour l'instant notre PictureItem n'affiche pas grand chose, nous allons changer ça en modifiant notre vue.

Maintenant affichons une image et un bouton. Sauf que ... notre image n'a pas de source !
Retournons dans notre classe principale pour qu'elle demande à la vue d'afficher quelque chose.
Lorsque notre composant a fini de charger sa vue, il appelle une fonction initContent.

Nous allons la surcharger pour accéder à notre image.

override private function initContent():Void{
_image = cast _tempElement.getElementsByClassName(imageId)[0];
_image.src = "toto.jpg";
}

_tempElement nous permet d’accéder à notre vue avant qu'elle soit injectée dans le DOM, mais rien ne nous empêche de le faire plus tard. C'est juste beaucoup plus rapide de parcourir la vue, que l'ensemble du DOM.
Et voilà, nous venons d'afficher une image.

Les Macros

Tout cela est rendu possible grâce aux macros. C'est quelque chose de très puissant qui nous permet de programmer le comportement du compilateur. Dans HTMLComponent il y a une macro qui va scruter la présence du tag @view, puis charger le html, le parser et l'injecter dans notre composant. Tout se passe à la compilation, rien au runtime.

Vous l'avez vu, nous n'avons rien inventé et c'est méchamment efficace ! Le fonctionnement de HTMLComponent reprend en partie celui de des composants Flex.

Il a trois phases d'initialisation :

  • parseContent();
  • initContent();
  • displayContent();

Il est possible de surcharger chacune d'elle.
Nous verrons la prochaine fois comment utiliser les macros pour faire du data-binding natif, sans while(true) ;)

GIF