HOW TO WRITE BIG APPS.Richard Rodger@rjrodger
Friday 26 October 2012
Node.js apps are getting bigger.
Friday 26 October 2012
So, how do you scale?‣be stateless, ‣lots of little processes,‣funky V8 options,‣...
Friday 26 October 2012
NO
Friday 26 October 2012
How do you scale this?
Friday 26 October 2012
Let's write a class for Cars.
Friday 26 October 2012
Classicalfunction Car( params ) { this.color = params.color || "red" this.marque = params.marque || "Ferrari" this.model = params.model || "Testarossa" this.cylinders = params.cylinders || 12 this.timeto60 = params.timeto60 || 5.2 // seconds }
Car.prototype.drive = function() { console.log( "vrooom!" )}
var car = new Car({color:"yellow"})car.drive()
Friday 26 October 2012
Classicalfunction Car( params ) { this.color = params.color || "red" this.marque = params.marque || "Ferrari" this.model = params.model || "Testarossa" this.cylinders = params.cylinders || 12 this.timeto60 = params.timeto60 || 5.2 // seconds }
Car.prototype.drive = function() { console.log( "vrooom!" )}
var car = new Car({color:"yellow"})car.drive()
VOTENOW
Friday 26 October 2012
Prototypicalvar Car = { color: "red", marque: "Ferrari", model: "Testarossa", cylinders: 12, timeto60: 5.2, drive: function() { console.log( "vrooom!", this ) }}
var car = Object.create(Car)car.color = "yellow"car.drive()
Friday 26 October 2012
Prototypicalvar Car = { color: "red", marque: "Ferrari", model: "Testarossa", cylinders: 12, timeto60: 5.2, drive: function() { console.log( "vrooom!", this ) }}
var car = Object.create(Car)car.color = "yellow"car.drive()
VOTENOW
Friday 26 October 2012
Functionalfunction Car( params ) { var self = {}
var color = params.color || "red" var marque = params.marque || "Ferrari" var model = params.model || "Testarossa" var cylinders = params.cylinders || 12 var timeto60 = params.timeto60 || 5.2
self.drive = function() { console.log( "vrooom!", self ) } return self}var car = Car({color:"yellow"})car.drive()
Friday 26 October 2012
Functionalfunction Car( params ) { var self = {}
var color = params.color || "red" var marque = params.marque || "Ferrari" var model = params.model || "Testarossa" var cylinders = params.cylinders || 12 var timeto60 = params.timeto60 || 5.2
self.drive = function() { console.log( "vrooom!", self ) } return self}var car = Car({color:"yellow"})car.drive()
VOTENOW
Friday 26 October 2012
Which one should we use for Cars?
Friday 26 October 2012
Let's play a GAME.
Friday 26 October 2012
Stand up.
Friday 26 October 2012
Stand up.Everybody.
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
YES NOStay standing. Sit down.
And stay down!
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
Is this a car?
Friday 26 October 2012
Is this a car?It's a painting.
Friday 26 October 2012
Which one?‣Classical‣Prototypical‣Functional
Friday 26 October 2012
Which one?‣Classical‣Prototypical‣Functional
NONE!Friday 26 October 2012
‣Color - Lego?‣Marque - Batman brand?‣Model - Flintstones?‣Cylinders - Star Wars hover car?‣timeto60 - Model T max is 45mph
What's wrong with properties?
Friday 26 October 2012
Classes are ideal Platonic forms.
Friday 26 October 2012
‣Sides - 3!‣Points - 3!‣Total of Angles - 180°!
Think of the ideal triangle.
Friday 26 October 2012
‣Sides - 3!‣Points - 3!‣Total of Angles - 180°!
Think of the ideal triangle.
Now picture it in your mind.
Friday 26 October 2012
Plato was wrong.Ideal forms do not exist.
Friday 26 October 2012
George Berkeley
berkeley.edusame guy
also Irish!Friday 26 October 2012
Inventor of...
Friday 26 October 2012
Friday 26 October 2012
There is no mental image of a ideal triangle.
Friday 26 October 2012
Classes suck.Objects are ok.
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ance
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ancerefactoring
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ancerefactoring
architecture
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ance
enca
psul
atio
n
refactoring
architecture
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ance
enca
psul
atio
n
refactoring
architecture
schemas
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ance
enca
psul
atio
npo
lym
orph
ism
refactoring
architecture
schemas
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ance
enca
psul
atio
npo
lym
orph
ism
unit testing
refactoring
architecture
schemas
Friday 26 October 2012
Classes suck.Objects are ok.inherit
ance
enca
psul
atio
npo
lym
orph
ism
unit testing
refactoring
architecture
schemas
dependencies
Friday 26 October 2012
Something is wrong with modeling a car.
Friday 26 October 2012
But you can still drive all those cars.
Friday 26 October 2012
It's not what you are.It's what you do.
Friday 26 October 2012
‣Register a new user,‣Place an order,‣Call an external service,‣Save and load data,‣...
What does your app want to do?
Friday 26 October 2012
This is JavaScriptJSON JSONfunction
A command for your app,
that "does stuff"
OUTPUT, asynchronously,
of courseINPUT(mostly in-
memory objects)
Friday 26 October 2012
How do you find the right "thing to do"?
Friday 26 October 2012
How do you find the right "thing to do"?PATTERN MATCHING!
Friday 26 October 2012
{ thing: "product", cmd: "save",
... other fields}
{ thing: "product", cmd: "load",
... other fields}
doSave()
doLoad()
Friday 26 October 2012
Define your "business logic" in terms of these commands.
Friday 26 October 2012
What do you get as the pay off?
Friday 26 October 2012
Really easy testing.Verify the returned JSON and you're done.
Friday 26 October 2012
A distributed system, if you need it.That gives you scale too.
Friday 26 October 2012
Completely decoupledcommands that never need to know about each other.
Friday 26 October 2012
Plugins for free - just bundle up a few related commands.Organize your code!
Friday 26 October 2012
middleware-style layering - e.g. add a caching layer by matching data storage commands.
Friday 26 October 2012
Stay in control - tracing, logging, throttling, permissions, special cases - all easy.
Friday 26 October 2012
Documentation - just list all the commands and the JSON they expect.
Friday 26 October 2012
Code!Open sourced at http://senecajs.orgnpm install seneca
Friday 26 October 2012
var seneca = require('seneca')()
// define a commandseneca.add({role:'math', cmd:'sum'}, function(args,callback) { var sum = args.left + args.right callback(null,{answer:sum}) })
// call the commandseneca.act({role:'math', cmd:'sum', left:1, right:2}, function(err,result) { if( err ) return console.error( err ) console.log(result) })
// prints: { answer: 3 }
Define and call a command.
Friday 26 October 2012
// define a commandseneca.add({role:'math', cmd:'sum'}, function(args,callback) { var sum = args.left + args.right callback(null,{answer:sum}) })
// pin the APIvar math = seneca.pin({role:'math',cmd:'*'})
// call the commandmath.sum({left:1,right:2}, function(err,result) { console.log(result) })
// prints: { answer: 3 }
Pinning an API for convenience
Friday 26 October 2012
seneca.use( function(seneca,options,callback) { seneca.add( {role:'math', cmd:'sum'}, function(args,callback) { var sum = args.left + args.right callback(null,{answer:sum}) })
seneca.add( {role:'math', cmd:'product'}, function(args,callback) { var product = args.left * args.right callback(null,{answer:product}) })
callback( null, seneca.http({ // just a connect middleware pin: {role:'math', cmd:'*'}, map: { sum: {}, product: {} }, // GET is the default HTTP method args: { left: parseFloat, right: parseFloat } }))})
var app = connect() .use(connect.query()) .use(seneca.service()) .listen(3000)// http://localhost:3000/api/sum?left=1&right=2
Plugins: commands + HTTP API.
Friday 26 October 2012
// client: // use transport plugin to calculate product remotelyseneca.use('transport',{ pins:[ {role:'math', cmd:'product'} ]})
// this will go out over networkseneca.act({role:'math', cmd:'product', left:3, right:4}, function(err,result) { if( err ) return console.error( err ) console.log(result) })
// server (as per previous slide):seneca.use('transport')...app.use( connect.json() )...
Build a distributed system
Friday 26 October 2012
var product = seneca.make('product')product.name = 'apple'product.price = 100
// ActiveRecord-styleproduct.save$(function( err, product ) { if( err ) return console.error( err ) console.log( 'saved: '+product )
// product.id was generated for you product.load$({id:product.id},function( err, product ) { if( err ) return console.error( err ) console.log( 'loaded: '+product ) })})
// output:// saved: //product:{id=286624;name=apple;price=100}// loaded: //product:{id=286624;name=apple;price=100}
// mix-and-match in-memory, MongoDB, MySQL, PostreSQL, etc.
Data storage (also plugin-based)
Friday 26 October 2012
Also, seneca...‣is about 18 months old‣has detailed tracing‣has nice error messages‣has a REPL! @dshaw happy?‣is used in production
Friday 26 October 2012
Why did we built it? builds Minimum Viable Products that become big apps.
Friday 26 October 2012
senecajs.org@nodeseneca
Thanks!
Friday 26 October 2012