
Patterns for Managing Large Scale Backbone Applications - benhowdle89
http://benhowdle.im/2013/03/24/patterns-for-managing-large-scale-backbone-applications/
======
ShellfishMeme
I honestly don't feel like any of the "large scale (JS|Backbone) applications"
posts really addresses the difficulties you run into when scaling JS
applications. Most of these things are common sense (eg. "use namespaces",
"make use of consistent naming conventions" etc.) and should hold for any kind
of application development.

For me, one of the main problems when scaling the Backbone app I work with is
decoupling View interactions. Now the usual recommendation you receive is
using an event bus. In the link @analog just posted [1], Addy Osmani talks
about using the Mediator pattern to achieve the decoupling, which certainly
does help, but imho his example does not fully reflect the purpose of the
Mediator pattern. His Mediator is barely more than just an event bus.

A Mediator can make use of an event bus, but an event bus is not automatically
a mediator. It still forces the views to know about events triggered from
other views and react to them. This still causes coupling, and even worse, it
keeps the coupling in the views. The mediator should exist to take care of
that coupling and pull it out of the views.

Let's take for example a checkout page. The checkout page has a view
containing a form for address data. It also has a view that lets you pick the
payment provider, a view that allows you to enter a coupon and a view that
shows the order total.

Here are some of the required view-to-view interactions:

* If the user email changed, revalidate the coupon to make sure the "new users only" constraint applies and show the status

* If the payment type is changed to Paypal, add an additional charge to the order total and display it.

* If a coupon is entered, update the order total

This means that in many cases, views need to know exactly how the public event
interfaces of the other views look, even if they communicate by an event bus
and not by direct references and method calls. To make the application
maintainable, we need to get rid of the knowledge about the other views'
events as well.

This is where the Mediator comes into play. We make the mediator aware of the
different event interfaces of the Views and have it decide which events to
retrigger or which methods to call in what View. Instead of having the views
subscribe to the other Views' events, the Mediator wires them up and
encapsulates the View interactions. The Mediator now knows that the
`change:email` event from the AddressForm triggers the `validateCoupon` method
on the CouponView or the `validate:coupon` event to which the CouponView
listens. The CouponView no longer needs to know about the existence of the
`change:email` event.

Now the Views only need to specify their public (event) interfaces and the
Mediator knows about how the different Views interact. This is a lot more
scalable than the naive event bus approach.

I really wish there were more articles about scaling really big JS
applications. In the end they will probably heavily borrow from GoF's Design
Patterns book, but it always helps to see the patterns in action. I appreciate
the author's effort, but I always feel disappointed when I read "Large Scale
(Backbone|JS) Applications" and don't find advice to solve and real problems
what come up with scaling "Large Scale (Backbone|JS) Applications".

[1] <http://addyosmani.com/largescalejavascript/>

~~~
ef4
The example you give is the kind of thing that Ember is really good at.

You would implement all those interrelationships with computed properties.
Each computed property updates automatically if its dependencies change, and
each view redraws automatically when the corresponding properties change. All
that work of defining events and propagating them through the mediator is
stuff that Ember does for you automatically, once you've declared what depends
on what.

I'm one of the early adopters who built a rather big application in pre-1.0
Ember. It definitely pays off as the application grows larger.

------
jashkenas
Ben -- since you're around, and it seems to be "struggle with getting started
with X.js week" around these parts ... I figure I should ask you about this:

    
    
        > which is what causes problems for a lot of people 
        > when getting to grips with it (myself included).
    

What exactly did you have a hard time coming to grips with?

~~~
kjbekkelund
Jeremy, what I've seen most people struggle with (including myself in the
beginning) is those first couple of hundred lines of code. How does everything
fit together? How should I handle templates? How to I create nested models?
How do I stop thinking "in jQuery" and start thinking "in Backbone"?

I guess the thing is that the current documentation works really well when you
understand Backbone. Before you understand it, getting started is really
difficult. That's why we see so many getting started guides all around — the
problem of course being that most of them are barely just ok. Backbone should
have a really, really good getting started guide, which (I think) should be
more opinionated than Backbone itself — i.e. it shows one (really good) way of
doing things (that works well when you scale up your application). Or at least
link to one.

I've heard many say "look at the todo example", but I think that it's so far
away from a real app that it's difficult to use as a starting point. It
doesn't use ajax, it relies heavily on global state, it puts templates in the
HTML, lots of global `$` stuff, no routing, etcetc. Ok-ish choices, but not a
great example for those getting started. E.g. having templates in the DOM is
ok when you have 5 views. When you have more it's problematic, especially for
testing and for precompiling templates.

Backbone is great when you grok it, but it takes a lot of time to find your
own patterns that works really well. (Marionette and Chaplin are awesome, but
still, first when you have some basic understanding of Backbone itself)

~~~
catshirt
>> How does everything fit together?

initialize models and controllers, then pass that data to newly initialized
views. at any scale, this hardly differs.

>> How should I handle templates?

backbone is template agnostic so the answer is "however you'd like". because I
use r.js, my preference is loading the templates as separate text modules and
defining them on my view. when our production script is build, the templates
are inlined into the javascript through r.js.

your qualms with the todo example (no AJAX, global variables, strange template
handling) are things that are not at all pertinent to Backbone and are solved
by other patterns. point being, Backbone has it's own model/view pattern, but
you can look at it in isolation. your other concerns are things solved by
patterns with no pertinent relation to Backbone.

~~~
kjbekkelund
I wasn't commenting on Backbone itself, I was commenting on getting started
with Backbone. I've held 15+ workshops and presentations on Backbone and
helped a lot of people getting started. These are the issues I have most often
heard from them.

~~~
catshirt
my point is that these questions seem either misdirected or simply answered.
that is to say, it's not a framework. it's a set of classes. how you handle
templates, how these classes fit together, etc is hardly a function of
Backbone.

don't get me wrong. i've been there. i've had the same questions. but i think
the answers i gave would have satisfied me when i was starting, had i had a
mentor.

------
brunoc
I recommend anyone getting into building web apps (regardless of framework) to
read Mixu's "Single page apps in depth" <http://singlepageappbook.com/single-
page.html>

It's a short read, it's opinionated and will make you think, especially if
you're a novice / intermediate programmer. In particular, the "Writing
maintainable code" chapter.

Focusing on things like namespacing is not necessarily a bad thing, but it
doesn't address the real goal - writing modular, testable, maintainable code.
If your components know where other components are in the namespace and depend
on them internally, the namespace hierarchy does nothing to help your design.

The main difficulty in designing complex web applications is managing
dependencies between objects, just like any large object-oriented piece of
software (assuming that is the paradigm you choose).

------
jlgaddis
Oh, _that_ backbone...

\-- disappointed network engineer

~~~
perlgeek
Same here, though I'm not a network engineer.

Can we please, please say "backbone.js" when we're not talking about that
"other" backbone (which has a much older claim on this name)?

~~~
magsun
You should get used to it.. More and more non-CS programmers are coming with
"JS is everything" and without any other tips.

------
zimbatm
Nitpick: App and Models are singleton instances. Shouldn't they be lowercased
?

~~~
benhowdle89
Truly nitpicking ;), you're probably right, but as a convention it makes sense
for me and hopefully others!

------
gvc
a bit of a side track here, I've been seen a lot of blogs with this same
layout, is it a blogging platform or just people copying around?

If it is a blogging platform, which one is it?

~~~
benhowdle89
Are you thinking of <https://svbtle.com/> ? Yeah mine looks similar but I
assure you, it wasn't ripped at all!

~~~
gvc
Sorry Ben, I didn't mean to accuse you of anything. Sorry if it came out that
way. And yeah, that's what I was looking for :) thanks!

------
analog
The big piece missing from this is RequireJs as the author mentions. We should
all know it's good practice not to use global variables so that should be
reason enough to use it in itself.

As an example an app we built had a conflict between a jQuery plugin that the
frontend devs had included, and a library that we had added with require.
Having the conflict only show up in one place rather than the whole app
certainly made it quicker to diagnose.

Addy Osmani's tutorials should be required reading if you're just starting
out. [1] [2]

The only downside that we saw was that you will have to provide AMD versions
of each library you use if you want to use jQuery from a CDN.

As well as being good practice it just feels really nice to have everything
you're using declared at the top of the file you're in. The sugared require
syntax helps with this. [3]

[1] <https://github.com/addyosmani/backbone-fundamentals>

[2] <http://addyosmani.com/largescalejavascript>

[3] <http://requirejs.org/docs/whyamd.html#sugar>

~~~
bjterry
I have found it is convenient to use RequireJS's shim features to load
libraries that use AMD rather than looking for AMD versions. For example, we
use MathJax off their CDN and they do not provide an AMD version.

~~~
analog
Are you using the r.js optimiser though? We definitely couldn't use a local
non-AMD version with other CDN libraries when using the optimiser to build our
js out for production.

