Backbone vs Knockout
lostechies.com
lostechies.com
I'd tend to think that attempts to glom together Backbone.js and Knockout.js will produce something less than the sum of their parts.
Here's Knockout's documentation: http://knockoutjs.com/documentation/introduction.html
Most of Knockout's API deals with binding JavaScript objects to web forms. If all of your web app's UI is essentially a series of web forms, then great! You're all set. The Knockout examples demonstrate this ability: http://knockoutjs.com/examples/
However, if your UI starts to move in interesting directions beyond filling out a series of forms, then Knockout doesn't have much to offer you (see LargeWu's comments on this page).
On the other hand, Backbone's philosophy is that your UI is your business -- jQuery is already great at extracting data from forms and other elements in the DOM, and there are already a large number of wonderful templating libraries for rendering HTML from JS objects. Instead, it focuses on helping you model your data in the browser: providing events you can observe whenever a model changes state, adding essential functions like "map", "filter", "find", "groupBy" and "any" to collections of models, giving you simpler declarative bindings for DOM events in your views, so that you don't have to worry about whether a particular piece of HTML is visible on screen or not, and so on...
But really, the best proof of "UI wizardry" is in the pudding. If you haven't scrolled through it recently, I encourage you to check out some of the amazing apps built with Backbone over the past year: http://backbonejs.org/#examples
(with all due apologies for boosterism)
as for the wizardry - it's jquery (or zepto or something else), not backbone that does this. while backbone integrates with and uses jquery heavily in the views, i don't think it's a fair claim to say backbone creates facilitates those user experiences. it helps us organize our code effectively so that we can create those user experiences in a well structured manner.
and come on, Jeremy... you know how much I love backbone! it's 80% of what I blog about these days! :)
Can you list the names of some of these, out of curiosity? I'm building some new stuff and it seems like this is the way to go, but all the ones I've seen have been way too heavyweight.
On the other hand, if you're looking to share templates between the client-side and server-side, and you're not using JavaScript on the server end, there's a strong case to be made for "logic-less" templates that can be rendered (at least in theory), by Ruby or Python just as easily as JavaScript. Check out Mustache: http://mustache.github.com/
There's also HAML, Jade, Eco, Handlebars, and many, many more.
You can find it at http://github.com/juggy/backrub
It gives almost the same functionalities of knockout.
You can't say "we're talking about the style in which you think", and then say "the UI is your business", and then be disheartened when developers handle the UI with a library like knockout.js.
I write apps to provide a user experience and backbone only provides a conceptual model for a portion of this (specifically the model, collection / syncing). Its extremely clean and elegant.
However, backbone does not provide an elegant conceptual model for the UI/DOM. Using declarative bindings and JS generated templates is just fine from a coding point of view (I've built a few apps this way), but frankly its not a very powerful mental model - nor is it necessary consistent with the design patterns in backbone that make it shine.
I'll tell you the conceptual model of using a view model to control html templates is more empowering. I don't like the syntax and a lot of things about Knockout - however to me knockout is a nice abstraction on top of jquery event bindings, much like Backbone.sync is a nice abstraction on top of $.ajax.
1. A conceptual model that describes the input / output between DOM and user.
2. More explicit enumerations of event bindings
3. Explicit link between user interactions/events and constrained DOM manipulation
- to match conceptual model.
4. Defining all viewable elements in HTML templates
5. Round-trip syncing between HTML and data models
Let me know if you think inputs are interesting or would want any more detail around concepts.- It's lightweight. I am a bit obsessed with client-side optimization, so that's a plus in my eyes.
- I am not a big fan of binding via html attributes. Yes, there is a way to do that script-only way in Knockout too, but it was neither fun nor appeared very clean.
- Backbone allows to use either jQuery or Zepto as DOM manipulation library.
- Backbone is template engine agnostic. The situation with templating in KO seemed a bit muddy to me.
- Backbone has routing built-in. With KO I'd have to use something like Crossroads.js thus adding even more weight.
In short you may need to write a bit more code in backbone to get the same that you can have with almost no code in KO, but on the other hand Backbone feels much more flexible and less restricting.
YMMV.
I was casting around for a simple way to implement a responsive UI in our latest application and Knockout appeared to be a good option (I'd not come across Backbone at that point).
Now it just feels like more work... I have written so many custom bindings it is unreal!
(I realise this is, as the author notes, mostly my failing in writing JS :))
I actually find writing custom bindings pretty enjoyable. That's where the nice separation and reusability come from.
Yes, I have a lot of custom bindings, but most are very reusable, and many have saved my butt (like wrapping bindings to include JQM's markup enhancements).
That said, I wasn't new to MVVM when I first came across Knockoutjs, so I used it efficiently from the get-go.
If you don't like MVVM, you won't like Knockoutjs.
I'd say that Knockout can be suitable for large applications, but that you need to handle having an unusual computational model pervade your code. If you're interacting with existing code, it can be tricky to get inputs and outputs mapped correctly, but the knockback library mentioned in the article probably solves that for backbone users.
One rule of thumb that might be useful is that any (non-event-handler) function you give to Knockout must handle being called an arbitrary number of times at arbitrary times, with some inputs being potentially outdated. If it cannot, you're not using the computational model the library essentially requires.
My major issue with Knockout.js is testability. It does not come out of the box with a very elegant way to trace your chained dependencies, or put meaningful automated tests in place using Jasmine or equivalent. I think this is mostly a function of the mindset of the community. This is problematic when your app gets complex - you waste countless hours chasing around silent failures or meaningless stack traces.
The Knockout.js community itself is a little funny - some people really know their stuff, but majority seem to want to take code off the shelf and hack up quick prototypes (which I think is a good use of knockout). However, the thing that is really impressive is that the community can communicate back and forth using JS fiddle. No long pasted stack traced or error codes need to be discussed - just paste a link to the JS fiddle of your app code and others can respond with their own JS fiddle. It really is an evolved form of communication for discussing code.
Lastly, I had not seen this before - https://github.com/kmalakoff/knockback - I think this is a great idea. First thing I picked up knockout.js I integrated the backbone model / collection. It just seems like the proper use of the 2 libraries. Knockout.js syncs with DOM off the shelf, Backbone syncs with the DB quite nicely. Glue them together with a clean app architecture and you have an elegant way to sync your DOM with the DB. I think this is the next generation of these apps - full sync from DOM to DB perhaps with a persistent store and data validation in the client.
For the record, Knockout handles way more than just forms. The statement that Knockout doesn't offer much beyond forms is simply false.
After writing code using both, on my next app I will use all of them: - Backbone for application structure and the client-side model layer functionality. Backbone is good at this. - Knockout to make handling user-triggered events a breeze, keep data in sync across views and layouts automatically, and to keep my markup and JS code tidy and separate with client-side templating. Knockout is good at this. - jQuery to interface with "low-level" constructs such as DOM elements. jQuery is good at this. In this set up, Backbone is the framework, Knockout is just another library being used, and jQuery is just another library being used. :-)
Update: Click the 'text only' link to avoid page loading forever.
Update: Click the 'text only' link to avoid page loading forever.
This should be google cache's default mode.It can absolutely make sense to have two models for two very different interactions with the same data - UI and REST server calls. Anyone who's written a substantial Silverlight or WPF app already has done this.
Or am I totally crazy? I intend to use both in my latest project, and I'll see how it goes.
"Many developers now include a client MVC framework like Backbone to better structure client code. A few have started to use declarative model-view binding libraries, such as Knockout and Angular, to reduce boilerplate DOM manipulation and event bindings. These are great concepts, and adding some structure certainly improves client code. However, they still lead to duplicating rendering code and manually synchronizing changes in increasingly complex server and client code bases. Not only that, each of these components must be manually wired together and packaged for the client."
The reason we started working on Derby, is that none of these frameworks offer a full-stack solution. Backbone and SproutCore will provide better structure and some automation of client-server data syncing. However, they still require manually creating appropriate server routes that handle AJAX requests and communicate with a database. They may provide client-side routing, but these routes are totally different from the server routes, so if you want to use the same URLs, you have to duplicate routing code. SproutCore uses Handlebars, so you might be able to render the same templates on the server for faster page rendering, and non-JavaScript browser or search engine crawler accessibility. However, this will require writing a bunch of custom server code to pull out the right data and render the templates. In addition, none of these frameworks provide tools to deal with data conflicts. Conflicts are inevitable in a multiple users realtime application, especially when supporting offline.
Derby's focus is to unify as much code between server and client and to provide automatic realtime syncing among all models and views. This approach requires less code, delivers faster load times, provides instant client-side rendering from full pages to individual data bindings, and supports offline by default. It's a work in progress, but let us know what you think about it so far.
The Knockout authors are great about updates - new releases this week, and the Knockout Model author just merged our feature request.
If you're interested in these, our team's searching for a JavaScript senior developer to work on both these - see http://handl.it
It also highlights two projects combining them:
http://notes.dylanized.com/knockoutjs-demo-kit-now-on-github
That said, the comments here are right. Knockout is good for scenarios where a dynamic UI is needed. For a more data intensive app, Backbone is usually a better choice, but at a cost.
Excited to see what happens with Knockback....
backbone and knockout focus on two different problem spaces: app architecture (backbone) and UI wizardry (knockout).
there are several plugins for backbone that bring model binding and other user experience enhancements to it, though. plus, backbone integrates directly with jQuery, so you have access to all of jQuery's libraries and plugins, still.
> I think the binding of data to HTML elements is a perfect fit and natural extension of HTML.
Have you checked out http://agilityjs.com ? I tried to create a pretty simple abstraction for data-element binding.
The lib is being used in production at opdots.com, and could use some additional contributors :)
In light of this article, what is a good application structure to use on the client if we do decide to go with Knockout?
If you're going to use Knockout to provide wiz-bang editing and binding on single page (as opposed to a slew of jQuery code everywhere), then you might not need much more than Knockout.
If you're going to be creating multi-page JavaScript applications within a single page of your site, you should look at combining something like Backbone.js with Knockout, using the Knockback library I linked to in that article.
Alternatively, if your looking for good structure for JavaScript applications in general, I have another post that introduces a few of the concepts and links to some great resources, here: http://derickbailey.lostechies.com (unfortunately, I can't get the exact URL at the moment... site seems to be slow / not responding. just look for the "Intro to composite JavaScript apps" post)
There are several way to structure your app, but it depends on what your app does and how structured it is. On a basic level I structure every page to have a page object to handle events and setup the view model(s).
So, for default.aspx, I might have something like:
var Page = new function(){ _this = this;
$(function(){
//document ready
});
$("#dataTable").delegate(".delete",function(){
_this.viewModel.deleteItem(ko.dataFor(this));
});
this.viewModel = new function(){
var _this = this;
//set up view model
this.observableVal = ko.observable("");
this.deleteItem = function(){
//delete item from VM
};
};
};But then you might want to have a page with multiple view models (ie UserControls that are self contained). This gets a bit tricky, especially if you want the multiple view models to interact.
Shoot me an email if you need help.
Best practices - I stick to simple rule of using Views (in backbone) and view models (in knockout) to interact with dom, then using models in both frameworks to sync w/ DB. This keeps code fairly clean, and use of other components of framework relatively straightforward.
My experience in Backbone was that things are a bit too tightly coupled. 'Controllers' (which are called views) are mapped to templates (the actual views). Views have a Model reference directly in the view. Again, for small apps this works great and enables data-binding by tying model changes to view updates (render).
For large apps, in regards to maintainability, I think you really need the C in MVC to stand for Command. Any type of undo/redo needs the command pattern. Commands are great as well as you can throw them away or add them without affecting the rest of your application.
I also wanted a system wide messaging system, or events that can be dispatched and received by any actor in the framework (rather than bound directly between actors).
In the end I rolled my own MVC framework based on traits.js (and borrows from Backbone, Spine, and some Flex frameworks), it's far from complete (no remote persistance yet) but it solved some of the issues I had with current JS MVC frameworks.
var vent = _.extend({}, Backbone.Events);
done.
see also http://lostechies.com/derickbailey/2011/07/19/references-rou... for more info on using it, and http://lostechies.com/derickbailey/2011/11/17/introduction-t... for more info on creating larger apps w/ backbone