BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Articles Backbone contre Angular : comparaison

Backbone contre Angular : comparaison

Opposer des idées et des outils est une très bonne façon de mieux les comprendre.

Dans cet article, je présenterai une liste de tâches auxquelles nous devons faire face chaque jour lorsque l'on travaille sur une application web et nous verrons comment Backbone et Angular permettent d'apporter des solutions.

Ce que l'on veut résoudre

La plupart des activités que nous entreprenons en tant que développeurs web peuvent se ranger dans une des catégories suivantes :

  • Implémenter de la logique métier

  • Construire le DOM

  • Implémenter de la logique de vue (déclarative et impérative)

  • Synchroniser le modèle et la vue

  • Gérer des interactions d'UI complexes

  • Gérer des états et des routes

  • Créer et lier des composants

Il n'est donc pas surprenant que la plupart des frameworks coté client proposent des solutions d'une manière ou d'une autre.

Backbone

Commençons par regarder ce que Backbone nous offre pour résoudre ces problèmes.

Logique Métier Modèle et Collections de Backbone
Construction du DOM Handlebars
Logique de vue déclarative Vues Backbone
Logique de vue impérative Vues Backbone
Synchronisation Vues-Modèle StickIt
Intéractions entre UI Objets JS ou Controlleurs Marionette
Etats et Routes Backbone.Router
Création et interconnexions entre composants Manuellement

Pour ceux qui sont plus visuels :

Quand je dis Backbone...

Comparer un Backbone simple avec Angular ne serait pas très équitable. Du coup, lorsque je parle de Backbone, je considère Backbone + Marionette + des add-ons.

Logique Métier

Une grosse part de la logique métier des applications se retrouve dans les modèles et collections de Backbone. Souvent ces objets correspondent à des ressources côté serveur. Et au-delà de cela, ils servent de supports pour les vues.

Etendre Backbone.Model et Backbone.Collection ajoute une bonne dose de complexité.

D'abord, il sépare les différents objets en POJOs et modèles Backbone. Les POJOs seront utilisés pour faire le rendu des templates et dialoguer avec le serveur et les objets modèles de Backbone seront utilisés pour les propriétés à observer (c'est à dire la création de bindings).

Ensuite, il incite à la mutabilité. Etant donné que Backbone ne supporte pas l'observation de fonctions, chaque propriété calculée doit être réinitialisée lorsqu'une de ses propriétés sources change. Cela ajoute beaucoup de complexité pouvant rendre le code difficile à comprendre et à tester. En plus, toutes les dépendances doivent être explicitement déclarées sous la forme de on("change:sourceProperty", this.recalculateComputedProperty).

Construction du DOM

Backbone utilise les moteurs de templates pour construire le DOM. En théorie, vous pouvez utiliser le moteur que vous souhaitez. En pratique, Mustache et Handlebars sont ceux qui sont généralement utilisés dans les grosses applications. Du coup, les templates Backbone contiennent souvent peu de logique et sont basés sur des strings mais ce n'est pas obligatoire.

Logique des vues

L'idée de séparer la logique des vues entre une partie impérative et une partie déclarative n'est pas récente (elle date en fait du pattern MVC original). La configuration de gestion des évènements et les bindings de données sont déclaratifs. La gestion d'évènements elle, est impérative. Il n'y a cependant pas de frontière physique entre les 2, qui se retrouvent ensemble dans Backbone.View.

Synchronisation du modèle et des vues

Du fait de la nature minimaliste de Backbone, il n'y a pas de support préconstruit pour le binding de données. Ce n'est pas un problème pour les petits projets où les vues peuvent porter la responsabilité de la synchronisation modèle-DOM. En revanche, on peut vite perdre le contrôle lorsque les applications grossissent.

Il existe plusieurs add-ons (comme Backbone.StickIt) qui permettent de soulager un peu le travail et vous permettent de vous concentrer sur les interactions complexes plutôt que la synchronisation de base entre le modèle et les vues. La plupart de ces add-ons se configurent directement en JavaScript, ce qui permet de construire des abstractions par-dessus, en fonction des besoins de votre application.

La contrepartie de l'utilisation des bindings de données de Backbone est qu'ils reposent sur l'observation de propriétés alors que les moteurs de template se basent sur de simples POJOs. Souvent, cela mène à une duplication de code.

Gestion des interactions complexes d'UI

Toutes les interactions d'UI peuvent être divisées en 2 catégories, les simples (gestion par Observer Synchronization) et les complexes (gestion par Flow Synchronization).

Comme décrit précédemment, les interactions simples sont gérées par Backbone.View via les bindings de données et la gestion d'évènements. Ensuite, puisque Backbone n'a pas de solution prédéfinie pour gérer les interactions complexes, vous êtes libre de choisir ce qui convient le mieux à votre application. Certains font tout dans Backbone.View mais je ne le recommande pas. Backbone.View en fait déjà trop. Supervising Presenter est le pattern que j'essaye généralement d'utiliser pour gérer les interactions complexes.

Etats et Routes

Backbone propose une implémentation très simple de routeur. Il n'y a pas de support pour gérer les vues et l'état de l'application. Tout doit être fait manuellement. C'est pourquoi, on utilise souvent d'autres bibliothèques (comme router.js) au lieu du routeur par défaut.

Création et interconnexions entre composants

En Backbone vous avez le choix de créer et connecter vos composants comme vous le souhaitez. L'inconvénient est la quantité de code générique à écrire à chaque fois et la discipline nécessaire pour conserver un code bien organisé.

Angular

Voyons maintenant comment Angular se débrouille avec ces problèmes.

Logique Métier objets JS
Construction du DOM Directives
Logique de vue déclarative Directives
Logique de vue impérative Controlleurs
Synchronisation Vues-Modèle Automatique
Interactions entre UI Controlleurs
Etats et Routes Router AngularUI
Création et interconnexions entre composants Injection de Dépendances

Pour ceux qui sont plus visuels :

Logique Métier

Comme Angular n'utilise pas de propriétés observables, vous n'êtes pas limité dans votre implémentation de modèle. Il n'y a pas de classe à étendre ou d'interface à respecter. Vous êtes libre d'utiliser ce que vous voulez (y compris des modèles Backbone). En pratique, la plupart des développeurs utilisent de simples objets JavaScript, ce qui apporte les avantages suivants :

  • Tous les objets du domaine sont indépendants du framework, ce qui les rend utilisables sur plusieurs applications.
  • Ils sont très proches des données reçues par le réseau, ce qui simplifie la communication client-serveur.
  • Ils sont utilisés pour faire le rendu de vues, il n'est donc pas nécessaire d'implémenter toJSON.
  • Les propriétés calculées prennent la forme de fonction.

Vue et Template

En Angular, un template est un fragment de DOM avant sa compilation. Pendant la compilation, Angular transforme ce DOM et y ajoute du JavaScript. Le résultat est un nouveau fragment de DOM qui devient la vue. Vous ne créez donc pas la vue vous-même, Angular le fait pour vous en compilant le template.

Construction du DOM

Backbone sépare clairement la construction du DOM et la logique de la vue. La première est gérée par le moteur de template et la seconde via les bindings de données et les mises à jours impératives du DOM. De son côté, Angular ne les sépare pas mais utilise le même mécanisme via les directives pour créer le DOM et définir le comportement déclaratif des vues.

Logique de vues

Pour Angular, la distinction entre logique de vue déclarative et impérative est claire, la première est gérée par la vue et la seconde par le controlleur.

Cette séparation peut sembler arbitraire mais elle est importante.

Premièrement, cela permet d'identifier clairement ce qui doit être testé unitairement. Ainsi, la logique déclarative de la vue (comme un ng-repeat), n'a pas vocation à être testé. En revanche, écrire des tests pour le controlleur est généralement une bonne chose.

Deuxièmement, toutes les dépendances fonctionnent dans le même sens, de la vue vers le controlleur. Donc le controlleur ne connaît pas la vue ou le DOM. Il permet de mutualiser du code et simplifie les tests unitaires. Inversement, Backbone.View manipule souvent le DOM et refait le rendu de grosses portions via le moteur de templates.

Synchronisation du modèle et de la vue

Angular embarque un support pour le binding de données qui, contrairement à la plupart des frameworks, ne repose pas sur l'observation de propriétés mais sur un système de vérification de l'état.

Ce système de vérification possède des avantages importants :

  • Le modèle n'est pas au courant qu'il est surveillé.
  • Il n'y a pas besoin de définir de dépendances entre des propriétés observables.
  • On peut aussi "observer" des fonctions.

Mais il y a aussi des inconvénients :

  • Lorsque vous intégrez des composants tiers ou des bibliothèques, vous devez vous assurer vous-même qu'Angular voit bien les mises à jour de vos modèles.
  • Dans certains cas, cela peut avoir un effet néfaste sur les performances.

Gestion d'interactions d'UI complexes

Comme déjà mentionné, le controlleur a la responsabilité d'implémenter la logique impérative des éléments de l'UI. Au-delà de ça, il peut aussi être utilisé comme Supervising Presenter pour coordonner les interactions complexes d'UI.

Etats et Routes

Comme Backbone, le router fourni par Angular est très basique et n'est pas suffisant pour créer de vraies applications. Heureusement, nous avons le projet AngularUI Router. Il gère les états de l'application, les vues et supporte les vues imbriquées. En d'autres termes, il apporte tout ce qu'on pourrait attendre d'un router mais vous n'êtes pas obligé de vous y limiter. Comme Backbone, si vous préférez, vous êtes libre d'utiliser une autre bibliothèque pour gérer vos routes.

Création et interconnexions entre composants

Angular met en place une inversion de contrôle, qui comme les systèmes d'injection de dépendances en général, implique de rendre votre code modulaire. Cela rend votre code réutilisable, testable et permet de s'affranchir d'une grande quantité de code répétitif. L'inconvénient est que cela augmente la complexité et réduit notre contrôle sur comment les composants sont créés.

En résumé

C'était une présentation rapide des techniques choisies par Backbone et Angular pour résoudre les problématiques courantes des applications web. Les deux frameworks proposent des solutions complètement différentes pour certains de ces problèmes. Backbone vous offre une plus grande variété d'options lorsqu'il s'agit de faire du rendu de template, de mettre en place des bindings ou de lier des composants. De l'autre côté, Angular propose aussi des solutions à ces problèmes mais dispose de moins d'options pour la construction de vos modèles et controlleurs.

A propos de l'auteur

Victor Savkin est développeur chez Nulogy. Il s'intéresse à la programmation fonctionnelle, à la plate-forme web et au Domain Driven Design. Il travaille sur de grosses applications écrites en JavaScript. Etant un passionné de langages, il passe une grande partie de son temps à coder en Smalltalk, JS, Dart, Scala, Haskell, Clojure et Ioke. Il tient également un blog victorsavkin.com sur la création d'applications en Ruby et JavaScript. Vous pouvez le suivre sur Twitter @victorsavkin.

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT