Spill på Ryggrad og Ember

Så du har akseptert utfordringen å gå tykk på klientsiden; bra gjort. Du har vurdert alle rammene der ute og er usikker på hvilken du skal velge? Du er ikke alene. Les videre.

Min erfaring, når man lærer måten å skrive klientsider, viser seg å være bratt og hardt. Det er ikke lett å bevisst velge å bruke MV * på klienten for noen som skrev JavaScript, basert utelukkende på jQuery og dens plugins. Dette er et helt nytt paradigme; det krever grunnleggende programmeringsferdigheter og en betydelig forståelse av JavaScript (språket) design. Hvis din erfaring gjelder min, så les videre!

Jeg vil forklare de viktigste forskjellene mellom to av de mest populære JavaScript-klientene rammebetingelser: Backbone.js og Ember.js. Hvert av disse verktøyene har sterke poeng, samt svakheter som kan hjelpe deg med å gjøre et mer gjennomtenkt valg.

Ansvarsfraskrivelse: Som programvareprofessorer må vi håndtere mangfold av mening. Backbone og Ember er resultater av erfarne og erfarne fagfolk, som deg og meg. Et verktøy er ikke bedre enn det andre; de tjener bare forskjellige folkemengder og, løser, løser forskjellige problemer. Takk Trek for det gode rådet.


Filosofien

Ryggraden er mye lettere å lære enn Ember.

Først og fremst må du forstå at Backbone og Ember spesielt serverer litt forskjellige folkemengder. Når det gjelder kompleksitet, er Backbone mye lettere å lære enn Ember. Men det er sagt at når du lærer Ember, blir det nesten ikke noe mer komplekst. Ta Treks ord på den. Hvis du bare har begynt med noen ekte JavaScript, er kanskje Backbone ditt verktøy. Hvis du vet at du skal håndtere mye mer enn bare en enkel brukstilstand eller to, kan du helst foretrekke Ember.

Backbone

Jeremy Ashkenas bygget Backbone, så det ville være mulig å ta sannheten ut av DOM. Hva han mener med dette er: hvilken virksomhet du bare brukte jQuery / Mootools / Prototype, kunne og bør bli ekstraheret til rene JavaScript-strukturer - objekter, hvis du vil. Istedenfor å bruke DOM elementer for å definere dine forretningselementer og oppførsel, Backbone inviterer deg til å gjøre det omvendt. JavaScript-objekter er kjernen og DOM er bare en representasjon av dataene.

Med Backbone har du noen påståtte påstander:

  1. Data ligger i JavaScript-objekter, ikke den DOM
  2. Hendelsehåndtering ligger i JavaScript-objekter, ikke jQuery hendelsesbindinger
  3. Måten du lagrer data på en backend-server, gjøres gjennom objekter som inneholder dataene

Du får full kontroll over måten du bygger din app på. Ryggraden var ment å gi deg en grunnleggende måte å designe modellobjektene på og hvordan disse samhandler med hverandre gjennom hendelsesbindinger.

Gjengivelse HTML til DOM er av ditt ansvar. Du er fri til å velge hvilken som helst malmotor: Moustache, DoT, Handlebars, Underscore, etc. Ryggraden inneholder en Utsikt prototype som har ansvaret for å artikulere DOM og JavaScript-kjerne.

Ember

Da Tilde begynte å bygge Ember, gjorde det det med et langt mer utfordrende mål: til gi standardkonvensjoner i utvikling av klientsiden, eliminere så mye boilerplate som mulig. Resultatet er et mye mer ambisiøst rammeverk som tar sikte på en forutsigbar arkitektur og stabil utvikling.

Ember deler noen vanlige punkter med Backbone i den måten den prøver å trekke data og oppførsel ut av DOM ved å gi utvidbare JavaScript-prototyper, men det gjør dette på en helt annen måte enn Backbone gjør.

Ember står på:

  1. Toveis databinding: Objekter i Ember er i stand til å registrere bindinger mellom hverandre. På den måten, når en fast eiendom endres, oppdateres den andre automatisk.
  2. Beregnede egenskaper: Hvis du ønsker å ha en egenskap som er et resultat av en funksjon, kan du opprette dem og tilordne en eiendom som beregnet av den funksjonen.
  3. Mal automatiske oppdateringer: Når et objekt er oppdatert i appen din, vises alle visninger som vises på skjermen som er bundet til objektet automatisk, automatisk endringen, uten boilerplate.

DOM - Visninger

Både Backbone og Ember har vanlige nøkkelbegreper, for eksempel visninger. De representerer begge DOM kommunikasjon, henholdsvis. Måten de oppnår dette konseptet er noe annerledes, skjønt.

Jeg bruker Todo-brukstilfellet til eksemplene nedenfor, inspirert av TodoMVC-utstillingsvinduet.

Backbone

En ryggradsvisning kan noe slikt:

var TaskView = Backbone.View.extend (tagName: "li", mal: "oppgavemal", gjengi: funksjon () // din kode for å gjengi her., events: "click .mark-done" : "mark_as_done", "change .body": "update_body", mark_as_done: funksjon () / * kode her * /, update_body: function () / * kode her * /);

Dette er bare definisjonen av visningen din. Du må instantiere en hvis du vil at den skal være på siden. Noe som dette vil gjøre trikset:

var task_view = ny oppgave (modell: task_model); . $ ( "Kroppen") føyer (task_view.el);

Legg merke til at vi sender en modell inn, slik at du kan holde en referanse til dataobjektet som mater malen. De mal Egenskapen inne i visningen kan brukes til å ringe en utvendig mal, via en identifikator. Jeg har brukt noe som dette tidligere:

var TaskView = Ryggrad.View.extend (mal: "# oppgavemal", gjengiv: funksjon () this. $ el.html (Mustache.render ($ (this.template) .html ()), dette. modell); // snip);

Ember

Ember har en annen tilnærming til synspunkter. Faktisk sier konvensjonen at synspunkter skal snakke med kontroller og ikke modeller direkte. Dette er en god praksis hvis du har tenkt å følge en stabil arkitektur. Jeg skal forklare prøven for samme visning:

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

Det er det. Men hvor er alle gjengivelsen ting? Vel, løfter Ember den kjelen for deg. Bare si hva malen er, kontrolleren som holder dataobjektet, og da trenger du bare å legge det til DOM.

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

Når du oppretter en ny visningsinstans, vil den binde kontrollens innhold (som kan være en Ember.Object eller en liste over dem) til visningen. Når du bestemmer deg for å legge til visningen til DOM, det vil se opp malen og plassere den genererte markeringen for deg.

tanker

Ryggraden er mer eksplisitt og mindre magisk.

Ryggraden er mer eksplisitt og mindre magisk. Du oppretter en Utsikt, fortell det hvilken mal du skal bruke og hvordan, registrer hendelsene og gjør hva du må gjøre. De eier siden. Det er en god start for de som kommer fra en jQuery-bakgrunn. Men når noe må oppdateres i DOM, du vil møte noen boilerplate.

Med Ember er oppdateringer automatisk. Du sier hvilken mal det er, og hendelsesanrop er funksjoner i visningsobjektet. Når et objekt oppdateres, oppdaterer visningen automatisk siden.

Noen vanlige hendelsesbindinger er innebygd i Ember, og andre må legges inn i malen. Det er bra for de som kommer fra et backend-perspektiv, da det reduserer boilerplate på en betydelig måte.


Data - Modeller

Modeller i ryggrad og Ember er ganske like. De har informasjon om en forretningsenhet.

Backbone

Et eksempel på en ryggradsmodell ser slik ut:

var TaskModel = Backbone.Model.extend ();

Med denne enkle koden har du en arbeidsmodell med HVILEful kommunikasjon innebygd. Du får metoder som lagre å fortsette dataene og hente å laste det gratis ingen plugin er nødvendig. Validering er også bygget inn i måten data lagres ved å gi en validere tilbakeringing, som returnerer en boolesk som forteller at posten skal lagres eller ikke. Implementeringen av valideringen er fortsatt for utvikleren å gjøre.

Du oppretter en ny oppgave for å opprette en ny oppgave TaskModel.

var oppgave = ny TaskModel (body: "Mow the lawn", ferdig: false);

Du kan injisere så mange attributter som du vil, fordi oppgavens attributtliste ikke er streng (tenk på det som skjemaløs). Du kan fortsatt stille inn en mislighold eiendom når den utvides Backbone.Model.

Ember

Med Ember er det ingen modeller, bare objekter. Det kan se slik ut:

var TaskObject = Ember.Object.extend ();

Ligner på Ryggrad, må du strekke seg fra Ember.Object å opprette en objektklasse. Det arver all grunnleggende funksjonalitet for en klasse med tilbakeringinger for når den blir forandret, opprettet og ødelagt, blant andre funksjoner. Det har imidlertid ikke backend-kommunikasjon ut av esken. Ember.Data blir utviklet som en forlengelse av Ember.Object av Ember kjerneteamet for å oppfylle det behovet. Den er allerede brukbar, men ikke stabil, så langt som dokumentasjonen forteller.

Ember objekter anses også å være skjemaløs. Hvis du vil injisere standardverdier i Ember-objekter, strekker du ut Ember.Object ved å sende et objekt med så mange attributter som du trenger.

var TaskObject = Ember.Object.extend (body: "Mow the lawn", ferdig: false);

tanker

Backbone har en konsolidert måte å synkronisere med et vedvarende lag over HVILE og det er en god konvensjon der. Det er en mindre ting du må konfigurere for å kunne jobbe med en backend-server.

Ember jobber seg mot å lage Ember.Data klar for produksjon, og det ser lovende ut. Likevel gjør det spesielt at Ember-objekter som har toveisbindinger, gjør det enkelt å utføre forbindelser mellom objekter.

På dette punktet i lesingen har du et bøyningspunkt mellom Backbone stabilitet i kommunikasjon med backend-serveren og Embers bindinger. Det som er viktigst for deg, bør avgjøre din beslutning.


The Lim - Controllers

Det er her rammene deler måter. De har et stort konseptuelt gap på hvordan du limer ting sammen i appen din. Mens Backbone forsøker å forbli så enkelt og fleksibelt som mulig, ofrer Ember kodebasestørrelsen for en bedre arkitektur. Det er en bytte, virkelig.

Advarsel: Følgende eksempler inneholder ikke HTML-maleksempler.

Backbone

Som jeg merket, er Backbone rettet mot enkelhet som konverterer til fleksibilitet, og det oppnår slike egenskaper nøyaktig gjennom Mangelen på en kontrollerklasse. Mesteparten av arbeidshesten er distribuert rundt visninger, samlinger, modeller og ruteren (bør du velge å bruke Backbone Router).

Med tanke på en liste over oppgaver som må styres, vil det kreve:

  • EN Samling å lagre oppgavene.
  • EN Modell å lagre en oppgaveinformasjon.
  • EN Utsikt å representere samlingen.
  • En annen Utsikt å representere hver oppgave.
  • EN Router å administrere nettadresser.

De fleste applikasjonslogikken vil leve i visningene, da de kobler modeller til DOM. Det er ingen klar forskjell på ansvar, da visningen gjør alt. Det kan være bra for små applikasjoner som ikke krever en solid arkitektur.

For å vise en liste over oppgaver, vil du ende opp med noe slikt:

Samling

var TaskList = Backbone.Collection.extend (modell: Oppgave);

Modell

var TaskModel = Backbone.Model.extend ();

Visninger

var TaskListView = Ryggrad.View.extend (render: function () this. $ el.empty (); for (_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 = Ryggrad.View.extend (tagName: "tr", render: function () this. $ el.html (M.to_html (template, this.model.attributes)); returner dette;);

Router

var Ruter = Ryggrad.Router.extend (initialiser: funksjon () this.tasks = new TaskList; this.view = ny TaskListView (collection: this.tasks);, ruter: "": "tasks_list" ,, tasks_list: funksjon () this.view.render (); $ ("bucket: first"). html (this.view.el);, start: funksjon () Backbone.history.start pushState: true, root: "/ tickets /"););

Legg merke til at samlingen ikke har en egen mal; heller, det delegerer til en enkelt oppgavevisning som blir gjengitt og vedlagt til sluttresultatet som blir lagt på siden.

Ember

Antallet klasser som kreves for å ha samme oppsett er litt større.

  • I stedet for a Samling, du ville ha en ArrayController, som fungerer veldig mye likt.
  • Du vil ha en ekstra ObjectController for å administrere en enkelt oppgave.
  • I stedet for a Modell, du ville ha en Gjenstand / DS.Model, som fungerer likt.
  • Du ville ha samme type Utsikts.
  • EN Router er også ansvarlig for å administrere nettadresser.

Du kan tenke at de to rammene ikke er så forskjellige fra hverandre. Det er ganske fristende, men det er ikke helt sant. Noen spesielle forskjeller er:

  1. Kontrolleren er ansvarlig for å samhandle med dataobjektene, ikke visningen.
  2. Utsikten er ansvarlig for håndtering av DOM, ikke kontrolleren.
  3. Visningene kommuniserer med kontrolleren, ikke direkte til dataobjektene.
  4. Dataene som mater visningsmalen, er faktisk en binding til kontrollerens data.
  5. Ruteren er mer av en statlig leder, som inneholder mye mer enn å håndtere nettadresser.

Adskillelsen av bekymringer er god på lang sikt. Controller håndterer data, visninger håndterer DOM, periode. Denne typen avkoblet og sammenhengende, kjelefri design gjør det mulig for mer fokusert testbarhet.

Implementeringen for å vise samme oppgaveliste vil være noe som følger med, vurderer en full Ember-applikasjon:

Programrotsarkitektur

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

Gjenstand

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

Controllers

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

Utsikt

App.TasksView = Ember.View.extend (malnavn: "min liste");

Router

App.Router = Ember.Router.extend (root: Ember.Route.extend (indeks: Em.Route.extend (rute: '/', connectOutlets: funksjon (router) router.get ('applicationController') .ConnectOutlet ('oppgaver');));

I Embers tilfelle er det ikke mye å si om hvordan ting gjøres inni. Alt dette kjelen er tatt bort, slik at du kan fokusere på det som virkelig betyr noe i appen din: du definerer et oppgaveobjekt, en oppgaveliste-kontroller med en gruppe som heter innhold, Visningen din og ruteren kombinerer helt enkelt alle sammen og legger den på siden.

tanker

Etter å ha forstått hvordan Ember virkelig fungerer, begynner det å bli befriende.

Forutsigbart var dette segmentet det vanskeligste å forstå på begge rammene. Ryggraden var definitivt enklere å lære, og den fleksible naturen gir kontroll over måten objekter og DOM samhandle. Dette kan være bra for deg, hvis du virkelig trenger den typen fleksibilitet, men likevel vil opprettholde en struktur for appens logikk på JavaScript-siden.

Når det gjelder Ember, kan den fantastiske implementeringen være skummel først. Men etter å ha forstått hvordan Ember virkelig fungerer, begynner det å bli befriende. Alle konvensjonene rammeverket sett for deg, frigjør deg fra boilerplate og konfigurasjon, slik at du kan fokusere på appen din. Dette ligner på hva Rails gjorde for serverside utvikling som fanget så mye oppmerksomhet.


Hva setter dem fra hverandre?

Ember var ment å løfte de vanlige byrdene av JavaScript-utvikling i nettleseren.

Hittil har hele poenget med å vise de to verktøyene vært å anerkjenne deres enkle og edle formål: å delegere makt til klientsiden, gjennom både struktur og metode.

Kjernekjernestyrke er definitivt KISS-tilnærmingen. Det gir deg det minste å slippe av DOM som kjernen tilhengeren av appen din, og begynn å bruke ekte JavaScript-objekter som kan testes og utformes på riktig måte.

Ryggraden kommer fullpakket med samlinger, modeller, visninger og ruteren, blant annet små verktøy. Du er fri til å gjøre det du vil med dem.

Ember, derimot, ble bygget med et annet tenkemåte, da det tar sikte på en mye mer konvensjonell og meningsfull måte å bygge webapper på. Det takler et sett med vanlige problemer, for eksempel boilerplate, data bindende og DOM templere slik at du ikke trenger å bekymre deg for dem fra starten. Ember var ment å løfte de vanlige byrdene av JavaScript-utvikling i nettleseren.

Ember kommer fullpakket med objekter, kontrollere, automatisk oppdatering av visninger, statlige maskiner, bindinger, observatører og en ruter (som også er en statlig maskin), alle trosset med en god dose konvensjoner. Du har en arkitektur som allerede er utformet og klar til å begynne å virke uten å miste fokus.


Konklusjon

Husk læringsgapet. Din erfaring og kulturarv vil sterkt diktere hvor fort du blir med på klientsiden. Hvis du er redd for hva du skal gjøre eller hvilken du skal velge, slo jeg en nerv av deg, og det er bra! Ønsker et godt svar å velge? Både.

Det handler om JavaScript

Hvis du er usikker på hvordan selv jQuery gjør all sin magi, så begynn å lære Ryggrad. Det er lettere å begynne med, og dokumentasjonen er død enkel å lese og forstå. Når du er ferdig, begynn å bygge noe. Gå skittent. Sjekk disse opplæringsprogrammene hvis du trenger litt hjelp.

Hvis du fortsatt er i mørket, les Yehuda Katz innlegg om hvordan JavaScript fungerer.

Når du får en bedre visjon om hvordan JavaScript fungerer som et språk, vil du begynne å få en bedre forståelse av hvordan objektene samhandler med hverandre. Når du gjør det, gå til Ember. Det er mer komplisert først, men ikke gi opp. Start å lese dokumentene og veiledningene. Du vil kanskje sjekke Trek Glowackis bloggoppføring like før du får hendene skitne.

Min bunnlinje

Personlig lurer jeg mot Ember; Jeg nyter robustheten i makroskala, og jeg foretrekker også sine konvensjoner. Ryggraden er et mer formet og enklere verktøy for mindre apper eller små funksjoner i en eksisterende app.

Jeg lærer fortsatt begge, og har noen utfordringer å takle:

  • Automatiske tester: hvordan du gjør dem og hvilken testpakke er bedre. Qunit eller Jasmine? Headless (Thinking PhantomJS), Node eller nettleser test runner? Ikke sikker enda.
  • Filopplastinger
  • internasjonalisering

Hva er tankene dine på hele denne debatten? Har du noen utfordringer i tankene? Noen problemer eller hindringer? Gi meg beskjed!