Monday, March 4, 2013

Client Side JavaScript MV* With Ember.js

My team at work is evaluating the suitability of several tools for client-side application development. We’re looking at building out some non-trivial applications on the client and wanted to make the best collective, educated decision on the best tool(s) for the job.

The tools we’ve been looking at include:

  • Backbone

  • Knockout

  • Angular

  • Ember

Backbone


I’ve already grown pretty familiar with Backbone, having spearheaded its adoption into our tools set a year or so ago. We’ve built out a few non-trivial applications with Backbone and admire it’s simplicity and elegance. Backbone is lean and non-prescriptive, it’s a minimalistic library that gives you the most basic structure and tools for event-based model management.
Backbone is view-agnostic, meaning it gives you a basic wrapper for an event-based view and leaves rendering, model binding and plumbing up to you. It’s designed to work with a REST API out-of-box but can be easily customized. A router is provided but is optional

Knockout


I built out a fairly simplistic but non-trivial demo application with Knockout a few months back. Microsoft is bundling it with VS 2012 so I thought it was worth taking a look under the hood. Knockout’s focus is on the UI, and it’s primary selling point is declarative two-way model binding. It’s a pretty slick library, but the DOM-based templating and mixture of behavior with markup leave me a little concerned with regard to maintainability at a large scale. My takeaway was that Knockout is best suited for smaller applications or “islands of richness” in traditional web applications.

Angular


Angular is currently being evaluated by one of my colleagues. It’s a research project from Google, which they describe as a “Superheroic JavaScript MVW Framework.” The “W” stands for Whatever, so you have models, views, and “whatever” you need to get the rest done. It uses declarative DOM based templating and a modular approach that is non-prescriptive. I’ll have to look under the hood myself before I can give an educated opinion on Angular.

Ember


Last but not least, I’ve been building out a demo with Ember.js. Ember takes a different approach in that it’s designed as a full-fledged application framework. It was designed by Rails and SproutCore contributors Yehuda Katz and Tom Dale, and is essentially a ground-up rewrite of SproutCore. It’s an impressive piece of work, there’s much to admire here, though there are some non-trivial concerns also.

Initial thoughts:

  • The learning curve is fairly steep, mostly getting your head around the core concepts of the framework. The Rails heritage of Ember is apparent: the framework is URL-centric - with the router front-and-center - and has a strong preference for convention over configuration. This made it a little difficult to get started at first, coming from a C#/.NET background where configuration is preferred.

  • The documentation is still in-progress. The “Ember Guides” are somewhat vague and inconsistent, making it hard to get up to speed.

  • The framework is nearing a 1.0 release, after which the core team intends to stabilize and lock it down. Until then, it is very much in transition, with regular breaking changes.
Ember.Application

Ember is designed for SPA (single page application) development, and controls your entire document. It requires a global application variable, to which you assign the result of Ember.Application.create(). The Application object is responsible for:

  • Acting as your application’s namspace

  • Event delegation: adds listeners to your document and delegates them to your views

  • Automatically renders your topmost application template

  • Creates a router and starts routing with the current URL
I have been using RequireJS/AMD as part of my tool set for a while now, and had hoped to create an Ember application without introducing a global application variable. Ember co-creator Tom Dale is not a fan of AMD - http://tomdale.net/2012/01/amd-is-not-the-answer/ - but I’m among a growing number of JavaScript developers embracing it as a stepping stone to native modules.

I created all my Ember entities as AMD modules, and used the undocumented (as yet) Application.createWithMixins() function to pass in a hash of the resulting module return values, rather than adding instances to the created application.

Routing

Routing is the primary focus in Ember. Every state in an Ember application is represented by a URL. Your models, views, and controllers all stem from a URL route and are associated by naming convention to that route. If you follow Ember conventions, and don’t require custom code, Ember will provide a router handler and controller “automagically,” dramatically reducing boilerplate code for common scenarios.

Routes with a dynamic segment, like our “agent” resource above for example, have a common hook that is implemented automatically if not specified by a route handler:


What’s happening here is: the route handler is specifying a model that represents the current state (route) of the application; the default hook is to call a find() method on the corresponding model (named “Agent” by convention after the route) and passing in the dynamic segment of the URL. The next method, setupController() sets the resulting model as the ‘content’ property of the associated controller. (“AgentController”, again by convention)


Templates

Ember has deep integration with the Handlebars templating library, by Ember co-creater Yehuda Katz. Handlebars is a string-based templating library that supports conditionals and iterators. Ember some framework-specific semantics to its lexicon.

The canonical approach is to embed templates in your markup using <script> tags with a name attribute matching the template’s associated route. Using this approach it is largely possible to write Ember applications without writing View objects. However, since I’m using AMD and prefer to load my templates from separate files I’m creating View objects and specifying the compiled template as a property of the View:

Controller

Ember controllers present application state to templates. They are a representation of a model (or array of models) suitable for rendering by the template. Ember provides ObjectController and ArrayController “classes” for this purpose, which act as proxies to their underlying models.

Ember Data

The Ember Guides on the EmberJS website discuss Ember Data as the de facto persistence provider. From the website:


“It provides many of the facilities you’d find in server-side ORMs like ActiveRecord, but is designed specifically for the unique environment of JavaScript in the browser.”


However, Ember Data does not ship with Ember, it is available via its GitHub repository, which clearly states that it is alpha quality and not production ready. Also, in order the get an current version of Ember Data, you have to clone the repository and build it with Ruby. While this makes sense given the Rails heritage, it’s off-putting for non-Ruby developers.

Anyway, I installed Ruby and built Ember Data so I could do a little investigation. Once nice feature is the FixtureAdapter, which lets you use in-memory data structures (an array of objects) to develop against prior to building out a server persistence layer.

Ember Data has a lot of promise, but I feel the Ember website shouldn’t be promoting it as the de facto solution when it’s clearly not finished.

Pros

  • Good abstraction, lots of “nuts and bolts” operations are handled for you

  • If you follow Ember conventions, you’ll write less boilerplate code than with other tools in this sector

  • The newest version of Ember Router provides robust routing/state management

  • Automatic memory management: Ember automatically binds and unbinds event listeners for garbage collection

  • Global event delegation: event handlers are bound once to the application’s root element (typically the document) and events are delegated downwards for greater efficiency/smaller memory footprint

  • Batch DOM updates: Ember gathers potential DOM updates and periodically applies them in batch for better performance. DOM updates are expensive.
Cons

  • Ember is prescriptive. It’s a very opinionated framework, you have to build an application that fits the Ember architecture vs. building an architecture for your application

  • Difficult to debug: abstraction and “automagical” housekeeping comes at the cost of complexity. Errors can be very hard to track down, so much so that Yehuda Katz authored an Ember Inspector extension for Chrome to aid in debugging Ember apps

  • You write “Ember code” and not much normal JavaScript, which is a quirky language to begin with

  • Ember has an odd capitalization convention: capitalized properties are assumed to be global variables in Handlebars conditionals/iterations, etc. Not only does this not fit the JavaScript community convention (capitals for Constructors only) but it’s very problematic for persistence layers with capitalized fields (i.e, enterprise)

  • Documentation is still a work in progress, the guides are vague and inconsistent, making it hard to get up to speed

  • The community is nascent, mostly Ruby or Rails oriented, many plugins have to be built with Ruby

  • Nearing a 1.0 release, when hopefully the core will stabilize. Yehuda and Tom’s (admirable) approach has been to let the community drive development, but this comes as the cost of instability
Conclusion

  • Ember.js is a powerful framework, showing tremendous promise. There is much to admire here.

  • Ember is well-suited to Single Page Applications (SPAs) with longer user interactions, where memory management is a concern.

  • If you subscribe to the “Ember way” it provides good abstraction, reduces boilerplate code, and handles a lot fo plumbing for you.

  • with great power comes great responsibility… all this power comes at the cost of flexibility and ease of debugging.

  • There are some non-trivial concerns, especially the framework’s transitional state as it moves towards a 1.0 release
I think we will take a “wait and see” approach on Ember, as I think it’s still just a little too early… it’s not quite ready for prime time until a 1.0 release is stabilized and Ember Data moves to a 1.0 release and/or gets bundled with the core. Still, it’s hard not to admire Yehuda and Tom’s work here. This is a well thought out, robust approach to client side application development.

image

No comments:

Post a Comment