Kokeilin hiljattain ohjelmoida melko yksinkertaisen pienen sovelluksen sekä Emberillä että Backbonella. Vedän tähän yhteen oleellisimmat huomaamani erot. Jos kyseiset frameworkit eivät ole tuttuja, niin niillä ohjelmoidaan webbiselaimessa toimivia JavaScript-sovelluksia. Ideana on rakentaa sovellukset MVC-rakenteen mukaisesti siten, että tietomallit, kontrollerit ja näkymät pystytään selvästi erottamaan toisistaan. Näin sovelluksista tulee selkeämpiä ja helpompia ylläpitää.

Dynaaminen sidonta

Ember.js:n selvästi erottuvin ominaispiirre on tapa, jolla tietomallien property-arvot voidaan sitoa näkymiin dynaamisesti. Kun property on kerran sidottu HTML:ään DOM-puun kautta, se päivittyy sinne automaattisesti aina myöhemminkin, kun propertyn arvoa muutetaan JavaScriptissä.

Tämä edellyttää, että Ember.js:n on oltava tietoinen HTML:n rakenteesta, mikä hieman monimutkaistaa templatejen ohjelmoimista. Esimerkiksi attribuutteja ei voi merkitä perinteiseen tapaan muodossa <a href="{{link}}"> vaan ne ovatkin muotoa <a {{bindAttr href="link"}}>. Tarvittava vaivannäkö on kuitenkin melko pieni suhteessa saatuun etuun nähden.

Backbonessa kaikki tämä täytyy tehdä itse kuuntelemalla Model- tai Collection-luokkien eventtejä ja renderöimällä sitten tarvittavat templatet kokonaan uudelleen. Mitä enemmän sovellus käsittelee erilaisia tietorakenteita, sitä enemmän 'turhaa' koodia tarvitaan huolehtimaan niiden päivittämisestä ruudulle.

Dynaamiset kontrollirakenteet

Edellä mainittu dynaamisuus pätee Emberissä myös templateissa käytettyihin kontrollirakenteisiin kuten {{#if}}-ehtoihin ja {{#each}}-silmukoihin. Jos if-lauseelle ehtona annetun propertyn arvo muuttuu, Ember osaa automaattisesti renderöidä kyseisen kohdan templatesta uudelleen.

Käytännössä tämä tarkoittaa, että ohjelmoija voi unohtaa, mitä kaikkia tietokenttiä templateissa käytetään ja luottaa siihen, että ne päivittyvät itsekseen ruudulle aina kun tarvetta on. Tästä on hyötyä erityisesti silloin, kun sovellukseen liittyy erilaisia REST-rajapintojen kutsuja ja muuta asynkronisuutta, joka tekee tiedon päivittymisen käsittelystä hankalampaa.

Kunhan data vain on alkuperäisessä tietomallissa oikein, Ember päivittää sen aina kaikkialle muuallekin. Kirjaston kehittäjät lupaavat, että päivittäminen HTML:ään on suorituskykyistä ja optimoitua siten, ettei DOM-puuta muokkailla turhaan ellei sille ole tarvetta.

Templatet ja property-muuttujat

Ember integroituu Backbonea paremmin Handlebars-moottoriin. Backbone-ohjelmoinnille on tyypillistä, että Model- ja Collection-tietomalleja ei voi käyttää templateissa sellaisenaan. Erityisen hankalaa on se, että tietomallien property-kenttiä luetaan get('name') -kutsuilla, mutta tämä ei toimi Handlebarsin tai Mustachen kanssa. Jos osa propertyistä on oikeita kenttiä ja osa laskennallisia arvoja (funktioita), templatessa täytyy käyttää välillä muotoa {{attributes.name}} ja välillä {{name}}.

Ember puolestaan normalisoi kaikki kentät siten, että templateissa käytetään aina muotoa {{name}}, eikä sillä ole merkitystä, onko kyseessä oikea kenttä vai funktiolla laskettu arvo. Lasketuille arvoille Ember tarjoaa vieläpä riippuvuussuhteiden määrittelyn siten, että jos "fullName" riippuu vaikkapa kentistä "firstName" ja "lastName", niin kumman tahansa muuttaminen päivittää lasketun arvon myös käyttöliittymään.

Mikä parasta, näitä laskennallisia arvoja voidaan käyttää myös ehtoina #if-lauseissa. Logiikka siirtyy siis kokonaan pois template-koodista. Templateille annetaan vain valmiiksi laskettuja "kyllä"- tai "ei"-totuusarvoja. Jos jokin niihin vaikuttava tietokenttä jossain vaiheessa päivittyy tietomalleissa, käyttöliittymäkin päivittyy automaattisesti ruudulle.

Kontrolleriluokat

iOS-ohjelmoijille on tuttua, että ohjelmointiympäristö tarjoaa valmiita UIViewController-luokkia, jotka huolehtivat rajapinnasta käyttöliittymän ja tietomallien välillä. Esimerkiksi UITableViewController ohjaa taulunäkymää ja kytkee sen haluttuun tietomalliin.

Backbonessa tällaisia kontrollereita ei ole lainkaan, vaan ohjelmoijan on itse päätettävä miten haluaa ne toteuttaa. Tästä seuraa helposti sekasotkua, jossa näkymät käyttävät välillä tietomalleja suoraan ja välillä taas niitä päivitetään jostain tapahtumankäsittelijästä. Pahinta on, jos tietomalliin aletaan lisätä koodia, joka ohjaa käyttöliittymää.

Ember tarjoaa valmiina ratkaisuna ArrayController-luokan, joka on tarkoitettu kytkemään listamuotoinen tietomalli käyttöliittymänäkymään. Ohjelmoija voi periä ArrayControllerin ja tehdä oman luokan, joka ohjaa käyttöliittymää halutulla tavalla. Näin itse tietomallia ei tarvitse sotkea käyttöliittymään liittyvällä ohjelmakoodilla.

Handlerbars-template voi käyttää ArrayControllerista perittyä luokkaa aivan kuin se käyttäisi alkuperäistä array-tietomallia, eli esimerkiksi {{#each}} toimii sellaisenaan. Lisäksi se näkee kaikki omaan luokkaan lisätyt toiminnot. Kontrolleriluokka on myös luonnollinen paikka erilaiselle käyttöliittymään liittyvälle tapahtumankäsittelykoodille.

Yhteenveto

Kaiken kaikkiaan uskaltaisin väittää, että Ember on data binding -ominaisuuksiensa ansiosta merkittävästi Backbonea edellä. Monimutkaisemmissa JavaScript-sovelluksissa sen oikeinlaisella hyödyntämisellä voi saavuttaa huomattavaa etua. Suuri osa perinteisestä tapahtumien kuuntelusta ja käsittelystä voidaan yksinkertaisesti jättää Ember-sovelluksista kokonaan pois.

Tämä pätee web-sovelluksiin, joilla käsitellään interaktiivisesti paljon erilaista dataa. Tavallisissa webbisaiteissa hyöty on vähäisempi.

Published 5.3.2012