design patterns for
Large-scale JAVASCRIPT
    
    
Jan 27th, 2014

AGENDA
- Design Patterns
- Javascript Design Patterns
- Constructor
- Module
- Revealing Module
- Façade
- Observer
- Mediator
- Large-scale Javascript
    ______________________________________________
    Design Patterns for Javascript
 

AGENDA
- Singleton
- Prototype
- Command
- 
Factory Method
 
- Abstract Factory
- Mixin
- Decorator
- Flyweight
- Lazy Loading
    ______________________________________________
    Design Patterns for Javascript
 

Prerequisites
- Intermediate Javascript
- 
    Familiarity with Design Patterns
    ______________________________________________
    Design Patterns for Javascript
 

design patterns
- 
Hyperspace: the next dimension above.
- We can only see up to the current dimension.
- Consider 3 dimensions for a browser:
- 
Rendering: HTML/CSS.
- 
Elements: DOM.
- 
Behavior: JS.
 
- The 4th dimension is its hyperspace. 
 How would it be?
    ______________________________________________
     Boosting the client-side with Backbone.js
 

javascript design patterns
- Application ends:
								
- 
Front-end: interacts with a human.
- 
Back-end: handles business logic and data/services access.
 
- Application sides:
								
- 
Client-side: runs on user browser/device.
- 
Server-side: runs on a server.
 
    THEY ARE NOT THE SAME THING!
    ______________________________________________
     Boosting the client-side with Backbone.js
 

constructor
- Isolated web-apps (client-side only):
		
- 
Only front-end. Ex: "BMI calculator".
- 
Front-end and back-end. Ex: "TODO list manager" persisting on HTML5 local storage on the browser.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

client-side vs. server-side
- Integrated web apps (client-side and server-side):
- 
Front-end on client-side + back-end on server-side. Response is hypertext over HTTP. Ex: "TODO list manager" in a web framework (Struts, JSF, Rails).
- 
Front-end and back-end on client-side + REST back-end on server-side. Response is data over HTTP. Ex: "Trello" implemented in Backbone.js.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

REST
- REpresentational State Transfer.
- Stateless architectural style for distributed systems, based on HTTP protocol:
- HTTP methods are verbs (actions).
- URIs are nouns (resources).
- HTTP status codes are meaningful actions responses, like 200 (ok), 404 (not found), 500 (internal server error).
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

REST
- REST actions addressed today:
    							
- 
    HTTP GET:
     retrieves a resource. Ex:  GET/users/1retrieves the user which id = 1.
- 
    HTTP POST:
 creates a resource. Ex:  POST/userscreates an user (data on request body).
- 
    HTTP PUT:
 updates a resource. Ex:  
PUT/users/1updates the user which id = 1 (data on req. body).
 
- 
HTTP DELETE:
 removes a resource. Ex:  DELETE/users/1removes the user which id = 1.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

JSON
- JavaScript Object Notation.
- Universal format of data transference in JavaScript.
- Reduced size, simplified format, easy to parse -> good alternative to XML.
{
  "name": "R2-D2",
  "owners": ["Anakin", "Leia", "Luke"],
  "attributes": {
    "height": 0.96,
    "mass": 32
  }
}					
    ______________________________________________
     Boosting the client-side with Backbone.js
 

MVC
- Model-View-Controller.
- Architectural design pattern that leverages better application organization through separation of concerns:
- 
Model: business data.
- 
View: user interface.
- 
Controller: connection and data input logic.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

MVC in Javascript
- Avoid "spaghetti code" (hard to read and maintain for the lack of structure).
- Overall maintainability is strongly improved. It  makes it clear to identify where to change the code.
- Enables more objective unit tests.
- Modularity allows better distribution of tasks among the team.
MVC IS OUR HYPERSPACE!!
    ______________________________________________
     Boosting the client-side with Backbone.js
 

WEB FRAMEWORKS vs. client-side apps
- Server-side web frameworks:
        
- Actions life cycle is managed and routed on the server-side.
- Server-side templates generating HTML from data.
- HTTP response transmitting hypertext (HTML).
- Every action demands a page reload.
- Actions are synchronous.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

WEB FRAMEWORKS vs. client-side apps
- Client-side apps:
    								
- Actions life cycle is managed and routed on the client-side.
- HTTP response transmitting data (JSON, XML, etc...).
- Client-side templates generating HTML from data.
- Actions DON'T demand any page reload.
- Actions can be asynchronous.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    backbone.js
- Javascript library that provides structure to client-side applications based on REST APIs using JSON.
- Created in 2010, it is currently used in big websites such as Airbnb, BitTorrent, Digg, Foursquare, Hulu, LinkedIn mobile, Pinterest, Trello, Walmart and Wordpress.
- Depends on Underscore.js and jQuery (or similar libs such as Zepto.js, with varying degrees of compatibility).
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    backbone.js
- 
SPA (Single-Page Application): architectural style about doing a single page load for the whole application.
- 
Elements: Model, Collection, View and Router.
Backbone.js isn't a classic MVC framework...
							...but it belongs to MV* family, which similar goals!!
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Model
- Stores and manipulates data.
- Communicates with REST APIs.
- Supports parsing, translation, validation and business logic processing.
var CardModel = Backbone.Model.extend({
  urlRoot : '/api/cards'
});							
							
- 
urlRootspecifies the base URL for REST calls, which will precede the REST actions.
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Model
- REST methods:
    								
- 
fetch(options): Retrieves an entity via HTTP GET.
- 
save(attributes, options): Creates an entity via HTTP POST (if the object doesn't have an id yet) or updates an entity via HTTP PUT (if the object has an id already).
- 
destroy(options): Removes an entity via HTTP DELETE.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Model
- Parâmetros:
    								
- 
attributes: Object containing data to be saved.
- 
options: Object containing configuration such as:
- 
url: Connection URL with the server-side, overwritingurlRoot.
- 
success: Callback function for success response.
- 
error: Callback function for error response or timeout .
 
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Model
var model = new CardModel({
  id: 1
});
// GET /api/cards/1
model.fetch({
  success: function(model, response, options) {
    console.log('Success! Model = ' + model.toJSON());
  },
  error: function(model, response, options) {
    console.log('Error or timeout.');
  }
});							
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Model
- Some common methods:
- 
get(attribute): Gets the value of an attribute from the Model. Ex:card.get('title');
- 
set(attribute, value): Sets a value for an attribute on the Model. Ex:card.set('title', 'Project X');
- 
toJSON(): Returns a copy of the Model data in JSON. Ex:card.toJSON();
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Collection
- Ordered list of Models.
- Creates models from a JSON array.
- Implements array methods from Underscore.js library.
var CardCollection = Backbone.Collection.extend({
  model : CardModel,
  url : '/api/cards'
});							
							
- 
modelspecifies the Model to be created.
- 
urlspecifies the base URL for REST calls, which will precede the REST actions.
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Collection
- Collections complement the REST API from Models with this method:
    								
- 
fetch(options): Retrieves an array of entities via HTTP GET,   populates each entity as a Model and inserts it in the Collection.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Collection
var cardCollection = new CardCollection();
// GET /api/cards
cardCollection.fetch({
  success: function(collection, response, options) {
    console.log('Success! Collection = ' + 
                collection.toJSON());
  },
  error: function(collection, response, options) {
    console.log('Error or timeout.');
  }
});    						
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Collection
- Some common methods:
    								
- 
get(id): Retrieves a Model a from its id. Ex:collection.get(12);
- 
at(index): Retrieves a Model from its position on the Collection. Ex:collection.at(1);
- 
add(model): Adds a Model to the Collection. Ex:collection.add({'title', 'Project X'});
- 
remove(id): Removes a Model from the Collection. Ex:collection.remove(12);
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Collection
- Some common methods:
        							
- 
toJSON(): Returns a copy of the Collection data in JSON. Ex:collection.toJSON();
 
- 
where(attributes): Returns just the Collection elements which match the given criteria. Ex:collection.where({'type': 'PROJECT'});
- 
pluck(attribute): Returns an array with extracted values from Collection elements, based on the given attribute. Ex:collection.pluck('title');
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    View
- Manages the presentation logic and events.
- Renders an HTML template which can be added to the DOM, consuming data from Models or Collections.
- The HTML template can be dynamically generated.
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    View
- Main attributes to be implemented:
- 
events: Events mapping object, like this:
 'CSS selector': function / 'function'
- 
render(): Method that should contain all the View logic, in three steps:
- Retrieving/preparing the HTML template.
- Rendering the HTML template from a Model or Collection.
- Inserting the rendering result into elattribute.
 
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    View
- Some common View attributes:
    								
- 
el: HTML element rendered by this View. It can be accessed via$elas a jQuery/Zepto.js object.
- 
id: Theidattribute fromel.
- 
className: Theclassattribute fromel
- 
tagName: The HTML tag to be used byel.
- 
remove(): Removes the View from the DOM and remove all event listeners binded to it.
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    View
var CardView = Backbone.View.extend({
  events: {
    'click button.close': function(e) {
      e.preventDefault();
      this.remove();
    }
  },
  render: function() {
    var result = 
       '<h1>' + this.model.get('title') + '</h1>' +
       '<button class="close">Close</button>');
    this.$el.html(result);
  }
});    						
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    View
- View parameters:
									
- 
el: An existing HTML element can be provided to receive the content rendered by the View.
- 
model: The Model to be consumed byrender().
- 
collection: The Collection to be consumed byrender().
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    View
var cardModel = new CardModel({ id: 1 });
cardModel.fetch({
  success: function(model, response, options) {
    var cardView = new CardView({
      model: cardModel
    );
    cardView.render();
    $('#contents').append(cardView.el);
  },
  error: function(model, response, options) {
    console.log('Error or timeout.');
  }
});							
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Router
- Allows for URL handling and routing.
- Controls the navigation history.
- Avoids direct requests to the server-side.
- Main attribute:
									
- 
routes: Mapping routes object, like this:
 'uri': function / 'function'
 
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Router
var AppRouter = Backbone.Router.extend({
  routes : {
    '' : 'viewAll',
    'card/:id' : 'viewCard',
    '*path' : 'viewAll'
  },
  viewAll: function() { ... },
  viewCard: function(id) { ... }
});    			
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Router
- It is necessary to call Backbone.history.start()
 
to start the routes monitoring by the Routers.
- Pass {pushState: true}to it in order to use HTML5 pushState. Otherwise, the routing would use # after the URL query string..
var appRouter = new AppRouter();
Backbone.history.start({
  pushState : true
});							
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Dynamic templates
- On the View, the HTML template can be generated by any Javascript templating library such as Underscore.js, Mustache, Handlebars.js, dust.js, etc...
- It is the same idea of PHP, JSP, ERB, ASP - but now on the client-side.
- It is much more maintainable then concatenated strings.
    ______________________________________________
     Boosting the client-side with Backbone.js
 

    Dynamic templates
- 
Handlebars.js: performative, flexible and easy to learn and to handle alternative.
{{#if children}}
  <ul>
    {{#each children}}
      <li>{{title}}: {{description}}</li>
    {{/each}}
  </ul>
{{else}}
  <p>There is no items!</p>
{{/if}}
- Will be covered on a next AC talk by Alysson Ferreira!
    ______________________________________________
     Boosting the client-side with Backbone.js
 

Conclusion
- Client-side apps aim to reproduce the desktop experience on the web.
- Client-side apps can drastically reduce the time waited by the user for a feedback.
- Hence, the chances for the user to stay on the system are greatly increased.
- Backbone.js is a mature MV* alternative to structure client-side apps.
    ______________________________________________
     Boosting the client-side with Backbone.js
 

Learn more
    ______________________________________________
    Design Patterns for Javascript
 

CHALLENGE
Write a multiple-choice quizz about a subject of your preference as a client-side app using Backbone.js.
    
- 
The user name and email should be collected.
        
- 
5 possible answers per question.
            
 
- 
            Either just 1 or up to 3 answers per time.
        
- 
            At least 5 questions on the quizz.
        
- 
            Lastly the user must see a graph of all questions and answers  from all users with % for each answer.
        
- 
            Any approach for persistence, as long it uses Models (REST backend, local storage, session object, cookie...).
- Send me the solution in a GitHub repo. 
    _____________________________________________
     Boosting the client-side with Backbone.js
 
