The World Beyond MVC
MVC, though, was one of the few ancient methods that made immediate sense. Because it has a clear place for the UI to exist, it's easily applied to the front-end (although, again, that application is not canon). Because any pattern we want to use has to be fudged a bit to get it to fit our context, MVC is a great place to start. But it's not the only option we have.
It seems fair to call Event-Driven Architectures the second most obvious pattern. We use event-driven patterns all over the place in JS, and even in combination with MV* patterns. They work well where we need a lot of messaging, and have less need for clear-cut, classical "objects". For the objects we do have, getters and setters (and soon,
Object.observe()) can be used as publishers and subscribers, decoupling events, the core of the application, from the things they affect. The value, though, is that these decoupled events don't need to affect only objects, but can also affect the DOM, or server interactions, or other events, and none of that needs to be packaged up in a Model-View-Controller triad if it doesn't make sense as one.
The Naked Objects pattern bears closest relation to MV*, and it would not be unfair to call it a variant of Presentation-Abstraction-Control (a more distant relative). This one's good for big meaty widgets that need to contain and render their own data, and whose visual representation maps directly to the data they contain. It bears similarity to the drag-and-drop IDEs we used to use to build desktop applications, but without the drag-and-drop bit. Rebecca Murphey used a similar pattern in building the Mulberry mobile app framework, which is a perfect use case because Naked Objects is a great way of organizing a composable framework whose implementations will be better served by a different pattern.
The third pattern I think deserves more examination is Pipelines. This should be familiar to jQuery developers or anyone who deals with a lot of callbacks. Pipelines chain operations together to affect a shared state, which might be a visual representation or just a set of data (or both!). The interesting thing to me is that we can use this pattern both synchronously and asynchronously, for example applying global functions to initialize, render, and wire-up a page, then use instance-specific functions to wait for user interaction, validate it, attempt to save it, and render again, all the while modifying the state of an abstraction of that page. Anything with a state can have a corresponding state diagram in code, with the ability to modify the path it takes depending on the result of each step.
With all of these, as with MVC or any other pattern, you have to consider how and where you want your application tightly or loosely coupled, and whether you need a centralized snapshot of the application, or it's better stored in the components it affects. Things like Naked Objects would be overkill if even your most complex controls are only used once. Things like EDA would be pointless if most of your code is setup and initialization code. And if your site is static, whatever introduces the least framework code while still helping you establish clear conventions would be preferable.
At the end of the day, you should still use Backbone rather than not use anything. However, if you find yourself with an application that fits more easily into some other pattern, you shouldn't be afraid to use it. Sadly, for most of these patterns (and the myriad I haven't even mentioned), you're going to have a hard time finding anything as robust and accessible as Backbone. So, more importantly, if you're sitting down to write a new JS application framework, you'd do all of us a service by exploring an alternative to MVC, so picking the right tool for the job won't be a matter of choosing from a selection of nice hammers with different brandnames to tighten screws. Whatever you choose, and whatever the application, though, remember that all implementations decay and it's just as important to leave the opportunity to improve architecture as it is to leave ways to improve the code itself.