Il y a 5 années · 9 minutes · Front

Backbone, deux ans après

Backbone fut une des premières librairies à offrir une structure aux applications JavaScript. Avec le succès qu’on lui connaît — trello, airbnb, linkedin. Cet article se propose de synthétiser l’expérience de deux ans de développements à ses côtés — mauvais jours inclus — d’identifier des bonnes pratiques et d’entrevoir la suite de l’aventure.

Plus simple, tu meurs

Backbone repose sur le pattern observeur de Smalltalk : les modèles stockent les données et émettent des évènements auxquels les vues s’abonnent — modification d’un attribut, réception d’une requête serveur, erreur de validation, etc. Les vues s’abonnent également aux évènements de l’interface — clic, saisie, etc. Les vues sont orchestrées par un routeur : abonné aux changements d’URL, il sélectionne quelles vues afficher.

Backbone canalise la puissance des deux célèbres librairies $ et _, auxquelles il ajoute peu, en définitive (une liste d’évènements et une interface restful). Avec jQuery, il s’entoure d’une myriade de plugins, et, comme il ne présuppose pas de la façon dont il sera utilisé, peut en intégrer de nombreuses autres aussi facilement — templating, charts, amd, etc.

De nombreux mécanismes concourent à rendre ses accès rest transparents : model.save crée l’objet s’il n’existe pas côté serveur, ou le met à jour sinon, model.fetch et model.destroy parlent d’eux-mêmes, model.url indique l’adresse de la ressource serveur, model.parse manipule la réponse serveur lorsqu’elle n’est pas similaire à l’objet souhaité, etc (en interne, les appels serveur sont effectués avec jQuery).

Cette approche minimaliste permet un debug très rapide : identifier la template concernée puis la vue qui la manipule et l’URL serveur de son modèle, vous y êtes presque. Les erreurs sont explicites, les responsabilités faciles à déceler. Il est extrêmement rare de se retrouver à éplucher le code source de Backbone pour essayer de démêler une situation étrange.

Simpliste, peut-être

Backbone n’est pas exempt de défauts. Le premier d’entre eux est le caractère rudimentaire du routeur. Ce dernier associe URLs et méthodes sans offrir de filtre d’accès global sur celles-ci. Ainsi, chacune des méthodes doit dupliquer le code de vérification si leur affichage dépend des droits de l’utilisateur. Il faudra avoir recours à une extension Backbone pour bénéficier de cette fonctionnalité.

Le deuxième problème que l’on peut rencontrer est la gestion manuelle de l’imbrication de modèles. Lorsque Backbone récupère des données du serveur, il les enrobe dans un modèle (ou une collection s’il s’agit d’une liste). Cependant, cet enrobage n’est pas récursif : seul le premier niveau se voit allouer un objet et seulement lui lèvera des évènements. Les raisons de ce fonctionnement sont détaillées dans la documentation et, ici aussi, des extensions Backbone sont disponibles (de notre côté, nous avons utilisé Associations).

Une autre source d’ennui est le manque de précision de certains évènements. Par exemple, l’ensemble des accès serveur — get, put, post, delete — se soldent par un évènement sync en cas de succès, sans indiquer de quel appel http il s’est agi. Cette information est rarement nécessaire, il faut l’avouer, mais quand c’est le cas, il faut alors surcharger la méthode sync du modèle en question (nous verrons comment un peu plus bas).

Backbone est un cadre de travail ouvert : de nombreux choix sont laissés à la discrétion du développeur. Des librairies comme Marionette ou Chaplin s’appuient sur Backbone et offrent une opinion plus appuyée côté client. Rendr, développé pour airbnb, offre même une intégration côté serveur.

Bonnes pratiques

Il existe bien des manières de construire des applications Backbone ; la librairie, elle, n’en préconise pas de particulière. Ceci dit, certaines idées ont fleuri au fur et à mesure.

Lorsqu’une vue manipule une collection (une liste de modèles) et qu’elle désire offrir des actions individuelles sur chaque modèle, il est plus simple de créer une sous vue par modèle et de lui confier la gestion des actions de son modèle. Plusieurs autres librairies — Ember et Angular, par exemple — utilisent de nombreux data-attributes dans le DOM pour ces cas de figure, là où Backbone peut s’en passer complètement.

Lorsqu’une vue doit être ajoutée au DOM, il est plus efficace qu’elle le soit par la vue (ou le routeur) qui l’a instanciée. En d’autres termes, une vue gagne à ne pas indiquer d’attribut el (le nœud du DOM auquel elle est liée — qu’il soit présent dans la page ou non). Ainsi, elle n’a pas comme prérequis la présence d’un élément dans le DOM. Cet élément est couramment présent dans le template de la vue parente : cette dernière est donc la mieux à même d’ajouter ses filles aux nœuds adéquats — se référer à l’exemple d’une liste ajoutant ses items dans son contenu (elle peut également le faire dans un sous sélecteur).

Les vues sans attribut el présentent un second avantage : puisqu’elles n’ont pas de nœud auquel s’attacher, elles se voient affecter un div — configurable — sur lequel est positionné les écouteurs d’évènements. Lorsque la vue n’est plus nécessaire, et que son nœud est détruit, ses écouteurs d’évènements le sont alors aussi. En revanche, si la vue est rattachée à un attribut el existant, ce dernier est potentiellement nécessaire à d’autres vues, il ne peut pas être détruit : le nettoyage de la vue est alors plus délicat.

Lorsqu’une vue est retirée du DOM, elle doit être supprimée de la mémoire. Cependant, tant qu’un objet a des références vers d’autres, le Garbage Collector JavaScript ne peut le supprimer. Elle devient ce qu’on appelle alors une vue fantôme ; elle continue à avoir un effet sur l’application : une case à cocher effectuant deux fois son action habituelle, par exemple. Une discussion animée sur ce sujet est en cours pour les futures versions de Backbone. En attendant, une pratique couramment retenue consiste à ajouter une méthode close aux vues, souvent déclenchée par le routeur lors de la navigation d’une vue vers une autre (et en cascade pour les vues filles).

Lorsqu’il devient nécessaire de surcharger Backbone, plusieurs choses sont à prendre en compte. La plus importante, imputable au langage JavaScript, est l’absence de mot clé super, qui contraint à l’utilisation du prototype de la classe à surcharger (comme expliqué dans l’aparté sur super de la documentation). À noter également : la méthode extend — issue d’Underscore — remplace les références d’attributs au lieu de les étendre. Ainsi, une classe fille définissant l’attribut events n’héritera pas de ceux de sa classe mère (si celle-ci en définit). En revanche, si seule la classe mère définit des évènements, ceux-ci sont bien hérités par la fille.

Lorsqu’une information de l’interface utilisateur n’est reliée à aucune donnée côté serveur, il est tout de même pertinent de s’appuyer sur un modèle — sans url, donc — auquel la vue peut apporter des modifications et s’abonner. Une convention de nommage est une bonne idée dans ce cas de figure. Par exemple, le tri d’une collection dans un tableau sur chaque attribut peut reposer sur un modèle, au lieu d’utiliser des variables dans la vue.

Lorsqu’une closure est utilisée dans une méthode d’une vue, le this de cette closure n’est pas la vue elle-même. Underscore propose des méthodes bind et bindAll pour parer ces cas de figure. À utiliser avec modération — pour des raisons de performances — ces méthodes peuvent souvent être remplacées par un simple self = this.

Lorsque la méthode toJSON tend à être modifiée pour le templating, la création d’une autre méthode est recommandée. En effet, toJSON est utilisée également par Backbone pour l’envoi des modèles au serveur. Utiliser des mixins/helpers dans les templates est aussi une piste intéressante.

Lorsqu’une gestion centralisée des erreurs serveur est souhaitée, la surcharge de la méthode sync commune à tous les composants est possible.

Idées reçues

Une des idées les plus discutées du moment est le manque de productivité de Backbone vis-à-vis de ses compétiteurs Angular ou Ember. Pour des applications basiques, c’est évident. Mais, dès qu’une application est élaborée, la différence est beaucoup plus ténue : l’intégration naturelle de Backbone avec jQuery et ses dérivés lui ouvre la quasi intégralité des librairies créées ces dix dernières années sur le web. C’est là où réside la force de la simplicité de Backbone : il propose de ne pas réinventer la roue, plutôt de pousser un cran plus loin la manière dont les applications web ont été construites jusque-là.

Pour l’avoir utilisé depuis sa version 0.3.3, Backbone s’est raffiné agréablement, profitant des améliorations d’Underscore, peaufinant sa gestion d’évènements, sans devenir compliqué : au contraire, ces améliorations l’on rendu plus cohérent encore. Et migrer d’une version à une autre n’a jamais été très difficile.

Backbone 1.0 est daté du 20 mars. Si l’on se rapporte aux issues actuelles, certaines choses mineures restent à traiter, et il semble qu’une gestion des vues imbriquées soit en discussion, avec à la clé le détail des opérations laissées à la discrétion des développeurs. Difficile aujourd’hui de prédire si Backbone se dotera d’opinions plus prononcées sur la création d’applications web ; il semble que sa popularité en dépende. La simplicité de l’ensemble et sa grande adaptation à tous les cadres en font une librairie d’une excellente qualité. La liste pléthorique d’applications réelles en tirant partie, sa popularité sur Github, soulignent à nouveau, l’élégance et la pertinence de cette modeste librairie aux 4 classes.

 

Yves Amsellem
Développeur depuis 5 ans — les 2 derniers chez Xebia — Yves tire de son expérience sur des sites à fort trafic une culture de la qualité, de l'effort commun et de l'innovation. Spécialisé du style d'architecture ReST, il intervient sur des projets web à forte composante JavaScript et NoSQL. Avec Benoît Guérout, il développe la librairie open source Jongo — Query in Java as in Mongo shell
Pierre Gayvallet
Passé du coté front-office de la force il y a bien longtemps, Pierre est un passionné de développement Web et d'UX, suivant avec grand intérêt tout ce qui touche à l'écosystème javascript. C'est également un craftsman Backbone aguerri.

Une réflexion au sujet de « Backbone, deux ans après »

  1. Publié par Mounir Boudraa, Il y a 4 années

    Très bel article. Beaucoup d’émotions

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *