114
Scalable JavaScript Application Architecture Nicholas C. Zakas | @slicknet

Scalable JavaScript Application Architecture 2012

Embed Size (px)

DESCRIPTION

An update to the Scalable JavaScript presentation of 2009. Describes how to piece together a JavaScript application framework designed for maintainability.

Citation preview

Page 1: Scalable JavaScript Application Architecture 2012

Scalable JavaScript Application Architecture

Nicholas C. Zakas | @slicknet

Page 2: Scalable JavaScript Application Architecture 2012

New

Page 3: Scalable JavaScript Application Architecture 2012

ControllerView

Model

Page 4: Scalable JavaScript Application Architecture 2012

Building an application framework

Page 5: Scalable JavaScript Application Architecture 2012

An application frameworkis like a playground for your code

Provides structure around otherwise unrelated activities

flickr.com/photos/osterwalder/152697503/

Page 6: Scalable JavaScript Application Architecture 2012

Isn't that what JavaScript libraries do?

Page 7: Scalable JavaScript Application Architecture 2012

A JavaScript library is like a toolboxYou can build any number of things using the tools

flickr.com/photos/skistz/398429879/

jQuery

YUI

Dojo

Page 8: Scalable JavaScript Application Architecture 2012

ApplicationCore

Base Library

Page 9: Scalable JavaScript Application Architecture 2012

Module TheoryEverything is a module

Page 10: Scalable JavaScript Application Architecture 2012

module (n)1 : a standard or unit of measurement2 : the size of some one part taken as a unit of measure by which the proportions of an architectural composition are regulated3 a : any in a series of standardized units for use together: as (1) : a unit of furniture or architecture (2) : an educational unit which covers a single subject or topic b : a usually packaged functional assembly of electronic components for use with other such assemblies4 : an independently operable unit that is a part of the total structure of a space vehicle5 a : a subset of an additive group that is also a group under addition b : a mathematical set that is a commutative group under addition and that is closed under multiplication which is distributive from the left or right or both by elements of a ring and for which a(bx) = (ab)x or (xb)a = x(ba) or both where a and b are elements of the ring and x belongs to the set

Source: Merriam-Webster Dictionary

Page 11: Scalable JavaScript Application Architecture 2012

module (n)1 : a standard or unit of measurement2 : the size of some one part taken as a unit of measure by which the proportions of an architectural composition are regulated3 a : any in a series of standardized units for use together: as (1) : a unit of furniture or architecture (2) : an educational unit which covers a single subject or topic b : a usually packaged functional assembly of electronic components for use with other such assemblies4 : an independently operable unit that is a part of the total structure of a space vehicle5 a : a subset of an additive group that is also a group under addition b : a mathematical set that is a commutative group under addition and that is closed under multiplication which is distributive from the left or right or both by elements of a ring and for which a(bx) = (ab)x or (xb)a = x(ba) or both where a and b are elements of the ring and x belongs to the set

Source: Merriam-Webster Dictionary

Page 12: Scalable JavaScript Application Architecture 2012
Page 13: Scalable JavaScript Application Architecture 2012
Page 14: Scalable JavaScript Application Architecture 2012

How does this apply to web applications?

Page 15: Scalable JavaScript Application Architecture 2012

web application module (n)1 : an independent unit of functionality that is part of the total structure of a web application

Source: Me

Page 16: Scalable JavaScript Application Architecture 2012
Page 17: Scalable JavaScript Application Architecture 2012

Web application modules consist ofHTML + CSS + JavaScript

Page 18: Scalable JavaScript Application Architecture 2012

Any single module should be able to live on its own

Page 19: Scalable JavaScript Application Architecture 2012

Loose coupling allows you to make changes to

one module without affecting the others

flickr.com/photos/quinnanya/3575417671/

Page 20: Scalable JavaScript Application Architecture 2012

Each module has its own sandboxAn interface with which the module can interact to ensure loose

coupling

flickr.com/photos/renfield/3414246938/

Page 21: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Module Module

Page 22: Scalable JavaScript Application Architecture 2012

Sandbox

ModuleModule

Module

Module Module

Modules have limited knowledgeEach module knows about their sandbox and that's it

Page 23: Scalable JavaScript Application Architecture 2012

Core.register("module-name", function(sandbox){

return { init: function(){ //constructor },

destroy: function(){ //destructor }

};

});

Page 24: Scalable JavaScript Application Architecture 2012

Which parts know about the web application being built?

Page 25: Scalable JavaScript Application Architecture 2012

None of them

Page 26: Scalable JavaScript Application Architecture 2012

Each part of the architecture is like a puzzle piece

No single piece needs to know what the picture isAll that matters is that the piece does its own job correctly

flickr.com/photos/generated/501445202/

Page 27: Scalable JavaScript Application Architecture 2012

What is a module's job?

Page 28: Scalable JavaScript Application Architecture 2012

Hello, I'm the weather module.It's my job to tell you the weather.

Page 29: Scalable JavaScript Application Architecture 2012

Hello, I'm the stocks module.It's my job to tell you about the stock market.

Page 30: Scalable JavaScript Application Architecture 2012

Each module's job is to create a meaningful user experience

Page 31: Scalable JavaScript Application Architecture 2012

The web application is createdas a result of all parts doing their job

flickr.com/photos/eljay/2392332379/

Page 32: Scalable JavaScript Application Architecture 2012

Sandbox

ModuleModule

Module

Module Module

Page 33: Scalable JavaScript Application Architecture 2012

Modules contain business logicrelated to the module’s particular job

ModuleModule

Module

Module Module

Page 34: Scalable JavaScript Application Architecture 2012

Module

Modules manage data and viewsThough may not have actual objects representing either

Data

View

Page 35: Scalable JavaScript Application Architecture 2012

Module

Widgets are reusable pieces of UIThey contain no business logic or data

Data

View

Widget

Widget

Widget

Page 36: Scalable JavaScript Application Architecture 2012

Module

Data

View

Menu

Tabs

Carousel

Widgets are reusable pieces of UIThey contain no business logic or data

Page 37: Scalable JavaScript Application Architecture 2012

Module

Widgets are part of a view toolkitAll modules can use widgets within their views

Data

View

Menu

Tabs

Carousel

ModuleData

View

Page 38: Scalable JavaScript Application Architecture 2012

Modules can’t do whatever they want to do their job

Page 39: Scalable JavaScript Application Architecture 2012

Modules are like little kidsThey need a strict set of rules so they don't get into trouble

flickr.com/photos/tedsblog/43433812/

Page 40: Scalable JavaScript Application Architecture 2012

Module RulesHands to yourself– Only call your own methods or those on the

sandbox– Don't access DOM elements outside of your box– Don't access non-native global objectsAsk, don't take– Anything else you need, ask the sandboxDon't leave your toys around– Don't create global objectsDon't talk to strangers– Don't directly reference other modules

Page 41: Scalable JavaScript Application Architecture 2012

Modules must stay within their own sandboxes

No matter how restrictive or uncomfortable it may seem

flickr.com/photos/madaise/3406217980/

Page 42: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Module Module

Page 43: Scalable JavaScript Application Architecture 2012

Sandbox

The sandbox ensures a consistent interfaceModules can rely on the methods to always be there

Page 44: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Module Module

Page 45: Scalable JavaScript Application Architecture 2012

Sandbox

ModuleModule

Module

Module Module

Modules only know the sandboxThe rest of the architecture doesn't exist to them

Page 46: Scalable JavaScript Application Architecture 2012

The sandbox also acts like a security guardKnows what the modules are allowed to access and do on the

framework

flickr.com/photos/heraklit/169566548/

Page 47: Scalable JavaScript Application Architecture 2012

Core.register("module-name", function(sandbox){

return { init: function(){

//not sure if I'm allowed... if (sandbox.iCanHazCheezburger()){ alert("thx u"); } },

destroy: function(){ //destructor }

};

});

Page 48: Scalable JavaScript Application Architecture 2012

Sandbox JobsConsistency– Interface must be dependableSecurity– Determine which parts of the framework a

module can accessCommunication– Translate module requests into core actions

Page 49: Scalable JavaScript Application Architecture 2012

Take the time to design the correct sandbox interface

It can't change later

Page 50: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Module Module

Page 51: Scalable JavaScript Application Architecture 2012

The application core manages modulesThat's it

ApplicationCore

Page 52: Scalable JavaScript Application Architecture 2012

aka Application Controller

ApplicationCore

Page 53: Scalable JavaScript Application Architecture 2012

The application core tells a module whenit should initialize and when it should

shutdownflickr.com/photos/bootbearwdc/

20817093/flickr.com/photos/bootbearwdc/

20810695/

Page 54: Scalable JavaScript Application Architecture 2012

Core = function(){ var moduleData = {};

return { register: function(moduleId, creator){ moduleData[moduleId] = { creator: creator, instance: null }; }, start: function(moduleId){ moduleData[moduleId].instance = moduleData[moduleId].creator(new Sandbox(this)); moduleData[moduleId].instance.init(); }, stop: function(moduleId){ var data = moduleData[moduleId]; if (data.instance){ data.instance.destroy(); data.instance = null; } } }}();

Page 55: Scalable JavaScript Application Architecture 2012

Core = function(){

return { //more code here... startAll: function(){ for (var moduleId in moduleData){ if (moduleData.hasOwnProperty(moduleId)){ this.start(moduleId); } } },

stopAll: function(){ for (var moduleId in moduleData){ if (moduleData.hasOwnProperty(moduleId)){ this.stop(moduleId); } } }, //more code here... };}();

Page 56: Scalable JavaScript Application Architecture 2012

//register modulesCore.register("module1", function(sandbox){ /*...*/ });Core.register("module2", function(sandbox){ /*...*/ });Core.register("module3", function(sandbox){ /*...*/ });Core.register("module4", function(sandbox){ /*...*/ });

//start the application by starting all modulesCore.startAll();

Page 57: Scalable JavaScript Application Architecture 2012

The application core manages communication between modules

flickr.com/photos/markhillary/353738538/

Page 58: Scalable JavaScript Application Architecture 2012
Page 59: Scalable JavaScript Application Architecture 2012

TimelineFilter = { changeFilter: function(filter){ Timeline.applyFilter(filter); }};

StatusPoster = { postStatus: function(status){ Timeline.post(status); }};

Timeline = { applyFilter: function(filter){ //implementation }, post: function(status){ //implementation }};

TightCoupling

TightCoupling

Page 60: Scalable JavaScript Application Architecture 2012

Core.register("timeline-filter", function(sandbox){

return { changeFilter: function(filter){ sandbox.notify({ type: "timeline-filter-change", data: filter }); } };});

Core.register("status-poster", function(sandbox){

return { postStatus: function(statusText){ sandbox.notify({ type: "new-status", data: statusText }); } };});

LooseCoupling

LooseCoupling

Page 61: Scalable JavaScript Application Architecture 2012

Core.register("timeline", function(sandbox){

return { init: function(){ sandbox.listen([ "timeline-filter-change", "post-status" ], this.handleNotification, this); },

handleNotification: function(note){ switch(note.type){ case "timeline-filter-change": this.applyFilter(note.data); return; case "post-status": this.post(note.data); return; } } };});

LooseCoupling

Page 62: Scalable JavaScript Application Architecture 2012

When modules are loosely coupled,removing a module doesn't break the

othersNo direct access to another module = no breaking should the module

disappear

Page 63: Scalable JavaScript Application Architecture 2012

The application core handles errorsUses available information to determine best course of action

flickr.com/photos/brandonschauer/3168761995/

Page 64: Scalable JavaScript Application Architecture 2012

Core = function(){

var moduleData = {}, debug = false; function createInstance(moduleId){ var instance = moduleData[moduleId].creator(new Sandbox(this)), name, method; if (!debug){ for (name in instance){ method = instance[name]; if (typeof method == "function"){ instance[name] = function(name, method){ return function(){ try { return method.apply(this, arguments);} catch(ex) {log(1, name + "(): " + ex.message);} }; }(name, method); } } }

return instance; }

//more code here

}();

Page 65: Scalable JavaScript Application Architecture 2012

Learn morehttp://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation

Page 66: Scalable JavaScript Application Architecture 2012

Application Core JobsManage module lifecycle– Tell modules when to start and stop doing their

jobEnable inter-module communication– Allow loose coupling between modules that are

related to one anotherGeneral error handling– Detect, trap, and report errors in the systemBe extensible– The first three jobs are not enough!

Page 67: Scalable JavaScript Application Architecture 2012

Why not?

Page 68: Scalable JavaScript Application Architecture 2012

Web applications changeOften in ways that you couldn't possibly anticipate

Page 69: Scalable JavaScript Application Architecture 2012

Plan for extension

Page 70: Scalable JavaScript Application Architecture 2012

Anything built for extension can never be obsolete

Extensions augment the capabilities of the core to keep it relevant and useful

flickr.com/photos/pointnshoot/1443575327/

Page 71: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Extension Extension

Module Module

Page 72: Scalable JavaScript Application Architecture 2012

What Extensions?• Error handling• Ajax communication• New module capabilities• General utilities• Anything!

Page 73: Scalable JavaScript Application Architecture 2012

Ajax communication comes in different forms

Tends to be tied to something available on the server

Page 74: Scalable JavaScript Application Architecture 2012

Response format

Request format

Entrypoint

Three parts must be in sync for Ajax to work

Modules shouldn't know anything about any of this

Page 75: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Extension Ajax/XML

Module Module

Page 76: Scalable JavaScript Application Architecture 2012

GET ?name=value&name=value

Response format

Request format

Entrypoint

<response> <status>ok|error</status> <data> <results> <result name="..." /> <result name="..." /> </results> </data></response>

/ajax

Page 77: Scalable JavaScript Application Architecture 2012

var xhr = new XMLHttpRequest();xhr.open("get", "/ajax?name=value", true);

xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if (xhr.status == 200 || xhr.status == 304){ var statusNode = xhr.responseXML.getElementsByTagName("status")[0], dataNode = xhr.responseXML.getElementsByTagName("data")[0];

if (statusNode.firstChild.nodeValue == "ok"){ handleSuccess(processData(dataNode)); } else { handleFailure(); } } else { handleFailure(); } }

};

xhr.send(null); Basic implementationLowest-level Ajax with XMLHttpRequest

Response format

Entrypoint

Request format

Page 78: Scalable JavaScript Application Architecture 2012

var id = Y.io("/ajax?name=value", { method: "get", on: { success: function(req){ var statusNode = req.responseXML.getElementsByTagName("status")[0], dataNode = req.responseXML.getElementsByTagName("data")[0]; if (statusNode.firstChild.nodeValue == "ok"){ handleSuccess(processData(dataNode)); } else { handleFailure(); } }, failure: function(req){ handleFailure(); } }});

Implementation using a libraryHides some of the ugliness but still tightly coupled to Ajax

implementation

Response format

Entrypoint

Request format

Library reference

Page 79: Scalable JavaScript Application Architecture 2012

var id = sandbox.request({ name: "value" }, { success: function(response){ handleSuccess(response.data); }, failure: function(response){ handleFailure(); }});

Implementation using sandboxPasses through to core - hides all Ajax communication details

Page 80: Scalable JavaScript Application Architecture 2012

Response format

Request format

Entrypoint

Ajax extension encapsulates all detailsAny of these three can change without affecting modules

Page 81: Scalable JavaScript Application Architecture 2012

Response format

Request format

Entrypoint

{ status: "ok|error", data: { results: [ "...", "..." ] }}

GET ?name=value&name=value /request

Page 82: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Extension Ajax/JSON

Module Module

Page 83: Scalable JavaScript Application Architecture 2012

Ajax Extension JobsHide Ajax communication details– Modules don't need to know any of itProvide common request interface– Modules use this interface to specify data to

send to the serverProvide common response interface– Modules use this interface to retrieve data from

the responseManage server failures– Modules only care if they got what they wanted

or not, don't care why

Page 84: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Base Library

ModuleModule

Module

Extension Extension

Module Module

Page 85: Scalable JavaScript Application Architecture 2012

Base Library

The base library provides basic functionality

Ironic, huh?

Page 86: Scalable JavaScript Application Architecture 2012
Page 87: Scalable JavaScript Application Architecture 2012

Most applications are too tightly coupledto the base library

Developers get upset when they can't touch the base library directly

flickr.com/photos/kartik_m/2724121901/

Page 88: Scalable JavaScript Application Architecture 2012

High-Performance JavaScript, OSCON 2007Joseph Smarr, Plaxo, Inc.

Page 89: Scalable JavaScript Application Architecture 2012

Learn morehttp://josephsmarr.com/2007/07/25/high-performance-javascript-oscon-2007/

Page 90: Scalable JavaScript Application Architecture 2012

Ideally, only the application core has any idea what base

library is being used

Page 91: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Dojo

ModuleModule

Module

Module Module

Page 92: Scalable JavaScript Application Architecture 2012

Sandbox

YUI

ModuleModule

Module

Module Module

ApplicationCore

Page 93: Scalable JavaScript Application Architecture 2012

Base Library JobsBrowser normalization– Abstract away differences in browsers with

common interfaceGeneral-purpose utilities– Parsers/serializers for XML, JSON, etc.– Object manipulation– DOM manipulation– Ajax communicationProvide low-level extensibility

Page 94: Scalable JavaScript Application Architecture 2012

Base Library

Extension Extension

Extension Extension

Sandbox

ModuleModule

Module

Module Module

ApplicationCore

Page 95: Scalable JavaScript Application Architecture 2012

Architecture Knowledge

Page 96: Scalable JavaScript Application Architecture 2012

Base Library

Extension Extension

Extension Extension

Sandbox

ModuleModule

Module

Module Module

ApplicationCore

Page 97: Scalable JavaScript Application Architecture 2012

Base Library

Only the base library knows which browseris being used

No other part of the architecture should need to know

Page 98: Scalable JavaScript Application Architecture 2012

ApplicationCore

Base Library

Only the application core knows whichbase library is being used

No other part of the architecture should need to know

Page 99: Scalable JavaScript Application Architecture 2012

Sandbox

ApplicationCore

Only the sandbox knows which application core

is being usedNo other part of the architecture should need to know

Page 100: Scalable JavaScript Application Architecture 2012

Sandbox

ModuleModule

Module

Module Module

The modules know nothing except thatthe sandbox exists

They have no knowledge of one another or the rest of the architecture

Page 101: Scalable JavaScript Application Architecture 2012

No part knows about the web application

Base Library

Extension Extension

Extension Extension

Sandbox

ModuleModule

Module

Module Module

ApplicationCore

Page 102: Scalable JavaScript Application Architecture 2012

Advantages

Page 103: Scalable JavaScript Application Architecture 2012

Multiple different applications can be created

with the same frameworkMinimize ramp-up time by reusing existing components

flickr.com/photos/kgoldendragon613/278240446/

Page 104: Scalable JavaScript Application Architecture 2012

Each part can be tested separatelyYou just need to verify that each is doing it's unique job

flickr.com/photos/misocrazy/151021636/

Page 105: Scalable JavaScript Application Architecture 2012

A scalable JavaScript architecture allows you to replace any block without fear of toppling the tower

flickr.com/photos/aku-ma/2424194422/

Page 106: Scalable JavaScript Application Architecture 2012

Implementations

Page 107: Scalable JavaScript Application Architecture 2012

https://github.com/legalbox/lb_js_scalableApp

Page 108: Scalable JavaScript Application Architecture 2012

http://scaleapp.org

Page 109: Scalable JavaScript Application Architecture 2012

http://tcorral.github.com/Hydra.js/

Page 110: Scalable JavaScript Application Architecture 2012

http://alanlindsay.me/kerneljs/

Page 111: Scalable JavaScript Application Architecture 2012

http://terrifically.org/

Page 112: Scalable JavaScript Application Architecture 2012

http://addyosmani.github.com/aura/

Page 113: Scalable JavaScript Application Architecture 2012

The End

Page 114: Scalable JavaScript Application Architecture 2012

Etcetera•My blog: nczonline.net•Twitter: @slicknet•These Slides: slideshare.net/nzakas