future-proofing your javascript apps (compact edition)

82
Thursday, 6 October 2011

Upload: addy-osmani

Post on 08-May-2015

27.048 views

Category:

Technology


0 download

DESCRIPTION

Future proofing your JavaScript applications with effective architectural design patterns.

TRANSCRIPT

Page 1: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 2: Future-proofing Your JavaScript Apps (Compact edition)

What are we looking at today?

Introduction

Design Patterns Patterns in JavaScriptScalable Application

Architecture

Thursday, 6 October 2011

Page 3: Future-proofing Your JavaScript Apps (Compact edition)

Some quick info.

About Me

• JavaScript & UI Developer @AOL

• Member of the jQuery core [Bugs/Docs/Learning] teams

• Blogger [AddyOsmani.com/ScriptJunkie]

• Author ‘Essential JavaScript Design Patterns’

Thursday, 6 October 2011

Page 4: Future-proofing Your JavaScript Apps (Compact edition)

We used to make these:

Thursday, 6 October 2011

Page 5: Future-proofing Your JavaScript Apps (Compact edition)

Which now make awesome pizza-cutters

Thursday, 6 October 2011

Page 6: Future-proofing Your JavaScript Apps (Compact edition)

Let’s get started.

Thursday, 6 October 2011

Page 7: Future-proofing Your JavaScript Apps (Compact edition)

We all like doing things a little bit differently.

We’re Individuals

“You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.”- Friedrich Nietzsche

Thursday, 6 October 2011

Page 8: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 9: Future-proofing Your JavaScript Apps (Compact edition)

Each of us have preferences for how we approach the below:

We all do things differently

Solving problems Structuring solutions Solving scalability

Thursday, 6 October 2011

Page 10: Future-proofing Your JavaScript Apps (Compact edition)

serious problems when working on code to be used by others.

Great but can lead to..

Inconsistent solutions Inconsistent architecture Dif!cult refactoring

Thursday, 6 October 2011

Page 11: Future-proofing Your JavaScript Apps (Compact edition)

A lot like how most Stormtroopers know that there’s a time, a place and a way to wear your uniform..and others

completely ignore this.

Thursday, 6 October 2011

Page 12: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 13: Future-proofing Your JavaScript Apps (Compact edition)

Reusable solutions that can be applied to commonlyoccurring problems in software design and architecture.

Design Patterns

“We search for some kind of harmony between two intangibles: a form we have not yet designed and a context we cannot properly describe’- Christopher Alexander, the father of design patterns.

Thursday, 6 October 2011

Page 14: Future-proofing Your JavaScript Apps (Compact edition)

Patterns are generally proven to have successfully solved problems in the past.

They’re proven

SolidReliable

approachesRe"ect

experience Representinsights

Thursday, 6 October 2011

Page 15: Future-proofing Your JavaScript Apps (Compact edition)

Patterns can be picked up, improved and adapted without great effort.

They’re reusable

Out-of-the-box solutions

Easily adaptedIncredibly !exible

Thursday, 6 October 2011

Page 16: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 17: Future-proofing Your JavaScript Apps (Compact edition)

Patterns provide us a means to describing approaches or structures.

They’re expressive

Problem agnosticCommon vocabularyfor expressing

solutions elegantly

Valuable as they can cut down on problems

Thursday, 6 October 2011

Page 18: Future-proofing Your JavaScript Apps (Compact edition)

Writing code that’s expressive, encapsulated & structured

JavaScript Design Patterns

Thursday, 6 October 2011

Page 19: Future-proofing Your JavaScript Apps (Compact edition)

Interchangeable single-parts of a larger system that can be easily re-used.

Module Pattern

“Anything can be de!ned as a reusable module”- Nicholas Zakas, author ‘Professional JavaScript For Web Developers’

Thursday, 6 October 2011

Page 20: Future-proofing Your JavaScript Apps (Compact edition)

Immediately invoked function expressions (or self-executing anonymous functions)

Stepping stone: IIFE

(function() {   // code to be immediately invoked   }()); // Crockford recommend this way

(function() {   // code to be immediately invoked   })(); // This is just as valid

(function( window, document, undefined ){    //code to be immediately invoked})( this, this.document);

(function( global, undefined ){    //code to be immediately invoked})( this );

Thursday, 6 October 2011

Page 21: Future-proofing Your JavaScript Apps (Compact edition)

But...

Thursday, 6 October 2011

Page 22: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 23: Future-proofing Your JavaScript Apps (Compact edition)

There isn’t a true sense of ‘privacy’ inside JavaScript.

Privacy In Modules

No Access Modi!ersVariables & Methods

can’t be ‘public’Variables & Methods

can’t be ‘private’

Thursday, 6 October 2011

Page 24: Future-proofing Your JavaScript Apps (Compact edition)

The typical module pattern is where immediately invoked function expressions (IIFEs) use execution context to create ‘privacy’. Here, objects are returned instead of functions.

Simulate privacy

var basketModule = (function() {    var basket = []; //private    return { //exposed to public        addItem: function(values) {            basket.push(values);        },        getItemCount: function() {            return basket.length;        },        getTotal: function(){           var q = this.getItemCount(),p=0;            while(q--){                p+= basket[q].price;             }            return p;        }    }}());

• In the pattern, variables declared are only available inside the module.

• Variables de"ned within the returning object are available to everyone

• This allows us to simulate privacy

Thursday, 6 October 2011

Page 25: Future-proofing Your JavaScript Apps (Compact edition)

Dojo attempts to provide 'class'-like functionality through dojo.declare, which can be used for amongst other things, creating implementations of the module pattern. Powerful when used with dojo.provide.

Module Pattern: Dojo

//traditional way var store = window.store || {};store.basket = store.basket || {}; //using dojo.setObject (with basket as a module of the store namespace)dojo.setObject("store.basket.object", (function() {    var basket = [];    function privateMethod() {        console.log(basket);    }    return {        publicMethod: function(){                privateMethod();        }    };}()));

Thursday, 6 October 2011

Page 26: Future-proofing Your JavaScript Apps (Compact edition)

In the following example, a library function is de!ned which declares a new library and automatically binds up the init function to document.ready when new libraries (ie. modules) are created.

Module Pattern: jQuery

function library(module) {  $(function() {    if (module.init) {      module.init();    }  });  return module;} var myLibrary = library(function() {   return {     init: function() {       /*implementation*/     }   };}());

Thursday, 6 October 2011

Page 27: Future-proofing Your JavaScript Apps (Compact edition)

A YUI module pattern implementation that follows the same general concept.

Module Pattern: YUI

YAHOO.store.basket = function () {     //"private" variables:    var myPrivateVar = "I can be accessed only within YAHOO.store.basket .";     //"private" method:    var myPrivateMethod = function () {            YAHOO.log("I can be accessed only from within YAHOO.store.basket");        }     return {        myPublicProperty: "I'm a public property.",        myPublicMethod: function () {            YAHOO.log("I'm a public method.");             //Within basket, I can access "private" vars and methods:            YAHOO.log(myPrivateVar);            YAHOO.log(myPrivateMethod());             //The native scope of myPublicMethod is store so we can            //access public members using "this":            YAHOO.log(this.myPublicProperty);        }    }; }();

Thursday, 6 October 2011

Page 28: Future-proofing Your JavaScript Apps (Compact edition)

Take the concept of reusable JavaScript modules further with the Asynchronous Module De!nition.

Better: AMD

Mechanism for de"ningasynchronously loadablemodules & dependencies

Non-blocking, parallel loading and well de"ned.

Stepping-stone to the module system proposed

for ES Harmony

Thursday, 6 October 2011

Page 29: Future-proofing Your JavaScript Apps (Compact edition)

de!ne allows the de!nition of modules with a signature of de!ne(id /*optional*/, [dependencies], factory /*module instantiation fn*/);

AMD: de!ne()

/* wrapper */define(    /*module id*/    'myModule',        /*dependencies*/    ['foo','bar','foobar'],        /*definition for the module export*/    function (foo, bar, foobar) {

        /*module object*/        var module = {};

        /*module methods go here*/        module.hello = foo.getSomething();        module.world = bar.doSomething();

        /*return the defined module object*/        return module;    });    

Thursday, 6 October 2011

Page 30: Future-proofing Your JavaScript Apps (Compact edition)

require is used to load code for top-level JS !les or inside modules for dynamically fetching dependencies

AMD: require()

/* top-level: the module exports (one, two) are passed as function args to the callback.*/require(['one', 'two'], function (one, two) {

});

/* inside: complete example */define('three', ['one', 'two'], function (one, two) {

    /*require('string') can be used inside the function    to get the module export of a module that has    already been fetched and evaluated.*/

    var temp = require('one');

    /*This next line would fail*/    var bad = require('four');

    /* Return a value to define the module export */    return function () {};});

Thursday, 6 October 2011

Page 31: Future-proofing Your JavaScript Apps (Compact edition)

Another easy to use module system with wide adoption server-side

Alternative: CommonJS

CommonJSWorking group

designing, prototyping,standardizing JS APIs

Format widely acceptedon a number of server-side

platforms (Node)

Competing standard. Tries to solve a few things AMD

doesn’t.

Thursday, 6 October 2011

Page 32: Future-proofing Your JavaScript Apps (Compact edition)

They basically contain two parts: an exports object that contains the objects a module wishes to expose and a require function that modules can use to import

the exports of other modules

CommonJS Modules

/* here we achieve compatibility with AMD and CommonJS using some boilerplate around the CommonJS module format*/(function(define){    define(function(require,exports){         /*module contents*/         var dep1 = require("foo");         var dep2 = require("bar");         exports.hello = function(){...};         exports.world = function(){...};    });})(typeof define=="function"? define:function(factory){factory(require,exports)});

Thursday, 6 October 2011

Page 33: Future-proofing Your JavaScript Apps (Compact edition)

De!ning modules that can work anywhere (CommonJS environments such as clients, servers; with script loaders etc). Thx to @KitCambridge for this version.

Better alternative: Universal Module De!nition

(function (root, Library) {  // The square bracket notation is used to avoid property munging by the Closure Compiler.  if (typeof define == "function" && typeof define["amd"] =="object" && define["amd"]) {    // Export for asynchronous module loaders (e.g., RequireJS, `curl.js`).    define(["exports"], Library);  } else {    // Export for CommonJS environments, web browsers, and JavaScript engines.    Library = Library(typeof exports == "object" && exports|| (root["Library"] = {      "noConflict": (function (original) {        function noConflict() {          root["Library"] = original;          // `noConflict` can't be invoked more than once.          delete Library.noConflict;          return Library;        }        return noConflict;      })(root["Library"])    }));  }})(this, function (exports) {  // module code here  return exports;});

Thursday, 6 October 2011

Page 34: Future-proofing Your JavaScript Apps (Compact edition)

A module format proposed for EcmaScript Harmony with goals such as static scoping, simplicity and usability.

ES Harmony Modules

// Basic modulemodule SafeWidget {    import alert from Widget;    var _private ="someValue";    // exports    export var document = {        write: function(txt) {            alert('Out of luck, buck');        },        ...    };}

// Remote modulemodule JSONTest from 'http://json.org/modules/json2.js';

Thursday, 6 October 2011

Page 35: Future-proofing Your JavaScript Apps (Compact edition)

Convenient, high-level interfaces to larger bodies of code that hide underlying complexity

Facade Pattern

“When you put up a facade, you're usually creating an outward appearance which conceals a different reality. Think of it as simplifying the API presented to other developers”- Essential JavaScript Design Patterns

Thursday, 6 October 2011

Page 36: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 37: Future-proofing Your JavaScript Apps (Compact edition)

var module = (function() {    var _private = {        i:5,        get : function() {            console.log('current value:' + this.i);        },        set : function( val ) {            this.i = val;        },        run : function() {            console.log('running');        },        jump: function(){            console.log('jumping');        }    };    return {        facade : function( args ) {            _private.set(args.val);            _private.get();            if ( args.run ) {                _private.run();            }        }    }}());module.facade({run: true, val:10}); //outputs current value: 10, running

A higher-level facade is provided to our underlying module, without directly exposing methods.

Example

Limited public view of functionality.Differs greatly from the reality of theimplementation.

Thursday, 6 October 2011

Page 38: Future-proofing Your JavaScript Apps (Compact edition)

A structural pattern found in many JavaScript libraries and frameworks (eg. jQuery).

A Facade

Simpli!es usage by encouraging use of

a limited interface forinteraction

Hides the inner-workings of a library.

Allows implementation to be less important.

This lets you be more creative behind the

scenes.

Thursday, 6 October 2011

Page 39: Future-proofing Your JavaScript Apps (Compact edition)

Encapsulates how disparate modules interact with each other by acting as an intermediary

Mediator Pattern

“Mediators are used when the communication between modules may be complex, but is still well de!ned”- Essential JavaScript Design Patterns

Thursday, 6 October 2011

Page 40: Future-proofing Your JavaScript Apps (Compact edition)

I always !nd this mediator analogy helps when discussing this pattern:

Air Traf!c Control

The tower handles what planes can take

off and land

All communication done from planes to tower,

not plane to plane

Centralised controlleris key to this success. Similar to mediator.

Thursday, 6 October 2011

Page 41: Future-proofing Your JavaScript Apps (Compact edition)

Promotes loose coupling. Helps solve module inter-dependency issues.

A Mediator

Allow modules tobroadcast or listen fornoti"cations without

worrying about the system.

Noti"cations can be handled by any number of

modules at once.

Typically easier to add or remove features to loosely coupled systems like this.

Thursday, 6 October 2011

Page 42: Future-proofing Your JavaScript Apps (Compact edition)

One possible implementation, exposing publish and subscribe capabilities.

Mediator Implementation

var mediator = (function(){    var subscribe = function(channel, fn){        if (!mediator.channels[channel])mediator.channels[channel] = [];        mediator.channels[channel].push({ context: this, callback:fn });        return this;    },     publish = function(channel){        if (!mediator.channels[channel]) return false;        var args = Array.prototype.slice.call(arguments, 1);        for (var i = 0, l = mediator.channels[channel].length; i <l; i++) {            var subscription = mediator.channels[channel][i];            subscription.callback.apply(subscription.context,args);        }        return this;    };     return {        channels: {},        publish: publish,        subscribe: subscribe,        installTo: function(obj){            obj.subscribe = subscribe;            obj.publish = publish;        }    };}());

Thursday, 6 October 2011

Page 43: Future-proofing Your JavaScript Apps (Compact edition)

Usage of the implementation from the last slide.

Example

//Pub/sub on a centralized mediator mediator.name = "tim";mediator.subscribe('nameChange', function(arg){        console.log(this.name);        this.name = arg;        console.log(this.name);}); mediator.publish('nameChange', 'david'); //tim, david  //Pub/sub via third party mediator var obj = { name: 'sam' };mediator.installTo(obj);obj.subscribe('nameChange', function(arg){        console.log(this.name);        this.name = arg;        console.log(this.name);}); obj.publish('nameChange', 'john'); //sam, john

Thursday, 6 October 2011

Page 44: Future-proofing Your JavaScript Apps (Compact edition)

Strategies for decoupling and future-proo!ng the structure of your application.

Scalable Application Architecture

Thanks to Nicholas Zakas, Rebecca Murphey, John Hann, Paul Irish, Peter Michaux and Justin Meyer for their previous work in this area.

Thursday, 6 October 2011

Page 45: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 46: Future-proofing Your JavaScript Apps (Compact edition)

Large-scale JavaScript apps are non-trivial applications requiring signi!cant developer effort

to maintain, where most heavy lifting of data manipulation and display falls to the browser.

De!ne a ‘large’ JS app.

Thursday, 6 October 2011

Page 47: Future-proofing Your JavaScript Apps (Compact edition)

Google’s GMail

Some Examples

Thursday, 6 October 2011

Page 48: Future-proofing Your JavaScript Apps (Compact edition)

The Yahoo! Homepage

Some Examples

Thursday, 6 October 2011

Page 49: Future-proofing Your JavaScript Apps (Compact edition)

AOL Mail / Phoenix

Some Examples

Thursday, 6 October 2011

Page 50: Future-proofing Your JavaScript Apps (Compact edition)

If working on a signi!cantly large JavaScript app, remember to dedicate suf!cient time to planning theunderlying architecture that makes the most sense.

It’s often more complex than we initially think.

Current Architecture

Thursday, 6 October 2011

Page 51: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 52: Future-proofing Your JavaScript Apps (Compact edition)

might contain a mixture of the following:

Your Current Architecture

MVC (Models/Views/Controllers)

An Application Core

Modules

Custom Widgets

JavaScript Libraries & Toolkits

Thursday, 6 October 2011

Page 53: Future-proofing Your JavaScript Apps (Compact edition)

The last slide contains some great architectural components, but used non-optimally they can come with a few problems:

Possible Problems

How much of this is instantly re-usable?

Can single modules exist on their ownindependently?

Can single modulesbe tested

independently?

Thursday, 6 October 2011

Page 54: Future-proofing Your JavaScript Apps (Compact edition)

Some further concerns:

Possible Problems

How much do modules depend on

others in the system?

Is your application tightly coupled?

If speci"c parts of your app fail, can it

still function?

Thursday, 6 October 2011

Page 55: Future-proofing Your JavaScript Apps (Compact edition)

What future concerns haven’t been factored in to this architecture?

Think Long-Term

• You may decide to switch from using jQuery to Dojo or YUI for reasons of performance, security or design

• Libraries are not easily interchangeable and have high switching costs if tightly coupled to your app

Thursday, 6 October 2011

Page 56: Future-proofing Your JavaScript Apps (Compact edition)

This is important.

Ask Yourself

If you reviewed your architecture right now, could a decision to switch

libraries be made without rewriting your entire application?

Thursday, 6 October 2011

Page 57: Future-proofing Your JavaScript Apps (Compact edition)

Fixing our architecture with JavaScript design patterns.

A Solution

“The only difference between a problem and a solution is that people understand the solution.’- Charles F. Kettering

Thursday, 6 October 2011

Page 58: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011

Page 59: Future-proofing Your JavaScript Apps (Compact edition)

We’re going to build something special.

Let’s Combine Our Patterns

Module Pattern

Facade Pattern

Mediator Pattern

+

+

= WIN

Thursday, 6 October 2011

Page 60: Future-proofing Your JavaScript Apps (Compact edition)

What do we want?

Let’s Think.

Loosely coupled architecture

Functionality broken down into smaller

independent modules

Framework or library agnostic. Flexibility to

change in future.

Thursday, 6 October 2011

Page 61: Future-proofing Your JavaScript Apps (Compact edition)

How might we achieve this?

Some More Ideas.

Single modules speak to the app when

something interesting happens

An intermediate layer interprets requests.

Modules don’t access the core or libraries

directly.

Prevents apps from falling over due to errors with speci"c modules.

Thursday, 6 October 2011

Page 62: Future-proofing Your JavaScript Apps (Compact edition)

The Facade

An abstraction of the core, it listens out for interesting events and says ‘Great. What happened? Give me the details’. It also acts as a permissions manager. Modules only communicate through this and are only able to do what they’ve been permitted to.

Thursday, 6 October 2011

Page 63: Future-proofing Your JavaScript Apps (Compact edition)

The Application Core

Manages the module lifecycle. It reacts to events passed from the facade and starts, stops or restarts modules as necessary. Modules here automatically execute when loaded.

Thursday, 6 October 2011

Page 64: Future-proofing Your JavaScript Apps (Compact edition)

Modules

Unique blocks of functionality for your application. They inform the application when something interesting happens. Don’t talk to each other directly, only concerned with publishing events of interest.

Thursday, 6 October 2011

Page 65: Future-proofing Your JavaScript Apps (Compact edition)

Enough talk! Let’s take a look at some real code.

Aura: A Preview

Aura is a framework I’m building at AOL that provides a boilerplate for one way to approach implementing this architecture. It will be released for open-source consumption once stable.

Thursday, 6 October 2011

Page 66: Future-proofing Your JavaScript Apps (Compact edition)

The Mediator / Application Core

Aura: Core

• Swappable Mediator with a light wrapper around a speci!c JavaScript library

• Ability to start and stop modules

• By default it comes with wrappers for both Dojo and jQuery, with core syntax that resembles the latter

Thursday, 6 October 2011

Page 67: Future-proofing Your JavaScript Apps (Compact edition)

How does this work?

Aura: Core

• Accessing this wrapper, the facade doesn’t care what framework has been slotted in. It works with the abstraction

• Behind the scenes, arguments are mapped to the relevant jQuery or dojo methods and signatures for achieving speci!c behaviour

Thursday, 6 October 2011

Page 68: Future-proofing Your JavaScript Apps (Compact edition)

A sample of the method signatures and namespaces supported

Aura: Core

// some core methodscore.start(module_id);   // define and initialise a modulecore.startAll();         // define, initialise all modulescore.stop(module_id);    // stop a specific modulecore.stopAll();          // stop all modulescore.destroy(module_id); // destroy a specific modulecore.destroyAll();       // destroy all modules

// core namespacescore.events  // bind, unbind etc.core.utils   // type checking.core.dom     // css, DOM manipulation

Thursday, 6 October 2011

Page 69: Future-proofing Your JavaScript Apps (Compact edition)

Chaining and CSS Style Manipulation are both supported. Behind the scenes, this works with both jQuery and Dojo, providing a single abstracted API that’s familiar to users.

Aura: Core.dom > Chaining, CSS

// Chaining and CSS style manipulationaura.core.dom.query('body').css({'background':'#1c1c1c'}); aura.core.dom.query('#search_input').css({'background':'blue'}).css({'color':'pink'});aura.core.dom.query('#search_button').css({'width':'200','height':'100'});

// Manipulating styles within a contextaura.core.dom.css('body', {'background':'red'});aura.core.dom.css('#shopping-cart',{'color':'green','background':'yellow'});aura.core.dom.css('#product-panel li', {'background':'purple'});

// Passing in DOM nodes also worksvar test = aura.core.dom.query('#shopping-cart'); //.query should handle this.aura.core.dom.css(test, {'background':'purple'});

Thursday, 6 October 2011

Page 70: Future-proofing Your JavaScript Apps (Compact edition)

Attribute manipulation and animation are also abstracted using an API similar to jQuery. Remember, with Dojo this actually maps arguments back to the relevant Dojo methods needed to achieve the task.

Aura: Core.dom > Attribs, Anim

// Get and set attributesconsole.log(aura.core.dom.query('#seach_input').attr('title','foobar'));console.log(aura.core.dom.query('#search_input').attr('title'));

// Passing in DOM nodesvar q = aura.core.dom.query('#shopping-cart');console.log(aura.core.dom.attr(q, 'id'));

// Animation supportaura.core.dom.animate('#product-panel li', { width: 400, height:20}, 5000);aura.core.dom.animate('button', {width: 200, duration: 100});aura.core.dom.animate('p', {width:20, height:40, padding:10,duration:200});

Thursday, 6 October 2011

Page 71: Future-proofing Your JavaScript Apps (Compact edition)

Similarly, element creation and ajax are also supported in the abstracted core interface.

Aura: Core.dom > Create, Ajax

// Element creationvar el = aura.core.dom.create("a", {          href: "foo.html",          title: "bar!",          innerHTML: "link"  },  'body');

// XHR/Ajax requests (deferred support coming soon) aura.core.dom.ajax({         url:'index.html',         type:'get', //post, put         dataType: "text",         success:function(data){                 console.log('success');         },         error:function(){                 console.log('error');         } });  

Thursday, 6 October 2011

Page 72: Future-proofing Your JavaScript Apps (Compact edition)

A very lightweight implementation of the facade pattern that provides modules with limited access to the core. They must communicate through the facade.

Aura: Aura.f (Facade)

 aura.f = {    define:function( core, module, config ){                var core = aura.core, dom = core.dom, events =core.events,        component = core.dom.query(module)._elements;

        return {            publish:function( e ){                events.trigger(e);            },            subscribe:function( e ){                events.register(e, module);            },            query:function( selector ){                return component.query(selector)._elements;            },            bind:function( el , type, fn ){                dom.bind(el, type, fn);            },            unbind:function( el , type, fn ){                dom.unbind(el, type, fn);            },            

Thursday, 6 October 2011

Page 73: Future-proofing Your JavaScript Apps (Compact edition)

aura.core.define("#todo-list", function (f) {    var todos;        return {        init : function () {          /*..*/        },        destroy : function () {         /*..*/       },       addEntry : function (todo) {         /*..*/       }   };});

Module wireframe.

Aura: Modules > add-todo.js

Let’s focus on this.

Thursday, 6 October 2011

Page 74: Future-proofing Your JavaScript Apps (Compact edition)

Module for adding new Todo items to a container on a page

Aura: Modules > add-todo.js

init : function () {    todos = f.query("ul");    f.subscribe({        'add-todo' : this.addEntry            });},destroy : function () {    f.destroy(todos);},addEntry : function (todo) {    var entry = f.create("li", { 'class' : 'todo_entry', [                    f.create("span", { 'class' :'todo_text', text : todo.value }),                    f.create("span", { 'class' :'todo_date', text : todo.date })                ]});    todos.append(entry);        f.publish({            type : 'added-todo',            data : todo.value    });              }

Thursday, 6 October 2011

Page 75: Future-proofing Your JavaScript Apps (Compact edition)

init : function () {    todos = f.query("ul");    f.subscribe({        'add-todo' : this.addEntry            });},

destroy : function () {    f.destroy(todos);},addEntry : function (todo) {    var entry = f.create("li", { 'class' : 'todo_entry', [                    f.create("span", { 'class' :'todo_text', text : todo.value }),                    f.create("span", { 'class' :'todo_date', text : todo.date })                ]});    todos.append(entry);        f.publish({            type : 'added-todo',            data : todo.value    });              }

Note how modules are only concerned with publishing and subscripting to noti!cations from the rest of the application. They don’t touch other modules directly.

Aura: Modules > add-todo.js

1. Cache the <ul> for a component representing the todo list (eg. a div)2. Subscribe to noti!cations about a new todo item being available. (eg. a user has just clicked ‘add’ somewhere in the app)3. A new noti!cation will trigger our .addEntry() method

Thursday, 6 October 2011

Page 76: Future-proofing Your JavaScript Apps (Compact edition)

init : function () {    todos = f.query("ul");    f.subscribe({        'add-todo' : this.addEntry            });},

destroy : function () {    f.destroy(todos);},

addEntry : function (todo) {

    var entry = f.create("li", { 'class' : 'todo_entry', [                    f.create("span", { 'class' :'todo_text', text : todo.value }),                    f.create("span", { 'class' :'todo_date', text : todo.date })                ]});    todos.append(entry);        f.publish({            type : 'added-todo',            data : todo.value    });              }

The facade allows access to everything from DOM query methods to dynamic object creation. It can be as light or as heavy on feature-access as you wish.

Aura: Modules > add-todo.js

1. Dynamically create a new todo entry (a list element with child spansfor the Todo text and creation date)2. Append this to the existing todo list cached earlier

Thursday, 6 October 2011

Page 77: Future-proofing Your JavaScript Apps (Compact edition)

init : function () {    todos = f.query("ul");    f.subscribe({        'add-todo' : this.addEntry            });},

destroy : function () {    f.destroy(todos);},

addEntry : function (todo) {    var entry = f.create("li", { 'class' : 'todo_entry',children : [                    f.create("span", { 'class' :'todo_text', text : todo.value }),                    f.create("span", { 'class' :'todo_date', text : todo.date })                ]});    todos.append(entry);        f.publish({            type : 'added-todo',            data : todo.value    });              }

Module for adding new Todo items to a container on a page

Aura: Modules > add-todo.js

Publish a noti!cation letting other modules know a todoitem has been added. The application can then react accordingly to this action.

Thursday, 6 October 2011

Page 78: Future-proofing Your JavaScript Apps (Compact edition)

aura.core.define("todo-counter", function(f){    var count, counter;    counter = f.query(".counter-text")        return{        init : function(){            f.subscribe({                'added-todo' : this.updateCount;            });        },        destroy: function(){            f.destroy(count);         },        updateCount: function(e){            count++;            counter.html(count);            f.publish({               type: 'counter-updated',               data: count             });        }

    } });

And here’s a basic module that consumes the noti!cations from the last one.

Aura: Modules > counter.js

Consuming events

Using library featureswithout directly touching them or the application core.

Thursday, 6 October 2011

Page 79: Future-proofing Your JavaScript Apps (Compact edition)

Let’s review what we looked at today.

What We Learned

‘Anyone who stops learning is old, whether at twenty or eighty. Anyone who keeps learning stays young. The greatest thing in life is to keep your mind young’- Henry Ford

Thursday, 6 October 2011

Page 80: Future-proofing Your JavaScript Apps (Compact edition)

Today we learned how to use three design patterns to create scalable ‘future-proof’ application architectures. The idea is to have:

Summary

Application coreMediator

Module managerSwappable

FacadeCore abstraction

Permission manager

ModulesHighly decoupled

Unique blocksFramework agnostic

Thursday, 6 October 2011

Page 81: Future-proofing Your JavaScript Apps (Compact edition)

For more on this architecture and other topics, check out:

That’s it.

Blog Twitter GitHub

http://addyosmani.com @addyosmani /addyosmani

Thursday, 6 October 2011

Page 82: Future-proofing Your JavaScript Apps (Compact edition)

Thursday, 6 October 2011