
Backbone has made me a better programmer - appleton
http://floatleft.com/notebook/backbone-has-made-me-a-better-programmer
======
jpk
Backbone is one of those libraries/frameworks/whatever that avoids magic. It's
just a pile of reusable parts that make building big javascript applications
easier. One can't say the same about, say, Rails. There's a lot of magic in
Rails.

Not that magic is a bad thing. Magic is what makes Rails good at what it's
good at. The downside, though, is that magic-ful frameworks often obscure
language mechanics that an inexperienced user of the language would do well to
understand. Thus, Rails is awesome for a programmer who's already good at
Ruby, but super frustrating for someone learning Ruby.

On the other hand, Backbone makes idiomatic use of javascript and lays it on
the table in a magic-less way. So not only does a new javascript programmer
not have to deal with confounding magic, they can also learn from how Backbone
uses javascript, and apply that knowledge outside the scope of the library.

I'd never thought of it this way, but I think this is probably one of the most
important distinctions between opinionated, magic-y frameworks, and things
like Backbone.

~~~
knowtheory
The thing I've enjoyed most about Backbone, is that it's given me a sane
conceptual point for learning browser APIs, and libs.

Using Backbone in no way obviates the need to learn about how browsers work in
the end, but it does make it a hell of a lot less painful for you to engage in
that process.

also +1 for literate code as a mechanism for learning more about what
Backbone's responsibilities and defaults are.

------
jb55
When we started using Backbone it was good for awhile until there was so much
code duplication all over the place. We decided to build a small declarative
API on top of backbone that allows us to easily compose views by mixing in
common functionality. It looks something like this:

    
    
        AlbumsView =
         bQuery.view()
          .set("el", "#albums-view")
          .init((opts={})->
            @readOnly = opts.readOnly or no
            @app = opts.app
          )
          .use(Mixins.bq.init('albums'))
          .use(Mixins.bq.collection
            tag: "#album-list"
            createView: (m) ->
              AlbumView = Views.AlbumView(readOnly: @readOnly)
              new AlbumView { model: m, app: @app }
          )
          .use(Mixins.bq.filterable
            pred: (album, ftext) -> album.get('title').indexOf(ftext) is 0
            filterTag: "#filter"
            collectionTag: "#album-list"
          )
          .on("click #addNew", ->
            @collection.create
              title: "New Album"
              type: "Album"
          )
          .make()
    

For example, the Mixins.bq.collection plugin abstracts away the common task of
adding and removing subviews when new things are added the collection. The
filterable plugin abstracts away the common task of filtering collections. Our
custom init plugin sets up all the events common to all of our views. In the
end make() just returns a BackboneView with all the events set up properly. It
has saved us so much time we figure people may actually want to use this as
well, we just have to write the documentation and some plugins now :)

<https://github.com/jb55/bquery>

~~~
jarek-foksa
What's the point of this excessive chaining? I use CoffeeScript a lot, but
your code looks unreadable to me.

~~~
eranation
I think code verbosity (which anyone can read and understand) is highly
underestimated these days. I don't think writing less lines of code is any
good if you need to explain to people what you did (yes, even smart people
sometimes don't figure it out right away if they didn't use a similar library
/ concept before, and you don't always have smart people reading your code
anyway, we all know that)

If you optimize your code to avoid any duplication, you are probably wasting
more time writing / extending libraries, doing pull requests than getting
working software done.

Refactoring, and good design is critical, helpful, almost mandatory, but if
your feature is not out there on time because you over refactored / engineered
your code, and some other startup get's it out there faster, no user will
care.

users don't do view source before they pay you.

------
hasenj
I didn't really like backbone at all. It was a pain. It didn't offer anything
to help you build complex UI.

I had to use backbone to build a mildly complicated UI - not so complex, mind
you, just something that's supposed to be somewhat interactive.

Backbone was no help at all. Its "views" don't really offer anything.

Just about 2 weeks ago I discovered knockout.js, and I felt stupid for
spending days building something that would probably take an afternoon to do
with knockout.js.

Then, a week later I discovered angular.js and felt even more stupid.

Now I _really_ dislike backbone.js

~~~
eggsby
I've built moderately sized applications in both angular.js and backbone,
backbone is much more pleasant to work with if only for the fact that
everything is _obvious_ , even if that requires you to do more development
legwork and thinking about your application structure. (this is a feature, not
a bug)

Angular.js data bindings are great and things like ng-repeat are neat until
you start to step outside of the bounds of the angular garden.

Want to fetch data yourself and not use the angular resource plugin? (The
resource plugin restricts the shape of data you can return from your server,
i.e. every resource.get() request must only return a single object, if you
want to receive an array you need to use .query() ). If you want to use jQuery
for ajax, for instance, you lose all data bindings because vanilla javascript
doesn't have the angular secret sauce! edit: angular provides utilities to
alleviate this issue, addressed in comment below.

Well that's fine maybe there's an event somewhere you can hook into and
trigger off of, right? Try to find this in the docs, I dare you! If this
doesn't demonstrate the incidental complexity caused by using a tool like
angular, consider the documentation for backbone and angular, or either
projects source for that matter. You can read backbone's source in an
afternoon, I couldn't say the same for angular (or ember, or knockout).
Because of this I can be confident backbone is largely bug free, I absolutely
can't say the same about larger projects like angular.

Angular.js is meant to have a low barrier of entry, but because of this the
developer interface is a thin facade on top of astonishingly complex
internals. Contrast this to backbone which provides a simple and solid base
for your application, providing freedom and foundation rather than a cookie
cutter solution.

When I consider the trade-offs between client-side tools for structuring
applications backbone consistently comes out on top.

~~~
kenster07
"If you want to use jQuery for ajax, for instance, you lose all data bindings
because vanilla javascript doesn't have the angular secret sauce!"

Data bindings should work as normal...if you're running into issues, try using
$scope.$apply().

Angular uses jQuery, internally, so there are events you can hook into --
jQuery events.

And comparing the complexity of Angular and Backbone's internals is a bit
misguided. They aren't meant to solve the same problems. Angular is complete
Javascript application framework, and Backbone isn't. To use a non-foolproof
analogy, if Angular were Rails, Backbone is Sinatra.

~~~
eggsby
I wasn't aware of $scope.$apply, should help simplify some of my angular
stuff. Thank you :)

~~~
kenster07
You're welcome. :)

------
jpallen
Unit testing will also force to decouple your code in a similar way. In the
first example it is impossible test individually test all the things the code
should do without worrying about everything else that is going on (e.g. you
need make sure all the elements exist on the page). By moving to an event
trigger like you suggest, you can then test that each listener does the
correct thing independently of the others. You can have a separate test for
'selector' and 'yet-another-selector' and they don't need to know about each
other. As an added benefit you don't need to mock out your ajax call either.
Instead you can just fire a "DataModel:update" event in the unit test.

I've only recently grokked this aspect of unit testing and I feel like it's
made my code an order of magnitude better and more maintainable. Thinking
first about how to write code in a decoupled manner also makes unit testing
really easy. After having tried unsuccessfully for years to test my code it
was a revelation when I that it was because my code was bad that it was hard
to test, not that testing is itself hard.

Edit: I've tried to illustrate my thoughts more clearly with a copy-cat post
to show the parallels between the two:
<http://news.ycombinator.com/item?id=4427842>

~~~
mmcnickle
I've been using TDD for server-side code for some time now, but I struggled
with it for javascript; I thought unit testing javascript was a myth. It was
only when I started using backbone that I realised that I was writing
horrible, terrible code.

------
mattmanser
OT: I keep trying to get into backbone but I just get driven crazy by `get`
and `set`. Inspecting your object feels like a world of pain, which is no fun
when I'm playing with code. And it also makes it feel like you're not
programming js any more. Quite a few years back an old company I used to work
for had a similar framework and perhaps it's just latent hatred for that
rather annoying framework.

I know it's a limitation of the present js because you can't make getters and
setters, but it just completely kills my enthusiasm for backbone, which
otherwise seems great. Are there any alternatives out there using
Object.defineProperty instead? I know it's still not really web ready, but
it'd be far more fun to play with.

~~~
jashkenas

        > perhaps it's just latent hatred for that rather annoying framework
    

... hopefully ;)

The reason why you need `set` is so that you know when to trigger `change`
events. Getters and setters aren't going to fly if you need to support
Internet Explorer. One alternative is the Angular.js tradeoff, where you're
setting regular properties on vanilla objects and arrays ... but then Angular
is going in behind the scenes and traversing all your objects and computing
the diffs for you, every time a change might occur.

... in the end, you start to appreciate the transparency of avoiding getters
and setters in JavaScript. It's a very _nice_ thing that whenever I write
`obj.a = b` -- I can _know_ that that operation has no side effects, and won't
trigger any outside-of-the-box behavior. Conversely, whenever I write
`model.set('owner', 'Moe')`, it's nice to know that _this_ is the point at
which the rest of the app will react to that change.

~~~
whalesalad
Thanks for this short and logical answer.

------
xyzzyb
I actually prefer the second (complicated) example: everything that happens on
the success of the call is right there. If it were to grow more complicated
than that I'd move it to its own function and perhaps break it into a few
functions: not into several objects.

I find firing events to be useful when I'm writing code that's not meant to be
directly accessed, e.g. a jQuery plugin.

~~~
asolove
So you have some change, either an xhr or a dom event. You want it to trigger
a bunch of other changes somewhere else.

One approach is to call functions (or call functions that call functions...)
that directly make that change. This method is fairly clear to read but it
becomes messy when more logic gets involved.

The Backbone approach is actually similar to writing a really good jQuery
plugin. When the change happens, you convert the raw xhr or dom event into a
custom event that is in the language of your domain model. Then anyone who
wants can do what they want with it: views can update themselves, other models
can update their data and check it with validations, throwing other events, so
that changes propagate naturally through the system.

If you aren't familiar with Backbone or MVC this code initially appears to be
spaghetti: why does this one event result in functions all over being called,
seemingly randomly, even though they're never called directly?

But after a bit of practice, you get used to the pattern. And I find it an
excellent way of structuring large front-end applications with lots of
reusable behavior.

My mental model of such applications is a directed graph connected by events.
Each object has a set of events it is interested in and listening to, and a
set of events it is responsible for and firing.

~~~
xyzzyb
Oh for sure. As soon as my code will be touching multiple, disparate parts of
an application I'll look to events. But I'm be wary of code that uses events
for everything.

------
jongold
Totally agree with this post - I was a 'JavaScript =~ jQuery' guy before I
picked up Backbone - writing hopelessly average jQuery spaghetti (with the
best of intentions - I'm a designer and had never looked at JS as a
programming language.

Backbone has totally changed all of that - learnt so much about design
patterns in such a short space of time - shout out to Addy Osmani for writing
such down-to-earth, approachable content.

~~~
kenkam
I also agree, although instead of Backbone I recently found that Twitter
Bootstrap's javascript files offer similar insights as to how to structure
code in an javascript-style object oriented manner. For example:
[https://github.com/twitter/bootstrap/blob/master/js/bootstra...](https://github.com/twitter/bootstrap/blob/master/js/bootstrap-
typeahead.js)

~~~
jarek-foksa

      matcher: function (item) {
        return ~item.toLowerCase().indexOf(this.query.toLowerCase())
      }
    

Why there is "~" bitwise operator used in this method?

~~~
voyou
indexOf returns -1 if the query isn't found in the string; -1 is usually
represented as all bits 1, so a bitwise not on -1 is 0, which when converted
to a Boolean is false. So ~x is more-or-less equivalent to x != -1; but its a
bit obscure, and seems like bad style to me (indeed, I'm not even sure if the
ECMAScript standard guarantees that -1 is stored as all bits 1, so it may not
even by correct).

~~~
ahoge
Numbers are IEEE 754 floating point. It's a separate standard which they just
had to reference.

I do agree that it's bad style, because it doesn't clearly communicate the
intention. If you want something that returns true or false, you should return
true or false.

~~~
voyou
Yeah, but -1 isn't represented in IEEE 754 floating point as all bits one, is
it? The ECMAScript standard specifies that the bitwise operators work by first
converting their arguments to 32-bit signed integers, but at least how I read
it, it doesn't actually say anything about how these 32-bit signed integers
are represented (which implies that they continue to be represented as IEEE
754, which isn't how browsers behave, and wouldn't be very useful).

~~~
deafbybeheading
It's not. And you're right, the spec isn't clear. On the other hand, the
current behavior of pretending the bits are arranged in 32-bit
two's-complement fashion for appropriate integer values when applying bitwise
operators is really the only sensible interpretation (especially since a
64-bit float can represent all 32-bit ints).

------
jparishy
I'm really glad that Backbone has helped you become a better programmer;
that's great!

But it's worth nothing that this is really a trickle down effect from the
creators and maintainers of Backbone making use of great design patterns and
using effective programming practices. We should all strive to learn from
great code in many languages using the design patterns and practices of many
libraries :)

*edit: typo

------
robinduckett
Backbone didn't make me a better programmer, dealing with it's bullshit has.

------
davidw
I think a real example might be better. I did not find the 4 lines of code
difficult to read.

------
Kototama
I'm also enjoying backbone.js since a few weeks and it helps me write new code
without too many callbacks and keep a clean separation between the UI and the
data.

I also pushed some Emacs Yasnippets templates for backbone.js today, feel free
to contribute:

<https://github.com/kototama/backbone-underscore-snippets>

------
suyash
Backbone has only given you the tools to make your code better, you have made
yourself whatever you are.

------
novaleaf
i think it's nice to see some javascript design patterns!

~~~
franze
i think design patterns are either

    
    
      A) a lack of necessary abstraction - or -
      B) a sign of unnecessary complexity

~~~
lmm
This. I remember reading a definition of a design pattern as "a structured way
of working around a language deficiency".

~~~
mattgreenrocks
Powerful languages don't force you to decouple your code. Disciplined use of
patterns can help.

But all our minds are warped from thinking web programming has to be different
somehow from the desktop programming of old, and that concepts like SRP, LoD,
and coupling don't matter.

------
sekou
I'm making my way through Jeffery Way's fantastic jQuery series. This looks
similar to a Publish/Subscribe concept, also jQuery deferreds are apparently
another good way to avoid putting too much code into a success callback.

------
Kiro
Am I the only one who still makes websites with very little JS in them? One
jQuery thing here and there. Using Backbone would be overkill and to be honest
I can't think of one hypothetical project where I would need it.

~~~
powatom
A lot of JS tends to be required when you're building a big, dynamic web
application, or your website needs lots of modules and lovely little widgets.
If you can avoid writing a lot of JS, then that's great - but HTML / CSS alone
can't provide the features that a lot of users are expecting.

------
Void_
Don't thank Backbone. It merely uses some of patterns that desktop
applications have been using for years.

If you really want to be a better programmer, I suggest you learn Cocoa, or
other well written desktop framework.

------
rjzzleep
when I realized that in the end backbone is just javascript and suffers from
the same inheritence problems due to its crappy prototype object model.

And you manually have to deal with event disposal when destroying views in
backbone. just google backbone ghost views, I realized maybe it wasn't the
best thing for the job after all.

edit: the top comment mentions mixins, good stuff
<https://github.com/jb55/bquery>

but personally i can't wait until we get a proper replacement for javascript,
like dart maybe.

------
seivan
May I suggest Batman.js :)

------
powatom
TL;DR - This was originally a reply to another commenter. There seems to be a
lot of people accusing Backbone of failing to provide things that it has never
claimed to provide. This is a bit of a rant so apologies in advance! Obviously
YMMV but I've been batting these criticisms of Backbone away left, right, and
center recently.

To summarise: If you need a framework, then Backbone is not what you're
looking for. Use something else, because in all likelihood Backbone will not
give you the tools you're looking for. Backbone solves a different problem.

====

The only real 'major' problem with Backbone.js is that people for some reason
think it's a framework. It is not, and as far as I'm aware it has never
claimed, or attempted, to be one.

The real, underlying problems that Backbone attempts to solve are the
following:

1: Unstructured, spaghetti JS code.

2: Complicated DOM traversal / outrageously convoluted jQuery selectors.

3: Total lack of templating.

4: Generally crap organisation of your application.

Customers / users are constantly requesting more dynamic pages. You know that
form which adds a new item to the Foo list? Why does it have to refresh the
entire page? Why can't I drag and drop stuff like I can with every other
application I use on my computer?

Customers are realising that they CAN do cool stuff in their browser now, and
you better believe you're going to get a call asking you to turn a previously
read-only site into a fully dynamic web app. So you do what every other dev
does and rewrite the whole thing from scratch using a proper framework and
it's all nicely designed and fully specced out. Or not. What actually happens
is your customer doesn't have enough money for a re-write. They want all the
existing features, but they want the development phased. Your boss / colleague
/ dog wouldn't let you re-write the damn thing anyway because they assume that
it's just a case of cut + paste from another application somebody who no
longer works there wrote 10 years ago. So you do it step by step. You do it
page by page / feature by feature. That page which displayed a list of items
now displays new items automatically, you don't need to refresh the page!
Adding a new item is a simple AJAX call back to the server. Notifications?
Done!

And then a bug is found. Suddenly you realise you have no real way of
isolating your model from the DOM. You're hiding data in hidden input fields
so you can retrieve it via jQuery later and do something with it - maybe some
AJAX request to the server. It takes you a day to fix a bug that should only
take 5 minutes. It takes you a month to add a new feature that should only
take a few days.

It seems like only in web development do developers have this (when you think
about it) really, truly, WEIRD approach to building applications. We let the
data provider build our user interface. We don't bother with models - just
hide data in the DOM and get it back when a user clicks a button. Need to
represent the same data in two different ways? Build a new View in your rails
app and add a ton of logic to change how it looks based on the model's data.
Why do we have an MVC framework server side and then forget all about it on
the client-side?

When you think about a web application PROPERLY, the insanity becomes obvious.
In what other development domain do we allow the data provider (the server) to
render the user interface? Why do we discard models and proper encapsulation?
Why do we weave logic into views which should really live in a model /
controller? What the hell have we been doing to ourselves?

A lot of web app developers think they're building the following:

    
    
      Server (Model / Controllers) - GIMME DEM HTMLZ -> Browser(View)
    

What they SHOULD be thinking about building is:

    
    
      Server (Data Provider / API) <-- DATA TRANSPORT --> Client (Model / View / Controller)
    

The fact that you're using HTML and JS to develop an application is merely
incidental. Your server provides you with some data - it's insanity to also
let it define what that data should look like when it arrives client-side.

Backbone.js aims to solve THESE problems. It is not an application framework.
It gives you a few basic objects and hopes a light bulb flickers on above your
head. Suddenly you realise that hey - you CAN isolate your models from your
views. You CAN have multiple views per model. You CAN have proper event
handling, just like you can in every other non-web application you've ever
written. Hurrah! Need to extend your model? Easy! How about displaying the
same model - once as a full page, once as a widget in a sidebar? Simple! Need
to update the view when your model gets updated? Piece of cake!

Backbone is a solution to a lack of structure. It is not a framework. There is
no convention, no 'right way' to do things. Backbone is exactly what the name
suggests: a spine for your application. Everything else - your framework, your
error handling system, your security mechanisms - these are all left for you
to figure out yourself. You can pick a framework built on top of Backbone, or
you can figure one out for yourself. Backbone doesn't magically turn your web
app into a modular, extensible system - but try to build one WITHOUT Backbone
or something similar and see how far you get before you realise you've got
serious problems.

    
    
      > Nested views and automatic view updates.
    

Not Backbone's problem. It doesn't even attempt to solve this issue as far as
I'm aware. Solve it yourself, or use something which does.

    
    
      > How would you display a list of items in backbone? What do you do when an element is removed/added?
    

How is this Backbone's problem? How would you do it in any other programming
language aside from JS? Port it to JS, and your problem's solved.

    
    
      > How do you update a view when an element changes?
    

It SHOULD just be as simple as calling your render() method? If your rendering
code is incapable of not fucking this up, then it's your own fault.

At the end of the day - Backbone is not there to hold your hand. If you can't
figure the above problems out on your own, then Backbone is probably not for
you. Backbone is even agnostic about how exactly you draw your views onto the
page. Want to stick a shit-ton of logic in your template? Fine - but leave
Backbone out of it - that's between you and your templating engine!

Backbone gives you a solid foundation. Everything else is just arms and legs.

