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/1
retrieves the user which id = 1. -
HTTP POST:
creates a resource. Ex:
POST
/users
creates an user (data on request body). -
HTTP PUT:
updates a resource. Ex:
PUT
/users/1
updates the user which id = 1 (data on req. body).
-
HTTP DELETE:
removes a resource. Ex:
DELETE
/users/1
removes the user which id = 1.
-
HTTP GET:
retrieves a resource. Ex:
______________________________________________
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'
});
-
urlRoot
specifies 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'
});
-
model
specifies the Model to be created. -
url
specifies 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
el
attribute.
-
______________________________________________
Boosting the client-side with Backbone.js
View
- Some common View attributes:
-
el
: HTML element rendered by this View. It can be accessed via$el
as a jQuery/Zepto.js object. -
id
: Theid
attribute fromel
. -
className
: Theclass
attribute 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
- Some common methods:
-
route(path, name)
: Also inserts a route, but can use regex. Ex:router.route(/^card/(\d+)$/, 'viewCard');
-
navigate(path, options)
: Navigates to a URL. In order to also trigger the route, useoptions
as{trigger: true}
. Ex:router.navigate('/card/32', {trigger: true});
______________________________________________
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
- Learning JavaScript Design Patterns - Addy Osmani - addyosmani.com/resources/essentialjsdesignpatterns
- Patterns for Large-Scale JavaScript Application Architecture - addyosmani.com/largescalejavascript
- Javascript Patterns - Stoyan Stefanov - shop.oreilly.com/product/9780596806767.do
______________________________________________
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
Copy of Design Patterns for Large-Scale Javascript
By Tiago Romero Garcia
Copy of Design Patterns for Large-Scale Javascript
Learn the essential design patterns for large-scale Javascript applications. By Tiago Garcia
- 2,136