Architecture for Big Backbone Applications

About us

Jorge Dias

Tech lead developer at XING

Jean Carlos Meninno

Frontend developer at XING

The good
old days

Not really

Browser wars

  • Incompatible versions
  • Global space pollution
  • Javascript events in the html

jQuery and others

  • Browser inconsistencies abstracted
  • Lots of plugins but often incompatible
  • Ad-hoc AJAX handling
  • Lack of client side templating

Modern
development

MV* – Backbone and friends

  • Modular structure
  • Communication through events
  • Consistent interface to backend

The good parts

Models and collections

  • Restful interface
  • Data and presentation are separated
  • Lifecycle events

Views

  • Easy handling of dom events
  • React to model/collection events

History

  • Routes handling
  • Back button keeps working
  • Push state (where available)
  • No full page reloads

Others

  • Not opinionated
  • underscore integration
  • jQuery integration
  • Fits into existent projects
  • Small footprint

The messy parts

Zombies

Types of zombies

  • Events
  • Views

Not a framework

  • Setup your own conventions
  • No clear way to structure your app
  • Lacks specialized views
  • Make your own framework on top

Others

  • No controllers
  • Mixed concerns between views and models
  • Huge routers

The Challenge

Rewrite the whole frontend in 4 months.
Previous version was 1.5 years in development.

The constraints

  • Don’t screw up by learning another framework
  • Lots of time preassure
  • 80% of team was backend

Alternatives Evaluation

  • Marionette
  • Chaplin
  • Thorax

What makes Marionette a good choice?

Documentation

Clean understandable code

Specialized views

  • Layouts
  • Region Manager
  • Collection/Composite View
  • ItemView

Memory and events management

Good bye zombies

Modules

  • Application structuring
  • Promotes modularity and encapsulation

Controllers

  • General purpouse coordinators

Event buses

Commands

App.commands.setHandler("log:request", function(request){
  console.log(request);
});

// Somewhere else
App.execute("log:request", request);

Requests

App.reqres.setHandler("foo", function(bar){
  return bar + "-quux";
});

App.request("foo", "baz"); // => returns "baz-quux"

Pub/sub

vent.on("foo", function(){
  console.log("foo event");
});

vent.trigger("foo"); // => "foo event" appears in console

App routers

  • Router composition
  • Router as configuration

Example

someController = {
  someMethod: function(){ /*...*/ }
};

Backbone.Marionette.AppRouter.extend({
  controller: someController,
  appRoutes: {
    "foo": "someMethod"
  }
});

Conventions

Composite applications

Real Examples

  1. User clicks on facet
  2. View triggers event
  3. Controller responds updating the search

  1. User clicks on Profile
  2. View triggers event
  3. Controller executes command to navigate

  1. Profiles app handles the command
  2. It initializes controller
  3. Controller requests profile model and renders the views

Data layer

  • Models and collections contained in one place
  • Events all the way
  • Everything is a promise
  • Only place that instantiates models/collections

// Inside entities/user
App.reqres.setHandler('user:current:entity', function () {
  return currentUser;
});

// Inside users/show/show_controller
// ...
currentUser = App.request('user:current:entity');

// Inside entities/search
App.reqres.setHandler('search:new:entity', function () {
  return new Search();
})

// Inside search/new/new_controller
var newSearch = App.request('search:new:entity');
var view = new New.SearchFormView({model: newSearch});
this.layout.mainRegion.show(view)

Core specialized classes

Patterns, patterns and more patterns

Examples

  • Dropdowns
  • Forms
  • Layouts
  • Modals
  • Tooltips
  • etc

Directory structure

  • Apps
  • Restful structure
  • Lib
  • Entities
  • Templates

Thank you

Cat picture for presentation completeness

Q & A