Pages

Affichage des articles dont le libellé est service. Afficher tous les articles
Affichage des articles dont le libellé est service. Afficher tous les articles

samedi 26 octobre 2013

Services ou événements dans l'optique des tests

Quelques réflexions complémentaires à mon article sur l'usage des services, qui partent d'une question que l'on m'a posé à la fin de ma présentation au Meetup AngularJS Paris chez Google. Quelqu'un m'a demandé si les événements pouvaient être utilisés pour simplifier les tests unitaires d'un contrôleur. En limitant les injections de services en dépendances, on évite la nécessité de versions factices (mock objects) de ces services.

Cette question me turlupinait dans le trajet retour, et j'ai essayé de pousser plus loin la réflexion en explorant cette piste et diverses alternatives.

mercredi 23 octobre 2013

Usage des services AngularJS

Cet article est basé sur la présentation que j'ai faite hier au Meetup AngularJS Paris chez Google. Les slides se trouvent ici, et une vidéo a été mise en ligne là. Mais comme les slides perdent beaucoup de leur intérêt sans les explications qui vont avec, ça méritait bien un article - et même plusieurs, puisque j'ai mis deux exemples dans des articles séparés (les liens sont vers la fin). Je vais aussi en écrire un sur l'autre partie de ma présentation, sur les scopes isolés dans les directives.

S'il y a une fonctionnalité que les développeurs qui débutent sur AngularJS sous-estiment énormément, c'est bien les services. Je me rend compte régulièrement en formation ou lors d'audits que beaucoup de code pourrait être largement simplifié en utilisant plus efficacement les services. Ça n'a d'ailleurs rien d'étonnant, on commence à partir des exemples qu'on trouve sur internet, qui sont des exemples courts et n'ayant évidemment pas toute la structure d'une vraie application. Des exemples qui montrent comment ça marche, pas comment il faut faire.

Dans une application non triviale, au moins 90 % du code JavaScript devrait être dans les services. Il peut y avoir quelques directives et filtres bien sûr, dont une partie peut d'ailleurs être commune à plusieurs applications, mais ce sont les contrôleurs qui doivent être aussi réduits que possible. Un contrôleur AngularJS est juste une fonction d'initialisation du scope correspondant, et il doit essentiellement se limiter à cela : faire quelques affectations dans l'objet scope. Il ne doit pas faire de requêtes HTTP, ni des traitements sur les données, ni gérer le stockage des données.


Conserver les valeurs des critères de recherche

Comment conserver lorsque l'on change de vue à l'intérieur d'une application AngularJS des données correspondant à l'état de la vue, comme les valeurs des critères d'une recherche ?

Imaginons qu'on affiche dans une vue une liste d'objets, avec des critères permettant de faire un filtrage en local. Et sur chaque objet, un lien permet de naviguer vers une vue des détails de l'objet. Quand l'utilisateur revient sur la liste, il s'attend à la retrouver dans le même état. Ça suppose que les valeurs de filtrage saisies soient conservées.

Or si ces valeurs sont simplement dans le scope de la vue, elles seront perdues à chaque changement de vue, car le scope de l'ancienne vue est détruit par AngularJS. La solution simple pour les conserver est de les stocker dans un service.

Service AngularJS de notification

Un autre exemple de service qui peut être très utile : il s'agit d'afficher des notifications pendant quelques secondes, comme le font les applications de Google, avec un lien dans le message permettant d'annuler l'action.

C'est typiquement le genre de truc qu'on imagine compliqué, mais si on le prend bien, avec AngularJS ça s'écrit en quelques lignes - enfin sans compter le CSS qui finalement est le plus gros du boulot.

L'exemple se trouve ici sur GitHub, et il y a un lien vers la démo (c'est le même que pour l'article "Conserver les valeurs des critères de recherche"). Ajoutez des articles au panier, et quand vous en supprimez du panier, vous avez une notification avec un lien pour annuler l'action.

mardi 19 février 2013

Les fonctionnalités de Twig avec AngularJS: angular-twig-pack

Depuis que je travaille avec AngularJS, j'ai entendu beaucoup de gens comparer le Framework avec divers moteurs de template... Et il en existe! La liste (non-exhaustive) de wikipedia: Template_engine_(web) en est la preuve. Malheureusement, Wikipedia ne nous numérote pas ce tableau, heureusement que la console est là:

> document.querySelectorAll('.wikitable tbody tr').length
89

Bon ... Trêve de plaisanterie, passons aux choses sérieuses. Je me suis dit pourquoi ne pas prendre un moteur de template existant et créer un pack de directives, filters et services pour ne pas trop dépayser les puristes.

Kezako

Pour cet exercice, j'ai choisi le Framework Twig (uniquement car je l'ai déjà utilisé et surtout car j'adore les couleurs du site: http://twig.sensiolabs.org/).

mardi 15 janvier 2013

AngularJS: Service de gestion de raccourcis clavier

A l'image des applications Google, Twitter et autres grosses applications Web du moment, il est très "user-friendly" (convivial pour les franglophobes !) de mettre en place une série de raccourcis clavier pour utiliser de manière optimisée l'application.

Les raccourcis clavier sont une touche ou une combinaison de deux ou plusieurs touches à presser simultanément afin d'éviter une action de pointage par la souris. Le fait de ne pas déplacer en permanence la main entre le clavier et la souris fait déjà gagner un temps précieux pour les gens qui travaillent toute la journée sur une application. De plus, à chaque action de la souris, il faut un temps de pointage pour déplacer le curseur sur l'endroit voulu.

Comment centraliser la gestion de ces raccourcis dans une application AngularJS ?

Nous allons voir comment utiliser un service AngularJS pour rendre cette gestion de raccourcis clavier générale.

mardi 11 décembre 2012

Décoration de services AngularJS

C'est bientôt Noël, mais il ne s'agit pas d'accrocher des guirlandes aux services d'une application AngularJS. Cherchez plutôt du côté du design pattern Decorator.

Pour compléter l'article précédent sur les différentes façons de créer un service, il existe aussi une technique dans AngularJS pour modifier un service existant lors de son instanciation, ou pour substituer à l'instance du service un objet différent mais similaire.

Cette fois ce n'est pas via une méthode de l'objet module. La méthode decorator() à utiliser se trouve dans le service standard $provide, qu'il faut bien sûr injecter. On peut appeler cette méthode dans la méthode config du module principal de l'application, ou d'un autre module.

lundi 10 décembre 2012

Les différentes façons de créer un service avec AngularJS

[Ajout du 02/01/2013] : tableau récapitulatif, et exemple d'utilisation des cinq méthodes (voir à la fin de l'article)

Les services dans une application AngularJS sont organisés en modules. Et chaque objet module dispose de cinq méthodes différentes permettant de créer un service : constantvalue, factory, service et provider. Nous allons voir quelles sont leurs particularités, et dans quels cas utiliser l'une plutôt que l'autre.

Mais d'abord, qu'est-ce qu'un service AngularJS ? C'est un objet JavaScript quelconque, qui peut même être un type primitif comme un nombre ou une chaîne de caractères. Par exemple le numéro de version de l'application, ou un objet contenant les informations sur l'utilisateur connecté, ou encore un objet qui met un ensemble de méthodes à disposition des contrôleurs. Ce qui en fait un service, c'est le fait de le publier sous un certain nom, via une des cinq méthodes citées, dans le module auquel il appartient. Attention, le module ne sert pas d'espace de nommage, donc il faut éviter de publier deux services sous le même nom dans deux modules différents, sous peine de collision si ces deux modules sont chargés ensemble dans la même application.

Donc un service n'est rien de plus qu'un objet publié sous un certain nom, pour qu'il puisse être injecté comme dépendance dans un contrôleur ou un autre service. Sauf qu'en réalité c'est un peu plus compliqué que ça. Lorsqu'on charge un module, les services ne sont pas immédiatement créés, et pour chaque service ce qui est référencé dans l'injecteur de dépendances, ce n'est pas le service lui-même puisqu'il n'existe pas encore, mais son provider.