SlideShare a Scribd company logo
1 of 120
Download to read offline
IOC + Javascript




Brian Cavalier @briancavalier / John Hann @unscriptable
Who?
 Two back-end engineers who defected to the front-end
 The main characters behind cujo.js
What?
cujo.js
    Spring-like concepts, but not a port of Spring to Javascript
    Embraces Javascript's functional and prototypal roots
    Provides architectural tools for next-generation JavaScript
    applications

http://cujojs.com/
How?

    Less slides, please!


Moar awesum codez, plz!
Q&A at the end and during code demos!

Code demos: Monty Hall UI && TodoMVC
Recent project stats
    6 "HTML Pages"
    300+ Javascript modules
    100+ "View modules" each of which has:
        HTML templates
        CSS files
        i18n bundles
        test harnesses


Not including 3rd party modules!
Recent project stats
Manual dependency management is just not
feasible at this scale
Help!

    Larger, more complex apps require carefully crafted rigorous
    architecture, patterns, and code organization.


-- Brian
IOC
 We know from Spring, good architectural plumbing helps to
 manage complexity
 Javascript is no exception
 In the browser and on the server
Can we ...?
  Build smaller modules that are easier to maintain and test
  Separate configuration and connection from application logic
  Glue it all back together
Apply IOC concepts in Javascript
  Declarative component creation
  Lifecycle management
  Configuration
  Dependency injection
  AOP
IOC for front-end Javascript
  What might it look like?
     XML? Not very Javascript-ish
     Annotations? No existing infrastructure, need to parse source

  Javascript is flexible: Can we work with the language?
Components
The first thing we need is a way to build
components
AMD
Asynchronous
Module
Definition
Three main parts
  Module format
  Run-time loader
  Build-time compiler (recommended for production)
AMD
Designed with browser environments in mind
   Loads asynchronously
   No parsing or transpiling needed
   Built-in closure
   Loads other resource types via plugins
Who supports it?
  dojo 1.7+
  cujo.js
  jQuery 1.7+
  MooTools 2+
  Lodash and many, many others
define()
AMD mandates a single, standardized global
function.
define();
define()
define(factory);
define(dependencyList, factory);
AMD Module variants
"Standard" AMD
define(['when', 'pkg/mod'], function (when, mod) {
    // use the dependencies, return your module:
    return {};
});
AMD Module variants
AMD-wrapped CommonJS
/* no deps, factory params != 0 */
define(function (require, exports, module) {
    // sync, r-value require
    var when = require('when');
    // decorate your exports object
    exports.bestUtilEver = function (stuff) {
        return when(stuff);
    };
});
AMD Module variants
AMD-wrapped Node
/* no deps, factory params != 0 */
define(function (require, exports, module) {
    // sync, r-value require
    var when = require('when');
    // declare your exports
    module.exports = function bestUtilEver (stuff) {
        return when(stuff);
    };
});
UMD
Universal
Module
Format
UMD
Boilerplate to sniff environment and export
module correctly
   AMD + legacy globals
   AMD + CommonJS
   AMD + Node
   AMD + Node + legacy globals
   ... etc.
UMD Module variants
AMD + Node (our favorite)
(function (define) {

define(function (require) {
    // module code goes here
});

})(
    typeof define === 'function' && define.amd
        ? define
        : function (factory) { module.exports =
factory(require); }
);
UMD: AMD + Node
app/game/controller
(code demo)
Bootstrapping an AMD app
"The other global"
   curl();
   requirejs();
   require(); (global require is problematic!)
Bootstrapping an AMD app
run.js
(code demo)
AMD Plugins
  Same dependency mechanism
  Non-AMD resources
  text! - HTML Templates and other text
  css! and link! - stylesheets
  i18n! - localization
  Google Maps
  JSON data, etc.
AMD Plugins
Can do even more powerful things
   wire! - wire.js IOC container integration
   has! - has.js feature detection and conditional module loading
   cs! - loads and transpiles Coffeescript
Plugins
app/main
(code demo)
CommonJS Module format
 Every file is a module with its own scope
 No closure, no factory, no define()
 require, exports, and module are “free variables”
curl.js <3 CJS!
"Compile to AMD"
Node !== CommonJS
 exports === this
 exports === module.exports
WTF
I know what you’re thinking
   Which one?!?
   Why are there 2 (3?) module formats, and how am I supposed to
   know which one to pick?!?!!1
It gets worse
ES Harmony modules are coming
Problem: Harmony is an authoring format. It doesn't handle:

    Dependency management
    Packaging, version management
    Compiling, concatenation
    Non-harmony resources (CSS, HTML, JSONP, etc.)
Relax
Relax
Your code is safe!
AMD consumes CJS and (soon) Harmony modules
Evolution
// curl.js config (coming soon!)
packages: [
    { name: 'node-thing', location: 'lib/node/thing', main:
'./main', transform: ['curl/transform/cjsm11'] },
    { name: 'cs-thing', location: 'lib/cs/thing', main:
'./init', transform: ['curl/transform/coffee'] },
    { name: 'future-thing', location: 'lib/harmony/stuff',
main: './main', transform: ['curl/transform/es7'] },
    ...
],
CommonJS Modules today
monty-hall-ui/cjsm (branch)
Same modules written as CommonJS Modules/1.1, but unwrapped!

(code demo)
Micro-modules
Smaller is better!
Micro-modules
Single-function modules are
   more reusable
   easier to test
   easier to discover
Hazard!
https://github.com/dojo/dijit/blob/ef9e7bf5df60a8a74f7e7a7eeaf859b9df3b0
Hazard!
How do we avoid dependency hell when using micro-modules?
Connections
  The lines in your box-and-line diagrams
  Can be just as important as the stuff you put inside the boxes
  Unfortunately, we end up putting the lines inside the boxes
AMD
 Maintains good separation of concerns
 But more like Java import, which isn't necessarily right for all
 situations.
Example
define(['dojo/store/JsonRest'], function(JsonRest) {
    function Controller() {
        this.datastore = new JsonRest({ target:
"mycart/items/" });
    }

      Controller.prototype = {
          addItem: function(thing) {
              return this.datastore.put(thing);
          },
          // ...
      }

      return Controller;
});
What's that smell?
  this.datastore = new JsonRest(..) is essentially a
  line inside our Controller box
  How would you unit test it?
  Could you use this with another type of data store?
  Multiple instances, each with a different type of store?
      different target URL?
Refactor
define(function() { // No AMD deps!

      function Controller(datastore) {
          this.datastore = datastore;
      }

      Controller.prototype = {
          addItem: function(thing) {
              return this.datastore.put(thing);
          },
          // ...
      }

      return Controller;
});
Or Similarly
define(function() { // No AMD deps!

      // Rely on the IOC Container to beget new instances
      return {
          datastore: null,
          addItem: function(thing) {
               return this.datastore.put(thing);
          },
          // ...
      };
});
What did we do?
  Decoupled the concrete JsonRest implementation
  Refactored to rely on a datastore interface
      Even though the interface is implicit
What did we accomplish?
  Moved the responsibility of drawing the line out of the
  Controller.
  Made Controller more flexible and easier to test
But we created a question
Who provides the datastore?
We know what to do
Dependency Injection in the Application
Composition Layer
DI & Application Composition
define({
    controller: {
         create: 'myApp/controller',
         properties: {
             datastore: { $ref: 'datastore' }
         }
    },

      datastore: {
          create: 'dojo/store/JsonRest',
          properties: {
              target: 'things/'
          }
      }
});
The DOM
 Obviously, working with the DOM is a necessity in front-end
 Javascript
 Similar problems: lines inside the boxes
Example
define(['some/domLib'], function(domLib) {

      function ItemView() {
          this.domNode = domLib.byId('item-list');
      }

      ItemView.prototype = {
          render: function() {
              // Render into this.domNode
          }
      }

      return ItemView;
});
That same smell
  Depends on an HTML id, and a DOM selector library
  Changing the HTML could break the JS
  Have to mock the DOM selector lib
Refactor
define(function() { // No AMD deps!

      function ItemView(domNode) {
          this.domNode = domNode;
      }

      ItemView.prototype = {
          render: function() {
              // Render into this.domNode
          }
      }

      return ItemView;
});
Better
  Decouples DOM selection mechanism
  and HTML: Can inject a different DOM node w/o changing
  ItemView's source.
DOM & Application Composition
define({
    itemView: {
         create: {
             module: 'myApp/ItemView',
             args: { $ref: 'dom!item-list' }
         }
    },

      plugins: [
          { module: 'wire/dom' }
          // or { module: 'wire/sizzle' }
          // or { module: 'wire/dojo/dom' }
          // or { module: 'wire/jquery/dom' }
      ]
});
DOM Events
define(['some/domLib', some/domEventsLib'], function(domLib,
domEventsLib) {

      function Controller() {
          domEventsLib.on('click', domLib.byId('the-button'),
              this.addItem.bind(this));
      }

      Controller.prototype = {
          addItem: function(domEvent) {
              // Add the item to the cart
          }
      }

      return Controller;
});
That same smell, only worse!
  Depends on:
     hardcoded event type,
     HTML id,
     DOM selection lib
     DOM events lib

  More mocking
Refactor
define(function() { // No AMD deps!

      function Controller() {}

      Controller.prototype = {
          addItem: function(domEvent) {
              // Update the thing
          }
      }

      return Controller;
});
Better
  Only cares about a general event: "Now it's time to add the item
  to the cart"
  Different/multiple event types on multiple DOM nodes
  No hardcoded DOM selector: multiple Controller instances
  Only have to mock the domEvent, then call addItem
DOM Events & App Composition
itemViewRoot: { $ref: 'dom.first!.item-view'},

controller: {
    create: 'myApp/Controller',
    on: {
        itemViewRoot: {
            'click:button.add': 'addItem'
        }
    }
},

plugins: [
    { module: 'wire/on' }
    // or { module: 'wire/dojo/on' }
    // or { module: 'wire/jquery/on' },

    { module: 'wire/dom' }
]
JS-to-JS Connections
Can components collaborate in a more loosely
coupled way than DI?
Synthetic events
  Javascript methods act like events
  "Connect" methods together
  Neither component has knowledge of the other
Example
Controller.prototype.addItem = function(domEvent) {...}

CartCountView.prototype.incrementCount = function() {...}
Using DI
controller: {
    create: 'myApp/cart/Controller',
    properties: {
        cartCountView: { $ref: 'cartCountView' }
    }
},

cartCountView: {
    create: 'myApp/cart/CartCountView'
}
Things we can improve
  Controller now dependent on CartCountView interface
  Have to mock CartCountView to unit test Controller
  What if there are other times we'd like to update the cart count?
Synthetic event connection
controller: {
    create: 'myApp/cart/Controller'
},

cartCountView: {
    create: 'myApp/cart/CartCountView',
    connect: {
        'controller.addItem': 'incrementCount'
    }
}
Better
  Application Composition layer makes the connection
  Controller no longer dependent on CartCountView
  Neither component needs to be re-unit tested when making this
  connection
      Nor if the connection is removed later
      Only need to re-run functional tests

  Could completely remove CartCountView simply by cutting it
  out of the Application Composition spec
Still not perfect
What if addItem throws or fails in some way?
AOP Connections
controller: {
    create: 'myApp/cart/Controller'
},

cartCountView: {
    create: 'myApp/cart/CartCountView',
    afterReturning: {
        'controller.addItem': 'incrementCount'
    }
}
Closer
  Only increment count on success
  What about failures?
AOP Connections
controller: {
    create: 'myApp/cart/Controller',
    afterReturning: {
        'addItem': 'cartCountView.incrementCount'
    },
    afterThrowing: {
        'addItem': 'someOtherComponent.showError'
    }
},

cartCountView: {
    create: 'myApp/cart/CartCountView'
},

someOtherComponent: // ...
Better! But not quite there
  More decoupled, testable, refactorable
  Still a level of coupling we can remove
Coupled parameters
function Controller() {}

Controller.prototype = {
    addItem: function(domEvent) {
        // How to find the item data, in order to add it?
    }
}
Coupled parameters
  Controller receives a domEvent, but must locate the associated
  data to update
  Need DOM traversal, and understand the DOM structure
     data id or hash key hiding in a DOM attribute?

  Have to mock for unit testing
Coupled parameters
Controller only really cares about the item
Refactor
function Controller() {}

Controller.prototype = {
    addItem: function(item) {
        // Just add it
    }
}
Transform connections
Connections that can, um, transform data!
Transform function
define(function() {

      // Encapsulate the work of finding the item
      return function findItemFromEvent(domEvent) {
          // Find the item, then
          return item;
      }

});
App Composition
itemList: { $ref: 'dom.first!.item-list'},

findItem: { module: 'myApp/data/findItemFromEvent' }

controller: {
    create: 'myApp/Controller',
    on: {
        itemList: {
            'click:button.add': 'findItem | addItem'
        }
    }
}
Ahhh, at last
  Controller is easier to unit test
  Algorithm for finding the thing
      can also be unit tested separately and more easily
      can be changed separately from Controller
      can be reused in other parts of the app
Awesome, we're done, right?
Not quite ...
What about asynchrony?
  Occurs most often at component and system boundaries
  Hence, connections often need to be asynchronous
     Canonical example: XHR
Example
Controller.prototype.addItem = function(item, callback) {...}

CartCountView.prototype.incrementCount = function() {...}
Example
controller: {
    create: 'myApp/cart/Controller',
    afterReturning: {
        'addItem': 'cartCountView.incrementCount'
    },
    afterThrowing: {
        'addItem': 'someOtherComponent.showError'
    }
},

cartCountView: {
    create: 'myApp/cart/CartCountView'
},

someOtherComponent: // ...
Uh oh
  Moved the function result from the return value to the parameter
  list
  Since addItem can't return anything, afterReturning doesn't
  work!
  And how do we provide the callback?
Brief, asynchronous detour
  Javascript is designed around a single-threaded event loop
  Browser DOM events and network I/O are async
  SSJS platforms (Node, RingoJS, etc) are built around async I/O
  AMD module loading is async--the A in AMD!
Callbacks
The typical solution is callbacks, aka
"Continuation Passing"
Example
// You wish!
var content = xhr('GET', '/stuff');
Add callback and error handler
xhr('GET', '/stuff',
    function(content) {
        // do stuff
    },
    function(error) {
        // handle error
    }
);
Callback infestation
// It's turtles all the way *up*
function getStuff(handleContent, handleError) {
    xhr('GET', '/stuff',
        function(content) {
            // transform content somehow, then
            // (what happens if this throws?)
            handleContent(content);
        },
        function(error) {
            // Maybe parse error, then
            // (what happens if THIS throws?!?)
            handleError(error);
        }
    );
}
Async is messy
  Code quickly becomes deeply nested and harder to reason
  about
  Familiar programming idioms don't work
     It's upside-down: Values and errors flow down the stack now
     rather than up.
     Functions are no longer easily composable: g(f(x)) doesn't
     work anymore
     try/catch/finally, or something reasonably similar is impossible

  Callback and errback parameters must be added to every
  function signature that might eventually lead to an
  asynchronous operation
  Coordinating multiple async tasks is a pain
Promises
  Synchronization construct
  Not a new idea
  Similar to java.util.concurrent.Future
  Placeholder for a result or error that will materialize later.
Example
Return a promise, into which the content, or an error, will
materialize.

function getStuff() {
    var promise = xhr('GET', '/stuff');
    return promise;
}
Promises
  Restore call-and-return semantics
      Move function results back to the return value
      Remove callback function signature pollution

  Provide an async analog to exception propagation
  It's right-side up
More about Promises
  http://en.wikipedia.org/wiki/Futures_and_promises
  http://blog.briancavalier.com/async-programming-part-1-its-
  messy
  http://blog.briancavalier.com/async-programming-part-2-
  promises
  http://github.com/cujojs/when/wiki
  http://wiki.commonjs.org/wiki/Promises/A
Promises
  Several proposed standards
  Promises/A defacto standard
      cujo.js: when.js
      Dojo: dojo/Deferred
      jQuery: $.Deferred (well, close enough)
      Q
      soon YUI, Ember
IOC + Promises
  Promises/A is an integration standard for asynchrony
  IOC is about gluing components together so they can
  collaborate
  Sounds like a match!
Refactor to return a promise
Controller.prototype.addItem = function(item) {
    // Asynchronously add the item, then
    return promise;
}
Promise-aware AOP
controller: {
    create: 'myApp/cart/Controller',
    afterResolving: {
        'addItem': 'cartCountView.incrementCount'
    },
    afterRejecting: {
        'addItem': 'someOtherComponent.showError'
    }
},

cartCountView: {
    create: 'myApp/cart/CartCountView'
},

someOtherComponent: // ...
Win
 Count will only be incremented after the item has been added
 successfully!
 If adding fails, show the error
Async without async
  Promise-aware AOP for async connections
  AMD loaders manage async module loading and dependency
  graph resolution.
  Promise-aware IOC container:
      Integrate with AMD loader to load modules used in
      application composition specs.
      Async component creation: constructor or plain function can
      return a promise
      Async DI: component references are injected as promises for
      the components resolve
      Component startup/shutdown methods can return a promise
Connections
  Implement application logic in components
  Connect components non-invasively via Application
  Composition
     DI, events (DOM and JS), AOP, Promise-aware AOP

  Adapt APIs by transforming data along connections
  Enjoy the easier testing and refactoring :)
Organize!
Components, components, components
    the "file tree on the left" actually became useful!


-- Brian
Organize!
Divide your app into feature areas
What are the things you talk about when you talk about the app?
Organize!
app/
(code demo)
Case: View-component
View-components consist of
   HTML(5) template (keep it simple!)
   CSS file (structural bits of OOCSS/SMACCS)
   i18n file(s)
   javascript controller (optional)
   test harness (also for design)
   any assets necessary for rendering
   any view-specific data transforms, validations, etc.
   wire spec (optional)
Case: View-component
app/instructions
(code demo)
Testing visual components
How?????
Testing visual components
Double-duty test harnesses
   Fixture for creating HTML and designing CSS
   Harness for user-driven tests
   Harness for unit tests
Testing visual components
Double-duty test harnesses
(code demo)
Unit tests
  Smaller is better
  Fewer dependencies means fewer mocks!
Unit tests
(code demo)
cujo.js
  AMD Modules - curl & cram
  IOC & Application Composition - wire
  Promises/A - when
  AOP - meld
  ES5 - poly
  Data binding - cola (alpha)
Alternatives
  AMD Modules - RequireJS, Dojo, lsjs, BravoJS
  IOC - AngularJS
  Promises - Q, Dojo
  AOP - Dojo
  ES5 - es5shim
  Data binding - Backbone, and everyone else
cujo.js
Get it at http://cujojs.com

Discussions, Announcements, Questions, etc.

https://groups.google.com/d/forum/cujojs

More Related Content

What's hot

From YUI3 to K2
From YUI3 to K2From YUI3 to K2
From YUI3 to K2kaven yan
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101ygv2000
 
CSharp Advanced L05-Attributes+Reflection
CSharp Advanced L05-Attributes+ReflectionCSharp Advanced L05-Attributes+Reflection
CSharp Advanced L05-Attributes+ReflectionMohammad Shaker
 
JavaScript Modules Done Right
JavaScript Modules Done RightJavaScript Modules Done Right
JavaScript Modules Done RightMariusz Nowak
 
Rich Internet Applications con JavaFX e NetBeans
Rich Internet Applications  con JavaFX e NetBeans Rich Internet Applications  con JavaFX e NetBeans
Rich Internet Applications con JavaFX e NetBeans Fabrizio Giudici
 
Difference between java script and jquery
Difference between java script and jqueryDifference between java script and jquery
Difference between java script and jqueryUmar Ali
 
JavaScript: DOM and jQuery
JavaScript: DOM and jQueryJavaScript: DOM and jQuery
JavaScript: DOM and jQuery維佋 唐
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An IntroductionManvendra Singh
 
JavaScript
JavaScriptJavaScript
JavaScriptSunil OS
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design PatternsScalable JavaScript Design Patterns
Scalable JavaScript Design PatternsAddy Osmani
 
web2py:Web development like a boss
web2py:Web development like a bossweb2py:Web development like a boss
web2py:Web development like a bossFrancisco Ribeiro
 
Javascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to JavascriptJavascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to JavascriptLivingston Samuel
 
Introduction to Polymer and Firebase - Simon Gauvin
Introduction to Polymer and Firebase - Simon GauvinIntroduction to Polymer and Firebase - Simon Gauvin
Introduction to Polymer and Firebase - Simon GauvinSimon Gauvin
 
Hibernate
Hibernate Hibernate
Hibernate Sunil OS
 
Dynamic Application Development by NodeJS ,AngularJS with OrientDB
Dynamic Application Development by NodeJS ,AngularJS with OrientDBDynamic Application Development by NodeJS ,AngularJS with OrientDB
Dynamic Application Development by NodeJS ,AngularJS with OrientDBApaichon Punopas
 

What's hot (20)

From YUI3 to K2
From YUI3 to K2From YUI3 to K2
From YUI3 to K2
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101
 
CSharp Advanced L05-Attributes+Reflection
CSharp Advanced L05-Attributes+ReflectionCSharp Advanced L05-Attributes+Reflection
CSharp Advanced L05-Attributes+Reflection
 
Zend Framework
Zend FrameworkZend Framework
Zend Framework
 
JavaScript Modules Done Right
JavaScript Modules Done RightJavaScript Modules Done Right
JavaScript Modules Done Right
 
Rich Internet Applications con JavaFX e NetBeans
Rich Internet Applications  con JavaFX e NetBeans Rich Internet Applications  con JavaFX e NetBeans
Rich Internet Applications con JavaFX e NetBeans
 
Difference between java script and jquery
Difference between java script and jqueryDifference between java script and jquery
Difference between java script and jquery
 
JavaScript: DOM and jQuery
JavaScript: DOM and jQueryJavaScript: DOM and jQuery
JavaScript: DOM and jQuery
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An Introduction
 
JavaScript
JavaScriptJavaScript
JavaScript
 
JavaScript
JavaScriptJavaScript
JavaScript
 
Jet presentation
Jet presentationJet presentation
Jet presentation
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design PatternsScalable JavaScript Design Patterns
Scalable JavaScript Design Patterns
 
web2py:Web development like a boss
web2py:Web development like a bossweb2py:Web development like a boss
web2py:Web development like a boss
 
Javascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to JavascriptJavascript session 01 - Introduction to Javascript
Javascript session 01 - Introduction to Javascript
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 
Introduction to Polymer and Firebase - Simon Gauvin
Introduction to Polymer and Firebase - Simon GauvinIntroduction to Polymer and Firebase - Simon Gauvin
Introduction to Polymer and Firebase - Simon Gauvin
 
React
React React
React
 
Hibernate
Hibernate Hibernate
Hibernate
 
Dynamic Application Development by NodeJS ,AngularJS with OrientDB
Dynamic Application Development by NodeJS ,AngularJS with OrientDBDynamic Application Development by NodeJS ,AngularJS with OrientDB
Dynamic Application Development by NodeJS ,AngularJS with OrientDB
 

Viewers also liked

5 formularios - javascript
5   formularios - javascript5   formularios - javascript
5 formularios - javascriptcarlos_hueyta
 
CHI 2009 Highlights
CHI 2009 HighlightsCHI 2009 Highlights
CHI 2009 Highlightsfrog
 
Should We Use Community IOC 2010
Should We Use Community IOC 2010Should We Use Community IOC 2010
Should We Use Community IOC 2010Nancy Wright White
 
Sport Research and Cyberpsychology
Sport Research and CyberpsychologySport Research and Cyberpsychology
Sport Research and CyberpsychologyAmarach Research
 
Ucl injury study brusells 2014 05-01
Ucl injury study brusells 2014 05-01Ucl injury study brusells 2014 05-01
Ucl injury study brusells 2014 05-01JanEkstrand
 
GUIDE: IOC Marketing Media 2012
GUIDE: IOC Marketing Media 2012GUIDE: IOC Marketing Media 2012
GUIDE: IOC Marketing Media 2012Laia Gilibets
 
Report writting by Abhishek & seenu
Report writting by Abhishek & seenuReport writting by Abhishek & seenu
Report writting by Abhishek & seenuSonu Choudhary
 

Viewers also liked (9)

5 formularios - javascript
5   formularios - javascript5   formularios - javascript
5 formularios - javascript
 
CHI 2009 Highlights
CHI 2009 HighlightsCHI 2009 Highlights
CHI 2009 Highlights
 
Should We Use Community IOC 2010
Should We Use Community IOC 2010Should We Use Community IOC 2010
Should We Use Community IOC 2010
 
Inmunidad
InmunidadInmunidad
Inmunidad
 
Sport Research and Cyberpsychology
Sport Research and CyberpsychologySport Research and Cyberpsychology
Sport Research and Cyberpsychology
 
Ucl injury study brusells 2014 05-01
Ucl injury study brusells 2014 05-01Ucl injury study brusells 2014 05-01
Ucl injury study brusells 2014 05-01
 
GUIDE: IOC Marketing Media 2012
GUIDE: IOC Marketing Media 2012GUIDE: IOC Marketing Media 2012
GUIDE: IOC Marketing Media 2012
 
Report writting by Abhishek & seenu
Report writting by Abhishek & seenuReport writting by Abhishek & seenu
Report writting by Abhishek & seenu
 
8 Tips for an Awesome Powerpoint Presentation
8 Tips for an Awesome Powerpoint Presentation8 Tips for an Awesome Powerpoint Presentation
8 Tips for an Awesome Powerpoint Presentation
 

Similar to IOC + Javascript

Modules and EmbedJS
Modules and EmbedJSModules and EmbedJS
Modules and EmbedJSJens Arps
 
Advanced Node.JS Meetup
Advanced Node.JS MeetupAdvanced Node.JS Meetup
Advanced Node.JS MeetupLINAGORA
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLsintelliyole
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
JavaScript Modules in Practice
JavaScript Modules in PracticeJavaScript Modules in Practice
JavaScript Modules in PracticeMaghdebura
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.jsVikash Singh
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.jsChris Cowan
 
Webpack: your final module bundler
Webpack: your final module bundlerWebpack: your final module bundler
Webpack: your final module bundlerAndrea Giannantonio
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS ArchitectureEyal Vardi
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS InternalEyal Vardi
 
Warsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - WebpackWarsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - WebpackRadosław Rosłaniec
 
uRequire@greecejs: An introduction to http://uRequire.org
uRequire@greecejs: An introduction to http://uRequire.orguRequire@greecejs: An introduction to http://uRequire.org
uRequire@greecejs: An introduction to http://uRequire.orgAgelos Pikoulas
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.jsAdrien Guéret
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Developing node-mdb: a Node.js - based clone of SimpleDB
Developing node-mdb: a Node.js - based clone of SimpleDBDeveloping node-mdb: a Node.js - based clone of SimpleDB
Developing node-mdb: a Node.js - based clone of SimpleDBRob Tweed
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsAdégòkè Obasá
 

Similar to IOC + Javascript (20)

RequireJS
RequireJSRequireJS
RequireJS
 
Modules and EmbedJS
Modules and EmbedJSModules and EmbedJS
Modules and EmbedJS
 
Advanced Node.JS Meetup
Advanced Node.JS MeetupAdvanced Node.JS Meetup
Advanced Node.JS Meetup
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
JavaScript Modules in Practice
JavaScript Modules in PracticeJavaScript Modules in Practice
JavaScript Modules in Practice
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
 
Webpack: your final module bundler
Webpack: your final module bundlerWebpack: your final module bundler
Webpack: your final module bundler
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
node.js.pptx
node.js.pptxnode.js.pptx
node.js.pptx
 
Warsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - WebpackWarsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - Webpack
 
uRequire@greecejs: An introduction to http://uRequire.org
uRequire@greecejs: An introduction to http://uRequire.orguRequire@greecejs: An introduction to http://uRequire.org
uRequire@greecejs: An introduction to http://uRequire.org
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Developing node-mdb: a Node.js - based clone of SimpleDB
Developing node-mdb: a Node.js - based clone of SimpleDBDeveloping node-mdb: a Node.js - based clone of SimpleDB
Developing node-mdb: a Node.js - based clone of SimpleDB
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web Apps
 

Recently uploaded

WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dashnarutouzumaki53779
 

Recently uploaded (20)

WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dash
 

IOC + Javascript

  • 1. IOC + Javascript Brian Cavalier @briancavalier / John Hann @unscriptable
  • 2. Who? Two back-end engineers who defected to the front-end The main characters behind cujo.js
  • 3. What? cujo.js Spring-like concepts, but not a port of Spring to Javascript Embraces Javascript's functional and prototypal roots Provides architectural tools for next-generation JavaScript applications http://cujojs.com/
  • 4. How? Less slides, please! Moar awesum codez, plz! Q&A at the end and during code demos! Code demos: Monty Hall UI && TodoMVC
  • 5. Recent project stats 6 "HTML Pages" 300+ Javascript modules 100+ "View modules" each of which has: HTML templates CSS files i18n bundles test harnesses Not including 3rd party modules!
  • 6. Recent project stats Manual dependency management is just not feasible at this scale
  • 7. Help! Larger, more complex apps require carefully crafted rigorous architecture, patterns, and code organization. -- Brian
  • 8. IOC We know from Spring, good architectural plumbing helps to manage complexity Javascript is no exception In the browser and on the server
  • 9. Can we ...? Build smaller modules that are easier to maintain and test Separate configuration and connection from application logic Glue it all back together
  • 10. Apply IOC concepts in Javascript Declarative component creation Lifecycle management Configuration Dependency injection AOP
  • 11. IOC for front-end Javascript What might it look like? XML? Not very Javascript-ish Annotations? No existing infrastructure, need to parse source Javascript is flexible: Can we work with the language?
  • 12. Components The first thing we need is a way to build components
  • 14. Three main parts Module format Run-time loader Build-time compiler (recommended for production)
  • 15. AMD Designed with browser environments in mind Loads asynchronously No parsing or transpiling needed Built-in closure Loads other resource types via plugins
  • 16. Who supports it? dojo 1.7+ cujo.js jQuery 1.7+ MooTools 2+ Lodash and many, many others
  • 17. define() AMD mandates a single, standardized global function. define();
  • 19. AMD Module variants "Standard" AMD define(['when', 'pkg/mod'], function (when, mod) { // use the dependencies, return your module: return {}; });
  • 20. AMD Module variants AMD-wrapped CommonJS /* no deps, factory params != 0 */ define(function (require, exports, module) { // sync, r-value require var when = require('when'); // decorate your exports object exports.bestUtilEver = function (stuff) { return when(stuff); }; });
  • 21. AMD Module variants AMD-wrapped Node /* no deps, factory params != 0 */ define(function (require, exports, module) { // sync, r-value require var when = require('when'); // declare your exports module.exports = function bestUtilEver (stuff) { return when(stuff); }; });
  • 23. UMD Boilerplate to sniff environment and export module correctly AMD + legacy globals AMD + CommonJS AMD + Node AMD + Node + legacy globals ... etc.
  • 24. UMD Module variants AMD + Node (our favorite) (function (define) { define(function (require) { // module code goes here }); })( typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); } );
  • 25. UMD: AMD + Node app/game/controller (code demo)
  • 26. Bootstrapping an AMD app "The other global" curl(); requirejs(); require(); (global require is problematic!)
  • 27. Bootstrapping an AMD app run.js (code demo)
  • 28. AMD Plugins Same dependency mechanism Non-AMD resources text! - HTML Templates and other text css! and link! - stylesheets i18n! - localization Google Maps JSON data, etc.
  • 29. AMD Plugins Can do even more powerful things wire! - wire.js IOC container integration has! - has.js feature detection and conditional module loading cs! - loads and transpiles Coffeescript
  • 31. CommonJS Module format Every file is a module with its own scope No closure, no factory, no define() require, exports, and module are “free variables”
  • 33. Node !== CommonJS exports === this exports === module.exports
  • 34. WTF I know what you’re thinking Which one?!? Why are there 2 (3?) module formats, and how am I supposed to know which one to pick?!?!!1
  • 35. It gets worse ES Harmony modules are coming Problem: Harmony is an authoring format. It doesn't handle: Dependency management Packaging, version management Compiling, concatenation Non-harmony resources (CSS, HTML, JSONP, etc.)
  • 36. Relax
  • 37. Relax Your code is safe! AMD consumes CJS and (soon) Harmony modules
  • 38. Evolution // curl.js config (coming soon!) packages: [ { name: 'node-thing', location: 'lib/node/thing', main: './main', transform: ['curl/transform/cjsm11'] }, { name: 'cs-thing', location: 'lib/cs/thing', main: './init', transform: ['curl/transform/coffee'] }, { name: 'future-thing', location: 'lib/harmony/stuff', main: './main', transform: ['curl/transform/es7'] }, ... ],
  • 39. CommonJS Modules today monty-hall-ui/cjsm (branch) Same modules written as CommonJS Modules/1.1, but unwrapped! (code demo)
  • 41. Micro-modules Single-function modules are more reusable easier to test easier to discover
  • 43. Hazard! How do we avoid dependency hell when using micro-modules?
  • 44. Connections The lines in your box-and-line diagrams Can be just as important as the stuff you put inside the boxes Unfortunately, we end up putting the lines inside the boxes
  • 45. AMD Maintains good separation of concerns But more like Java import, which isn't necessarily right for all situations.
  • 46. Example define(['dojo/store/JsonRest'], function(JsonRest) { function Controller() { this.datastore = new JsonRest({ target: "mycart/items/" }); } Controller.prototype = { addItem: function(thing) { return this.datastore.put(thing); }, // ... } return Controller; });
  • 47. What's that smell? this.datastore = new JsonRest(..) is essentially a line inside our Controller box How would you unit test it? Could you use this with another type of data store? Multiple instances, each with a different type of store? different target URL?
  • 48. Refactor define(function() { // No AMD deps! function Controller(datastore) { this.datastore = datastore; } Controller.prototype = { addItem: function(thing) { return this.datastore.put(thing); }, // ... } return Controller; });
  • 49. Or Similarly define(function() { // No AMD deps! // Rely on the IOC Container to beget new instances return { datastore: null, addItem: function(thing) { return this.datastore.put(thing); }, // ... }; });
  • 50. What did we do? Decoupled the concrete JsonRest implementation Refactored to rely on a datastore interface Even though the interface is implicit
  • 51. What did we accomplish? Moved the responsibility of drawing the line out of the Controller. Made Controller more flexible and easier to test
  • 52. But we created a question Who provides the datastore?
  • 53. We know what to do Dependency Injection in the Application Composition Layer
  • 54. DI & Application Composition define({ controller: { create: 'myApp/controller', properties: { datastore: { $ref: 'datastore' } } }, datastore: { create: 'dojo/store/JsonRest', properties: { target: 'things/' } } });
  • 55. The DOM Obviously, working with the DOM is a necessity in front-end Javascript Similar problems: lines inside the boxes
  • 56. Example define(['some/domLib'], function(domLib) { function ItemView() { this.domNode = domLib.byId('item-list'); } ItemView.prototype = { render: function() { // Render into this.domNode } } return ItemView; });
  • 57. That same smell Depends on an HTML id, and a DOM selector library Changing the HTML could break the JS Have to mock the DOM selector lib
  • 58. Refactor define(function() { // No AMD deps! function ItemView(domNode) { this.domNode = domNode; } ItemView.prototype = { render: function() { // Render into this.domNode } } return ItemView; });
  • 59. Better Decouples DOM selection mechanism and HTML: Can inject a different DOM node w/o changing ItemView's source.
  • 60. DOM & Application Composition define({ itemView: { create: { module: 'myApp/ItemView', args: { $ref: 'dom!item-list' } } }, plugins: [ { module: 'wire/dom' } // or { module: 'wire/sizzle' } // or { module: 'wire/dojo/dom' } // or { module: 'wire/jquery/dom' } ] });
  • 61. DOM Events define(['some/domLib', some/domEventsLib'], function(domLib, domEventsLib) { function Controller() { domEventsLib.on('click', domLib.byId('the-button'), this.addItem.bind(this)); } Controller.prototype = { addItem: function(domEvent) { // Add the item to the cart } } return Controller; });
  • 62. That same smell, only worse! Depends on: hardcoded event type, HTML id, DOM selection lib DOM events lib More mocking
  • 63. Refactor define(function() { // No AMD deps! function Controller() {} Controller.prototype = { addItem: function(domEvent) { // Update the thing } } return Controller; });
  • 64. Better Only cares about a general event: "Now it's time to add the item to the cart" Different/multiple event types on multiple DOM nodes No hardcoded DOM selector: multiple Controller instances Only have to mock the domEvent, then call addItem
  • 65. DOM Events & App Composition itemViewRoot: { $ref: 'dom.first!.item-view'}, controller: { create: 'myApp/Controller', on: { itemViewRoot: { 'click:button.add': 'addItem' } } }, plugins: [ { module: 'wire/on' } // or { module: 'wire/dojo/on' } // or { module: 'wire/jquery/on' }, { module: 'wire/dom' } ]
  • 66. JS-to-JS Connections Can components collaborate in a more loosely coupled way than DI?
  • 67. Synthetic events Javascript methods act like events "Connect" methods together Neither component has knowledge of the other
  • 68. Example Controller.prototype.addItem = function(domEvent) {...} CartCountView.prototype.incrementCount = function() {...}
  • 69. Using DI controller: { create: 'myApp/cart/Controller', properties: { cartCountView: { $ref: 'cartCountView' } } }, cartCountView: { create: 'myApp/cart/CartCountView' }
  • 70. Things we can improve Controller now dependent on CartCountView interface Have to mock CartCountView to unit test Controller What if there are other times we'd like to update the cart count?
  • 71. Synthetic event connection controller: { create: 'myApp/cart/Controller' }, cartCountView: { create: 'myApp/cart/CartCountView', connect: { 'controller.addItem': 'incrementCount' } }
  • 72. Better Application Composition layer makes the connection Controller no longer dependent on CartCountView Neither component needs to be re-unit tested when making this connection Nor if the connection is removed later Only need to re-run functional tests Could completely remove CartCountView simply by cutting it out of the Application Composition spec
  • 73. Still not perfect What if addItem throws or fails in some way?
  • 74. AOP Connections controller: { create: 'myApp/cart/Controller' }, cartCountView: { create: 'myApp/cart/CartCountView', afterReturning: { 'controller.addItem': 'incrementCount' } }
  • 75. Closer Only increment count on success What about failures?
  • 76. AOP Connections controller: { create: 'myApp/cart/Controller', afterReturning: { 'addItem': 'cartCountView.incrementCount' }, afterThrowing: { 'addItem': 'someOtherComponent.showError' } }, cartCountView: { create: 'myApp/cart/CartCountView' }, someOtherComponent: // ...
  • 77. Better! But not quite there More decoupled, testable, refactorable Still a level of coupling we can remove
  • 78. Coupled parameters function Controller() {} Controller.prototype = { addItem: function(domEvent) { // How to find the item data, in order to add it? } }
  • 79. Coupled parameters Controller receives a domEvent, but must locate the associated data to update Need DOM traversal, and understand the DOM structure data id or hash key hiding in a DOM attribute? Have to mock for unit testing
  • 80. Coupled parameters Controller only really cares about the item
  • 81. Refactor function Controller() {} Controller.prototype = { addItem: function(item) { // Just add it } }
  • 82. Transform connections Connections that can, um, transform data!
  • 83. Transform function define(function() { // Encapsulate the work of finding the item return function findItemFromEvent(domEvent) { // Find the item, then return item; } });
  • 84. App Composition itemList: { $ref: 'dom.first!.item-list'}, findItem: { module: 'myApp/data/findItemFromEvent' } controller: { create: 'myApp/Controller', on: { itemList: { 'click:button.add': 'findItem | addItem' } } }
  • 85. Ahhh, at last Controller is easier to unit test Algorithm for finding the thing can also be unit tested separately and more easily can be changed separately from Controller can be reused in other parts of the app
  • 86. Awesome, we're done, right? Not quite ...
  • 87. What about asynchrony? Occurs most often at component and system boundaries Hence, connections often need to be asynchronous Canonical example: XHR
  • 88. Example Controller.prototype.addItem = function(item, callback) {...} CartCountView.prototype.incrementCount = function() {...}
  • 89. Example controller: { create: 'myApp/cart/Controller', afterReturning: { 'addItem': 'cartCountView.incrementCount' }, afterThrowing: { 'addItem': 'someOtherComponent.showError' } }, cartCountView: { create: 'myApp/cart/CartCountView' }, someOtherComponent: // ...
  • 90. Uh oh Moved the function result from the return value to the parameter list Since addItem can't return anything, afterReturning doesn't work! And how do we provide the callback?
  • 91. Brief, asynchronous detour Javascript is designed around a single-threaded event loop Browser DOM events and network I/O are async SSJS platforms (Node, RingoJS, etc) are built around async I/O AMD module loading is async--the A in AMD!
  • 92. Callbacks The typical solution is callbacks, aka "Continuation Passing"
  • 93. Example // You wish! var content = xhr('GET', '/stuff');
  • 94. Add callback and error handler xhr('GET', '/stuff', function(content) { // do stuff }, function(error) { // handle error } );
  • 95. Callback infestation // It's turtles all the way *up* function getStuff(handleContent, handleError) { xhr('GET', '/stuff', function(content) { // transform content somehow, then // (what happens if this throws?) handleContent(content); }, function(error) { // Maybe parse error, then // (what happens if THIS throws?!?) handleError(error); } ); }
  • 96. Async is messy Code quickly becomes deeply nested and harder to reason about Familiar programming idioms don't work It's upside-down: Values and errors flow down the stack now rather than up. Functions are no longer easily composable: g(f(x)) doesn't work anymore try/catch/finally, or something reasonably similar is impossible Callback and errback parameters must be added to every function signature that might eventually lead to an asynchronous operation Coordinating multiple async tasks is a pain
  • 97. Promises Synchronization construct Not a new idea Similar to java.util.concurrent.Future Placeholder for a result or error that will materialize later.
  • 98. Example Return a promise, into which the content, or an error, will materialize. function getStuff() { var promise = xhr('GET', '/stuff'); return promise; }
  • 99. Promises Restore call-and-return semantics Move function results back to the return value Remove callback function signature pollution Provide an async analog to exception propagation It's right-side up
  • 100. More about Promises http://en.wikipedia.org/wiki/Futures_and_promises http://blog.briancavalier.com/async-programming-part-1-its- messy http://blog.briancavalier.com/async-programming-part-2- promises http://github.com/cujojs/when/wiki http://wiki.commonjs.org/wiki/Promises/A
  • 101. Promises Several proposed standards Promises/A defacto standard cujo.js: when.js Dojo: dojo/Deferred jQuery: $.Deferred (well, close enough) Q soon YUI, Ember
  • 102. IOC + Promises Promises/A is an integration standard for asynchrony IOC is about gluing components together so they can collaborate Sounds like a match!
  • 103. Refactor to return a promise Controller.prototype.addItem = function(item) { // Asynchronously add the item, then return promise; }
  • 104. Promise-aware AOP controller: { create: 'myApp/cart/Controller', afterResolving: { 'addItem': 'cartCountView.incrementCount' }, afterRejecting: { 'addItem': 'someOtherComponent.showError' } }, cartCountView: { create: 'myApp/cart/CartCountView' }, someOtherComponent: // ...
  • 105. Win Count will only be incremented after the item has been added successfully! If adding fails, show the error
  • 106. Async without async Promise-aware AOP for async connections AMD loaders manage async module loading and dependency graph resolution. Promise-aware IOC container: Integrate with AMD loader to load modules used in application composition specs. Async component creation: constructor or plain function can return a promise Async DI: component references are injected as promises for the components resolve Component startup/shutdown methods can return a promise
  • 107. Connections Implement application logic in components Connect components non-invasively via Application Composition DI, events (DOM and JS), AOP, Promise-aware AOP Adapt APIs by transforming data along connections Enjoy the easier testing and refactoring :)
  • 108. Organize! Components, components, components the "file tree on the left" actually became useful! -- Brian
  • 109. Organize! Divide your app into feature areas What are the things you talk about when you talk about the app?
  • 111. Case: View-component View-components consist of HTML(5) template (keep it simple!) CSS file (structural bits of OOCSS/SMACCS) i18n file(s) javascript controller (optional) test harness (also for design) any assets necessary for rendering any view-specific data transforms, validations, etc. wire spec (optional)
  • 114. Testing visual components Double-duty test harnesses Fixture for creating HTML and designing CSS Harness for user-driven tests Harness for unit tests
  • 115. Testing visual components Double-duty test harnesses (code demo)
  • 116. Unit tests Smaller is better Fewer dependencies means fewer mocks!
  • 118. cujo.js AMD Modules - curl & cram IOC & Application Composition - wire Promises/A - when AOP - meld ES5 - poly Data binding - cola (alpha)
  • 119. Alternatives AMD Modules - RequireJS, Dojo, lsjs, BravoJS IOC - AngularJS Promises - Q, Dojo AOP - Dojo ES5 - es5shim Data binding - Backbone, and everyone else
  • 120. cujo.js Get it at http://cujojs.com Discussions, Announcements, Questions, etc. https://groups.google.com/d/forum/cujojs