
Step by step from jQuery to Backbone - sebg
https://github.com/kjbekkelund/writings/blob/master/published/understanding-backbone.md
======
romaniv
I am familiar with two general approaches to creating unreadable and
unmanageable software.

The first one is to take logically unrelated operations and combine them into
one giant blob via shared/global variables and god objects/methods. This is
what commonly known as spaghetti code.

The second one it to take every piece of functionality and shatter it into
tiny pieces, so no unit of code represents anything anymore. This can be done
with endless callbacks or layers of abstraction, and it can be made worse by
complex frameworks with a lot of "magic" taking place or a lot of boilerplate
being required. I don't know any common name for this, but let's call it mush
coding.

It looks like the post describes how to convert moderately readable spaghetti
code into unreadable mush code. (I would claim that a person not familiar with
JQuery could easily understand the initial code, while a person not keenly
familiar with Backbone would be completely lost in the final version.)

If most of your methods are longer than 100 lines, something is probably
wrong. If most of your methods are shorter than 3 lines, something is probably
wrong as well.

~~~
nahname
Method length should be 1 to 3 lines. Longer and you are incurring technical
debt. The function name should be descriptive and it's description shouldn't
be,
'adds_one_to_a_number_unless_override_is_on_then_it_subtracts_four_except_when_global_is_set_then_it_jumps_into_a_switch'

~~~
berntb
>>Method length should be 1 to 3 lines.

I've read that claim. The only time I really had to work with code like that
was horrible.

It was like a book where the sentences were in random order, with the next
sentence number appended, so you would have to browse to another page every
few words. :-(

The context switches didn't make me productive... Sometimes, I had to look 3-4
levels up or down in the hierarchy to find a parameter type (this was in a
scripting language). If anyone talked to me, it took a looong time to rebuild
the model in my head.

Edit: In short, grandparent++.

~~~
taproot
Lasagne is starting to sound a lot like Spaghetti, I guess that's the point.

------
jcampbell1
Is it just me, or did reasonable jQuery get refactored into broken code? In
the jQuery code, the status is added after the sever acknowledges receipt. In
the backbone code, you are adding an element rendering it to the page, and
then the model is doing some automagic synchronization. Unless there is some
serious magic in the Backbone model, things can get completely out of sync.

This looks like one hell of a bastardization of MVC. It seems the view is
really a controller+view, and the model does the sync in a way that requires
coupling the view to the model to handle any sort of error.

Edit: I could be wrong here, but can someone show me how to fix the Backbone
code to handle an error correctly? Error handling can be added to the jQuery
code by adding 'error:function() { // do something simple },'

~~~
sophacles
There are a couple things you could do:

1) You can pass a {wait:True} as the second argument to collection.create(),
and the add event won't be fired until after a successful sync. If you want
error code, you add error:funciton(){..} to the create options hash.

2) You can change the event listened for from 'add', to 'sync', and still have
the error handling code in the options hash.

3) You can manually create the model, call save() and have the success
callback be code to add the model to the collection, and the error code do
something else.

In all of these, you'd just have to add a function to the view to indicate
error, and do what you want to handle it. (Depending on the specifics, this
could be for the NewStatusView or for the StatusesView..)

~~~
jcampbell1
My thoughts:

> 1) You can pass a {wait:True} as the second argument to collection.create(),
> and the add event won't be fired until after a successful sync. If you want
> error code, you add error:funciton(){..} to the create options hash.

This is problematic. Now you completely lose the "add" event, so if you wanted
to do something like add a spinner while the request is in flight, that is not
possible.

> 2) You can change the event listened for from 'add', to 'sync', and still
> have the error handling code in the options hash.

But now you are asking about the sync status from a collection. It doesn't
seem relevant to ask a collection about it's sync status when you are
interested in the status of a form submission.

> 3) You can manually create the model, call save() and have the success
> callback be code to add the model to the collection, and the error code do
> something else.

This seems to be the best option to me. It puts the success, error, and model
all in the same frame, which puts us in the same place as the original jQuery.

The jQuery code was far more elegant that the author would have you believe.
At the core, you are handling a user interaction which comes in units of a
"submission". The jquery code, wraps a "submit" into a singe activation frame
and handles it.

The backbone wraps this "submit" unit up, passes it through a collection, some
automated saving, and now you have no way to reason about what comes out the
other end. When you submit 5 times, and have 2 failures, what do you do? What
is a collection going to know?

I recognize the problem with the original jquery, but this ain't the right
solution.

~~~
sophacles
Look, I don't really care if you like backbone or not, but try to actually
object to it with facts, not projections based on word semantics. All of your
objections are made on incorrect assumptions of what information is provided,
and what actually happens.

1) the add event isn't lost. It just doesn't fire until a success. Want to add
a spinner, have it fire in the appropriate view as a response to the "submit
form" event.

2) That isn't how sync is defined, and sure there may be a better name for it,
but this isn't what it means. Lots of information is passed into the callback.
Useful information, stuff that contradicts your objections.

3) Not the same as JQuery - you can reason about what comes out the other end,
because the information is actually in the collection, with an api for getting
it. The events have a great set of arguments for them.

Muddling the conversation with such incorrect assertions (aka FUD) is counter-
productive.

------
AlexMcP
I think it's important to note that if this code never grows or changes, then
this refactor is totally unnecessary. It DOES add code, and it DOES almost
over-decompose the structure.

The payoff, however, is if more features or behaviors were in the pipeline
(and when aren't they?). This really sets you up to gracefully manage more
complexity by having sensical places to put more code, instead of writing a
few more $(document).ready callbacks to ship something on time.

Backbone.js might not be the right tool for the contrived example, but I've
come to expect a sacrifice of real-world applicability for smaller, digestible
chunks. That the synthesis is up to you is ok, I think.

------
sophacles
This is a nicely written post, and uses nice idioms for backbone development.

I would like to note though, that the justification for the increase in LOC
count feels a little weak. I understand and agree with it, however before I
really grokked what Backbone enabled I probably would have been a bit wary of
that - it really just looks like extra work.

I would suggest a follow up, that traces adding some functionality or widget
use through both the original code and the newly refactored code, to highlight
the power of backbone and make it clear. (I'm suggesting this from the
original author, because the post I just read was pretty well written and
seeing the same style in the in-depth guide would be pretty nice :) ).

------
scr4ve
I wonder why Backbone is getting so much attention. For small tasks, jQuery is
completely sufficient (as in this example as others have noted). If you're
going to develop applications on a larger scale, Dojo is a way better
alternative in most cases IMO. It comes with modularization, build tools, i18n
etc... Backbone is somewhere in the middle, neither highlevel nor lowlevel JS.
I really don't see a spot where Backbone significantly outperforms either Dojo
or jQuery. Can anyone tell me what's so special about it?

~~~
jashkenas
Since it gets asked so very frequently, I've tried to put together an answer
in the FAQ here: <http://backbonejs.org/#FAQ-why-backbone>

~~~
nlh
Thank you for the FAQ Jeremy - helpful to this Backbone newb.

I won't ask you directly for the answers to this since it wouldn't be polite
for you to answer (or would it?), but I feel like a lot of that FAQ is
specifically addressing different frameworks' way of doing things, which is
totally fine.

Would someone mind extrapolating a bit and let me know which frameworks /
features he's referring to in each point? I assume the 2-way data binding and
"nifty demos" piece is about Meteor and Derby, and the "stuffing application
logic into your HTML" refers to Knockout, but I'm a bit lost on the others.

Just trying to grow my awareness of the landscape....

~~~
ganarajpr
I am going to attempt to answer you :

Here are the list of points from the FAQ :

The focus is on supplying you with helpful methods to manipulate and query
your data, not on HTML widgets ( __angular __) or reinventing the JavaScript
object model ( __Ember __).

Backbone does not force you to use a single template engine ( __Ember __).
Views can bind to HTML constructed in your favorite way.

It's smaller. There's fewer kilobytes for your browser or phone to download,
and less conceptual surface area. You can read and understand the source in an
afternoon ( __Ember and Angular __).

It doesn't depend on stuffing application logic into your HTML ( __angular /
knockout __). There's no embedded JavaScript, template logic, or binding
hookup code in data- or ng- attributes, and no need to invent your own HTML
tags ( __angular __).

Synchronous events are used as the fundamental building block, not a
difficult-to-reason-about run loop ( __Ember __), or by constantly polling and
traversing your data structures to hunt for changes ( __Angular __). And if
you want a specific event to be aynchronous and aggregated, no problem.

Backbone scales well, from embedded widgets to massive apps.

Backbone is a library, not a framework, and plays well with others. You can
embed Backbone widgets in Dojo apps without trouble, or use Backbone models as
the data backing for D3 visualizations (to pick two entirely random examples).

"Two way data-binding" is avoided. While it certainly makes for a nifty demo (
__Angular & Knockout __), and works for the most basic CRUD, it doesn't tend
to be terribly useful in your real-world app. Sometimes you want to update on
every keypress, sometimes on blur, sometimes when the panel is closed, and
sometimes when the "save" button is clicked. In almost all cases, simply
serializing the form to JSON is faster and easier. All that aside, if your
heart is set, go for it.

There's no built-in performance penalty for choosing to structure your code
with Backbone. And if you do want to optimize further, thin models and
templates with flexible granularity make it easy squeeze every last drop of
potential performance out of, say, IE8.

I have marked the individual points he pointed out with the relevant MVC
framework out there.. I might have missed out on some but it looks like (
atleast to me! ), jashkenas feels the greatest threat to Backbone currently is
Angular.. And I think he is right about it.. Backbone is currently ruling the
throne of Front End MVC frameworks, but it looks like its rule is ending
soonish...

------
andreypopp
I'm kinda scared that it turns out there's twice as much code in the final
result. I understand, that this example is just for educational purposes but,
I think, the conclusion that it's better to leave this jQuery-based piece code
"as-is" is much more educational.

~~~
aidos
I think it's more about showing people how this stuff works at a digestible
level.

I'm currently reworking something in Angular (I was only part way into the
build). It took me a couple of days to get up and running but now I'm there
it's paying itself off. The code is far more modular, easier to understand and
I'm turning it out way faster.

Toy examples will always just be that, but they're needed in order to learn.

------
danso
Great work...it calls to mind a longform guide that Sam Clay wrote in
converting NewsBlur's spaghetti code to Backbone:

[http://www.ofbrooklyn.com/2012/11/13/backbonification-
migrat...](http://www.ofbrooklyn.com/2012/11/13/backbonification-migrating-
javascript-to-backbone/)

------
kjbekkelund
If you have any questions regarding the blog post, just let me know :)

~~~
Jare
I have one: clearInput(), which clears the textarea, is tied directly to the
addition of a new status, not to the submission of a new status via that
textarea. Any other piece of the app that adds a new status (from other users,
from automated systems, whatever) would clear what I'm typing. I can't imagine
why you'd do that.

~~~
kjbekkelund
Haha, of course. I guess it was just a moments blackout — I was probably just
too focused on making Backbone easily understandable. There might be some
strangeness in there, but hopefully most readers have a better understanding
of Backbone after reading it. And I don't have time to change it now either
way.

------
lifeisstillgood
Brilliant - as someone who has recently taken the same steps (and into
Marionette) there is a lot of half way info out there and not nearly enough
complete tutorials.

I am writing one myself - so would be interested to hear the good and bad
points of this as much as the OP

------
hayksaakian
I was nodding my head until about half way through.

Thinking that I could apply this logic to client side storage was fine until
he proposed that persistance would be automatically handled by Backbone's
ajax.

At that point, backbone gives you less flexibility for more code. No thanks.

------
BillGoates
Separating DOM and data I can understand, but I am not convinced Backbone is
the right way to do it.

My code would look more like:

    
    
        function postdata(url, data, callback) {
            $.ajax({
                url: '/status',
                type: 'POST',
                dataType: 'json',
                data: data,
                success: function (received) { callback(received); }
            });
        }
    
    
        var statusform;
    
        (function(pub) {
            var status = ""
    
            pub.init = init;
            function init() {
                $('#new-status form').submit(function(e) {
                    submitdata(); 
                    e.preventDefault(); 
                });
            }
    
            function submitdata() {
                var data = {
                    text: getfieldvalue("textarea")
                };
    
                if (!data.text) { return; }
                postdata("/status", data, function(received) {
                    status = received.status;
                    drawscreen();
                });
            }
    
            function getfieldvalue(fieldname) {
                return $('#new-status').find(fieldname).val();
            }
    
            function drawscreen() {
                if (status) {
                    $('#statuses').append('<li>' + status + '</li>');
                    $('#new-status').find('textarea').val('');
                    status = "";
                }
            }
        }) (statusform);
    
    
        $(document).onload(statusform.init);
    
    

Note 1: This code sample is untested, but should give a good enough idea what
I am trying to do. Note 2: For extra type safety, use typescript interfaces to
model data.

~~~
gknoy
Apologies for off-topic, but how does one post code, or do quoted text on HN?
I've seen it done here and a few other places, but haven't been able to find
documentation on how.

~~~
cristoperb
"Text after a blank line that is indented by two or more spaces is reproduced
verbatim. (This is intended for code.)"

<http://news.ycombinator.com/formatdoc>

------
pacomerh
I really like the approach of translating from jQuery. Even if you don't end
up using Backbone for everything, it really gives you an idea of what to do
with it. I read Backbone tutorials before, and you learn how to do things, but
with not much language context. Looking at the alternative ways to do one
thing is way more useful.

~~~
taproot
Agreed, I really enjoyed working through this, haven't come across anything
giving the the same level of context to, not only the why, but the how you got
there side of things as well.

I wonder if the author would be interested in writing up something about unit
tests / tdd in the same sort of fashion.

------
freethejazz
I remember seeing this last July or August, but I lost it. So glad it
resurfaced!

------
jpb0104
More great Backbone information: <http://addyosmani.github.com/backbone-
fundamentals/>

------
jonny_eh
Why do I get the feeling this could have been done much more easily with
angular.js?

~~~
henkap
I want to see a similar post for angular!

------
rdcapasso
This is just fantastically put together. Thank you for doing this.

