Game On Backbone et Ember

Donc, vous avez accepté le défi d’aller de l’avant du côté du client; bien joué. Vous avez examiné tous les cadres existants et vous ne savez pas lequel choisir? Tu n'es pas seul. Continuer à lire.

Mon expérience, lors de l'apprentissage de la manière d'écrire des applications côté client, s'avère être difficile et difficile. Ce n'est pas facile de choisir délibérément d'utiliser MV * sur le client pour quelqu'un qui a écrit JavaScript, entièrement basé sur jQuery et ses plugins. C'est un paradigme entièrement nouveau. cela nécessite des compétences de base en programmation et une compréhension considérable de la conception de JavaScript (le langage). Si votre expérience concerne la mienne, alors lisez la suite!

Je vais expliquer les principales différences entre deux des infrastructures JavaScript les plus populaires: Backbone.js et Ember.js. Chacun de ces outils a des points forts, ainsi que des faiblesses qui pourraient vous aider à faire un choix plus réfléchi..

Avertissement: en tant que professionnels du logiciel, nous devons faire face à la diversité des opinions. Backbone et Ember sont le résultat de professionnels avisés et expérimentés, comme vous et moi. Un outil n'est pas meilleur que l'autre; ils servent juste des foules différentes et, par conséquent, résolvent différents problèmes. Merci Trek pour le conseil solide.


La philosophie

Backbone est beaucoup plus facile à apprendre que Ember.

Avant tout, vous devez comprendre que Backbone et Ember servent en particulier des foules légèrement différentes. En ce qui concerne la complexité, Backbone est beaucoup plus facile à apprendre que Ember. Cependant, il est dit qu'une fois que vous avez appris l'Embre, cela devient à peine plus complexe. Prenez le mot de Trek à ce sujet. Si vous commencez à utiliser du vrai JavaScript, alors peut-être que Backbone est votre outil. Si, toutefois, vous savez que vous allez traiter beaucoup plus qu'un simple cas d'utilisation, vous préférerez peut-être Ember.

Colonne vertébrale

Jeremy Ashkenas a construit Backbone afin qu’il soit possible de sortir la vérité du DOM. Ce qu’il entend par ceci est que: quelle que soit votre activité commerciale utilisant uniquement jQuery / Mootools / Prototype, elle pourrait et devrait être mieux extraite dans des structures JavaScript pures - des objets, si vous voulez. À la place d'utiliser DOM éléments permettant de définir vos éléments métier et votre comportement, Backbone vous invite à le faire à l’inverse. Les objets JavaScript sont le noyau et le DOM est simplement une représentation de ces données.

Avec Backbone, vous avez des assertions données:

  1. Les données se trouvent dans des objets JavaScript, pas dans la DOM
  2. La gestion des événements repose sur des objets JavaScript et non sur des liaisons d'événements jQuery.
  3. La façon dont vous enregistrez les données sur un serveur principal se fait via les objets qui contiennent les données.

Vous disposez d'un contrôle total sur la manière dont vous construisez votre application. Backbone était destiné à vous fournir un moyen simple de concevoir vos objets de modèle et leur interaction les uns avec les autres via des liaisons d'événements..

Le rendu HTML au DOM est de votre responsabilité. Vous êtes libre de choisir n’importe quel moteur de template: Moustache, DoT, Guidon, Underscore, etc. Le backbone contient un Vue prototype qui a la responsabilité d’articuler les DOM et votre noyau JavaScript.

Ember

Lorsque Tilde a commencé à construire Ember, il l’a fait avec un objectif beaucoup plus ambitieux: Fournir des conventions standard dans le développement côté client, en éliminant le plus grand nombre possible de passe-partout. Le résultat est un cadre beaucoup plus ambitieux qui vise une architecture prévisible et un développement constant.

Ember partage des points communs avec Backbone dans la façon dont il tente d'extraire des données et un comportement du système. DOM en fournissant des prototypes JavaScript extensibles, mais il le fait d'une manière très différente de celle de Backbone.

Ember se dresse sur:

  1. Liaison de données bidirectionnelle: les objets dans Ember peuvent enregistrer des liaisons entre eux. De cette façon, chaque fois qu'une propriété liée change, l'autre est automatiquement mise à jour.
  2. Propriétés calculées: si vous souhaitez avoir une propriété résultant d'une fonction, vous pouvez les créer et attribuer une propriété calculée par cette fonction.
  3. Mises à jour automatiques des modèles: lorsqu’un objet est mis à jour dans votre application, toutes les vues actuellement affichées à l’écran et liées à cet objet reflètent automatiquement le changement, sans aucun passe-passe.

Le DOM - Vues

Backbone et Ember ont des concepts clés communs, tels que vues. Ils représentent tous les deux DOM communication, respectivement. La façon dont ils réalisent ce concept est quelque peu différente, bien que.

Je vais utiliser le cas d'utilisation de Todo pour les exemples ci-dessous, inspirés de la vitrine de TodoMVC.

Colonne vertébrale

Une vue dorsale pourrait ressembler à ceci:

var TaskView = Backbone.View.extend (tagName: "li", template: "task-template", rendu: function () // votre code à restituer ici., events: "click .mark-done" : "mark_as_done", "change .body": "update_body", mark_as_done: fonction () / * code ici * /, update_body: fonction () / * code ici * /);

Ceci est simplement la définition de votre vue. Vous devrez en instancier un si vous voulez qu'il soit dans la page. Quelque chose comme ça va faire l'affaire:

var task_view = new Task (modèle: modèle_tâche); $ ("body"). append (task_view.el);

Notez que nous transmettons un modèle afin que vous puissiez conserver une référence à l'objet de données qui alimente le modèle. le modèle propriété à l'intérieur de la vue peut être utilisée pour appeler un modèle externe, via un identifiant. J'ai utilisé quelque chose comme ça dans le passé:

var TaskView = Backbone.View.extend (template: "# task-template", render: function () this. $ el.html (Moustache.render ($ (this.template) .html ()), cela. modèle); // snip);

Ember

Ember a une approche différente des points de vue. En fait, la convention stipule que les vues doivent parler aux contrôleurs et non aux modèles directement. C'est une bonne pratique si vous avez l'intention de suivre une architecture stable. Je vais expliquer l'exemple pour la même vue:

var TaskView = Ember.View.extend (templateName: "task-template", mark_as_done: function () / * code ici * /, update_body: function () / * code ici * /);

C'est tout. Mais où sont tous les trucs de rendu? Eh bien, Ember soulève ce passe-partout pour vous. Dites simplement en quoi consiste le modèle, le contrôleur qui contient l’objet de données, et il vous suffit ensuite de l’ajouter au DOM.

var task_view = TaskView.create (controller: task_controller // Ember.ObjectController); task_view.append ();

Lors de la création d’une nouvelle instance de vue, il va lier le contenu du contrôleur (qui peut être une Ember.Object ou une liste d'entre eux) à la vue. Lorsque vous décidez d’ajouter la vue au DOM, il recherchera le modèle et placera le balisage généré à votre place.

Pensées

Backbone est plus explicite et moins magique.

Backbone est plus explicite et moins magique. Vous créez un Vue, Dites-lui quel modèle utiliser et comment, enregistrez les événements et faites ce que vous devez faire. Ils possèdent la page. C'est un bon début pour ceux qui viennent d'un milieu jQuery. Cependant, quand quelque chose doit être mis à jour dans le DOM, vous ferez face à un passe-partout.

Avec Ember, les mises à jour sont automatiques. Vous dites de quel modèle il s'agit et les rappels d'événements sont des fonctions à l'intérieur de l'objet de vue. Chaque fois qu'un objet est mis à jour, la vue met automatiquement à jour la page..

Certaines liaisons d'événements communes sont intégrées à Ember et d'autres doivent être insérées dans le modèle. C'est bon pour ceux qui viennent d'un point de vue back-end, car cela réduit considérablement l'effet standard.


Les données - modèles

Les modèles dans Backbone et Ember sont assez similaires. Ils détiennent des informations pour une entreprise.

Colonne vertébrale

Un exemple de modèle Backbone ressemble à ceci:

var TaskModel = Backbone.Model.extend ();

Avec cette simple ligne de code, vous avez un modèle de travail avec DU REPOScommunication complète intégrée. Vous obtenez des méthodes comme enregistrer conserver les données et aller chercher le charger gratuitement; aucun plugin n'est requis. La validation est également intégrée à la façon dont les données sont sauvegardées en fournissant un valider callback, qui retourne un booléen indiquant à l’enregistrement d’être sauvegardé ou non. L'implémentation de la validation reste à faire par le développeur.

Pour créer une nouvelle tâche, vous instanciez une nouvelle TaskModel.

var task = new TaskModel (body: "Tondez la pelouse", done: false);

Vous pouvez injecter autant d'attributs que vous voulez, car la liste d'attributs de la tâche n'est pas stricte (pensez-la comme sans schéma). Vous pouvez toujours définir un défauts propriété lors de l'extension Backbone.Model.

Ember

Avec Ember, il n'y a pas de modèles, juste des objets. Cela pourrait ressembler à quelque chose comme ça:

var TaskObject = Ember.Object.extend ();

Semblable à Backbone, vous devez étendre de Ember.Object créer une classe d'objets. Il hérite de toutes les fonctionnalités de base d'une classe avec des rappels pour le moment où elle est modifiée, créée et détruite, entre autres fonctionnalités. Il n’a toutefois pas de communication dorsale prête à l'emploi. Ember.Data est développé comme une extension de Ember.Object par l'équipe de base Ember pour répondre à ce besoin. Il est déjà utilisable mais pas stable dans la mesure où la documentation l'indique.

Les objets de braise sont également considérés comme sans schéma. Pour injecter des valeurs par défaut dans les objets Ember, vous étendez Ember.Object en passant un objet avec autant d'attributs que nécessaire.

var TaskObject = Ember.Object.extend (body: "Tondez la pelouse", done: false);

Pensées

Backbone a une méthode consolidée de synchronisation avec une couche de persistance sur DU REPOS et c'est une bonne convention là-bas. C'est une chose de moins que vous devez configurer pour travailler avec un serveur principal.

Ember travaille pour faire Ember.Data prêt pour une utilisation en production, et cela semble prometteur. Même dans ce cas, la particularité des objets Ember d’avoir des liaisons bi-directionnelles facilite la connexion entre les objets..

À ce stade de votre lecture, vous avez un point d'inflexion entre la stabilité de Backbone dans la communication avec le serveur principal et les liaisons d'Ember. Tout ce qui est le plus important pour vous devrait déterminer votre décision.


La colle - contrôleurs

C'est ici que les cadres se séparent. Ils ont un énorme fossé conceptuel sur la manière de coller des éléments dans votre application. Alors que Backbone s'efforce de rester aussi simple et flexible que possible, Ember sacrifie la taille de la base de code pour une meilleure architecture. C'est un compromis, vraiment.

Avertissement: les exemples suivants ne contiennent pas d'exemples de modèles HTML.

Colonne vertébrale

Comme je l’ai noté, Backbone vise une simplicité qui se transforme en flexibilité et permet de réaliser ces attributs avec précision. le manque d'une classe de contrôleur. La plupart des outils de travail sont répartis entre des vues, des collections, des modèles et le routeur (si vous choisissez d’utiliser Backbone). Routeur).

Considérant une liste de tâches à gérer, il faudrait:

  • UNE Collection pour stocker les tâches.
  • UNE Modèle stocker les informations d'une tâche.
  • UNE Vue représenter la collection.
  • Un autre Vue représenter chaque tâche.
  • UNE Routeur gérer les URL.

La plupart des logiques d’application vivront dans les vues, car elles relient les modèles au DOM. Il n'y a pas de distinction claire des responsabilités, car la vue fait tout. Cela peut être bon pour les petites applications qui ne nécessitent pas une architecture solide.

Pour afficher une liste de tâches, vous obtiendrez quelque chose comme ceci:

Collection

var TaskList = Backbone.Collection.extend (model: Task);

Modèle

var TaskModel = Backbone.Model.extend ();

Des vues

var TaskListView = Backbone.View.extend (render: function () this. $ el.empty (); pour (_i = 0, _i < this.collection.length; _i++)  var task = this.collection.models[_i]; this.$el.append(this.renderItem(task));  var tasks = this.$el.html(); this.$el.html(Mustache.to_html(template,  tasks: tasks, no_tasks: !this.collection.length )); , renderItem: function(task)  var view = new Row( model: task ); var el = view.render(); return el.el; , );
var TaskView = Backbone.View.extend (tagName: "tr", render: function () this. $ el.html (M.to_html (modèle, this.model.attributes)); retourne ceci;);

Routeur

var Router = Backbone.Router.extend (initialize: function () this.tasks = new TaskList; this.view = new TaskListView (collection: this.tasks);: itinéraires: "": "tasks_list" ,, tasks_list: function () this.view.render (); $ (". bucket: first"). html (this.view.el);, start: function () Backbone.history.start ( pushState: true, root: "/ tickets /"););

Notez que la collection n'a pas de modèle propre; au lieu de cela, il délègue à une seule vue de tâche en cours de rendu et ajouté au résultat final mis sur la page.

Ember

Le nombre de classes requis pour avoir la même configuration est légèrement plus grand.

  • Au lieu d'une Collection, vous auriez un ArrayController, qui fonctionne très bien.
  • Vous auriez un extra ObjectController pour gérer une seule tâche.
  • Au lieu d'une Modèle, vous auriez un Objet / DS.Modèle, qui fonctionnent pareillement.
  • Vous auriez le même genre de Vues.
  • UNE Routeur est également responsable de la gestion des URL.

Vous pensez peut-être que les deux cadres ne sont pas trop différents l'un de l'autre. C'est plutôt tentant, mais ce n'est pas tout à fait vrai. Quelques différences particulières sont:

  1. Le contrôleur est responsable de l’interaction avec les objets de données, pas avec la vue..
  2. Les vues sont responsables de la gestion des DOM, pas le contrôleur.
  3. Les vues communiquent avec le contrôleur, pas directement avec les objets de données.
  4. Les données qui alimentent le modèle de vue constituent en réalité une liaison aux données du contrôleur..
  5. Le routeur est plus qu'un gestionnaire d'état, qui comprend beaucoup plus que la gestion des URL.

La séparation des préoccupations est bonne à long terme. Le contrôleur gère les données, les vues gèrent la DOM, période. Ce type de conception découplée et cohérente sans chaudière permet une testabilité plus ciblée.

L'implémentation permettant d'afficher la même liste de tâches ressemblerait à quelque chose comme ceci, en considérant une application Ember complète:

Architecture racine d'application

window.App = Ember.Application.create (); App.ApplicationController = Ember.ObjectController.extend (); App.ApplicationView = Ember.View.extend (templateName: "application");

Objet

App.Task = Ember.Object.extend ();

Contrôleurs

App.TasksController = Ember.ArrayController.extend (content: []);

Vue

App.TasksView = Ember.View.extend (templateName: "ma-liste");

Routeur

App.Router = Ember.Router.extend (racine: Ember.Route.extend (index: Em.Route.extend (route: '/', Connecteurs / Connecteurs, Connecteurs, Commandes / Connecteurs, Guide de l'utilisateur, E-mail. .connectOutlet ('tasks');));

Dans le cas d'Ember, on ne parle pas beaucoup de la façon dont les choses se font à l'intérieur. Tout ce bazar est enlevé pour que vous puissiez vous concentrer sur ce qui compte vraiment dans votre application: vous définissez un objet de tâche, un contrôleur de liste de tâches avec un tableau appelé contenu, votre vue et le routeur les combine simplement et les met dans la page.

Pensées

Après avoir compris comment fonctionne vraiment Ember, il commence à devenir libératrice.

De manière prévisible, ce segment était le plus difficile à saisir sur les deux cadres. Backbone était définitivement plus facile à apprendre et sa nature flexible permet de contrôler la façon dont les objets et DOM interagir. Cela pourrait être bon pour vous, si vous avez vraiment besoin de ce type de flexibilité mais que vous souhaitez tout de même conserver une structure pour la logique de votre application dans le côté JavaScript..

Quant à Ember, sa mise en œuvre à couper le souffle pourrait faire peur au début. Cependant, après avoir compris comment fonctionne réellement Ember, il commence à devenir libératoire. Toutes les conventions que le cadre vous a définies vous libèrent de la configuration standard et vous permettent de vous concentrer sur votre application. Ceci est similaire à ce que Rails a fait pour le développement côté serveur qui a attiré tant d'attention.


Ce qui les distingue?

Ember était destiné à lever le fardeau commun du développement JavaScript dans le navigateur.

Jusqu'ici, l'intérêt de ces deux outils a été de reconnaître leur seul et noble objectif: déléguer Puissance au côté du client, à travers la structure et la méthode.

La force principale de Backbone est clairement son approche KISS. Il vous fournit le minimum pour lâcher de la DOM en tant que principal supporteur de votre application, et commencez à utiliser de vrais objets JavaScript pouvant être testés et conçus correctement.

Backbone est fourni avec des collections, des modèles, des vues et le routeur, entre autres petits utilitaires. Vous êtes libre de faire ce que vous voulez avec eux.

Ember, d’autre part, a été conçu dans un esprit différent, dans la mesure où il vise une manière beaucoup plus conventionnelle et plus avisée de créer des applications Web. Il aborde un ensemble de problèmes communs, tels que le "warmplate", la liaison de données et DOM la création de modèles afin que vous n'ayez pas à vous en soucier dès le début. Ember était destiné à lever le fardeau commun du développement JavaScript dans le navigateur.

Ember est fourni avec des objets, des contrôleurs, des vues à mise à jour automatique, des machines à états, des liaisons, des observateurs et un routeur (qui est aussi une machine à états), le tout avec une bonne dose de conventions. Vous avez une architecture déjà conçue et prête à commencer à fonctionner sans perdre le focus.


Conclusion

Attention à l'écart d'apprentissage. Votre expérience et votre patrimoine culturel dicteront fortement la rapidité avec laquelle vous rejoindrez le côté client. Si vous avez peur de ce qu'il faut faire ou de ce qu'il faut choisir, je vous ai touché un nerf et c'est bien! Vous voulez une bonne réponse sur laquelle choisir? Tous les deux.

Tout tourne autour du JavaScript

Si vous ne savez pas comment même jQuery fait toute sa magie, commencez à apprendre Backbone. Il est plus facile de commencer et la documentation est extrêmement simple à lire et à comprendre. Une fois que vous avez terminé, commencez à construire quelque chose. Allez sale. Consultez ces tutoriels si vous avez besoin d'aide..

Si vous êtes toujours dans le noir, lisez les entrées de Yehuda Katz sur le fonctionnement de JavaScript..

Une fois que vous aurez une meilleure vision du fonctionnement de JavaScript en tant que langage, vous commencerez à mieux comprendre comment les objets interagissent les uns avec les autres. Quand tu le feras, choisis Ember. C'est plus compliqué au début, mais n'abandonnez pas. Commencez à lire la documentation et les guides. Vous voudrez peut-être vérifier l'entrée du blog de Trek Glowacki juste avant de vous salir les mains.

Ma ligne de fond

Personnellement, je me penche vers Ember; J'apprécie sa robustesse à l'échelle macro et je préfère aussi ses conventions. Backbone est un outil plus malléable et plus facile pour les petites applications ou les petites fonctionnalités d'une application existante..

J'apprends toujours les deux et j'ai quelques défis à relever:

  • Tests automatiques: comment les effectuer et quelle suite de tests est la meilleure. Qunit ou Jasmine? Sans tête (en pensant à PhantomJS), coureur de test de noeud ou de navigateur? Pas encore sûr.
  • Fichiers téléchargés
  • Internationalisation

Quelles sont vos pensées sur toute cette débâcle? Avez-vous des défis en tête? Des difficultés ou des obstacles? Faites le moi savoir!