8. Classical
function 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!" )
}
VO
TE
var car = new Car({color:"yellow"})
NO
car.drive()
W
Friday 26 October 2012
9. var Car = {
Prototypical
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
10. var Car = {
Prototypical
color: "red",
marque: "Ferrari",
model: "Testarossa",
cylinders: 12,
timeto60: 5.2,
drive: function() {
console.log( "vrooom!", this )
}
}
VO
TE
var car = Object.create(Car)
NO
car.color = "yellow"
car.drive()
W
Friday 26 October 2012
11. Functional
function 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
12. Functional
function 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 )
VO
TE
}
return self
NO
}
var car = Car({color:"yellow"})
W
car.drive()
Friday 26 October 2012
13. Which one
should we
use for
Cars?
Friday 26 October 2012
25. Is this a car?
It's a painting.
Friday 26 October 2012
26. Which one?
‣Classical
‣Prototypical
‣Functional
Friday 26 October 2012
27. Which one?
‣Classical
‣Prototypical
‣Functional
NONE!
Friday 26 October 2012
28. What's wrong
with properties?
‣Color - Lego?
‣Marque - Batman brand?
‣Model - Flintstones?
‣Cylinders - Star Wars hover car?
‣timeto60 - Model T max is 45mph
Friday 26 October 2012
29. Classes
are
ideal
Platonic
forms.
Friday 26 October 2012
30. Think of the ideal
triangle.
‣Sides - 3!
‣Points - 3!
‣Total of Angles - 180°!
Friday 26 October 2012
31. Think of the ideal
triangle.
‣Sides - 3!
‣Points - 3!
‣Total of Angles - 180°!
Now picture it in
your mind.
Friday 26 October 2012
32. Plato was
wrong.
Ideal forms do
not exist.
Friday 26 October 2012
33. George
Berkeley
berkeley.edu
same guy
also Irish!
Friday 26 October 2012
36. There is no
mental image
of a ideal
triangle.
Friday 26 October 2012
37. Classes suck.
Objects are ok.
Friday 26 October 2012
38. Classes suck.
Objects are ok.
i nh
eritan ce
Friday 26 October 2012
39. Classes suck.
refac
torin
Objects are ok.
i nh
eritanc eg
Friday 26 October 2012
40. Classes suck.
refac
torin
archi
tectu
Objects are ok.
itanc eg re
er
i nh
Friday 26 October 2012
41. on
Classes suck.
lati
archi
u
aps
refac tectu
enc
torin
Objects are ok.
itanc eg re
er
i nh
Friday 26 October 2012
42. on
Classes suck.
sch
lati
e
archi
ma
u
s
aps
refac tectu
enc
torin
Objects are ok.
itanc eg re
er
i nh
Friday 26 October 2012
43. on
Classes suck.
sch
lati
e
archi
ma
u
s
ism
aps
refac tectu
orph
enc
torin
Objects are ok.
itanc eg
polym
re
er
i nh
Friday 26 October 2012
44. on
Classes suck.
sch
lati
e
archi
ma
un
u
s
ism
aps
it t
refac tectu
orph
enc
est
torin
Objects are ok.
eg
ing
itanc
polym
re
er
i nh
Friday 26 October 2012
45. on
Classes suck.
sch
lati
e
archi
ma
un
u
s
ism
aps
it t
refac tectu
orph
enc
est
torin
Objects are ok.
eg encies
ing
itanc pen d
polym
re
er de
i nh
Friday 26 October 2012
46. Something is
wrong with
modeling a
car.
Friday 26 October 2012
47. But you can
still drive all
those cars.
Friday 26 October 2012
48. It's not what
you are.
It's what you
do.
Friday 26 October 2012
49. What does your
app want to do?
‣Register a new user,
‣Place an order,
‣Call an external service,
‣Save and load data,
‣...
Friday 26 October 2012
50. This is JavaScript
JSON function JSON
OUTPUT,
A command asynchronously,
INPUT for your app, of course
(mostly in- that
memory objects) "does stuff"
Friday 26 October 2012
51. How do you find the
right "thing to do"?
Friday 26 October 2012
52. How do you find the
right "thing to do"?
PATTERN
MATCHING!
Friday 26 October 2012
53. {
thing: "product",
cmd: "save",
... other fields
doSave()
}
{
thing: "product",
cmd: "load",
... other fields
doLoad()
}
Friday 26 October 2012
54. Define your
"business logic" in
terms of these
commands.
Friday 26 October 2012
55. What do you get as
the pay off?
Friday 26 October 2012
56. Really easy testing.
Verify the returned
JSON and you're
done.
Friday 26 October 2012
57. A distributed system,
if you need it.
That gives you scale
too.
Friday 26 October 2012
58. Completely
decoupled
commands that never
need to know about
each other.
Friday 26 October 2012
59. Plugins for free - just
bundle up a few
related commands.
Organize your code!
Friday 26 October 2012
60. middleware-style
layering - e.g. add a
caching layer by
matching data
storage commands.
Friday 26 October 2012
61. Stay in control -
tracing, logging,
throttling,
permissions, special
cases - all easy.
Friday 26 October 2012
62. Documentation - just
list all the commands
and the JSON they
expect.
Friday 26 October 2012
63. Code!
Open sourced at
http://senecajs.org
npm install seneca
Friday 26 October 2012
64. Define and call a command.
var seneca = require('seneca')()
// define a command
seneca.add({role:'math', cmd:'sum'},
function(args,callback) {
var sum = args.left + args.right
callback(null,{answer:sum})
})
// call the command
seneca.act({role:'math', cmd:'sum', left:1, right:2},
function(err,result) {
if( err ) return console.error( err )
console.log(result)
})
// prints: { answer: 3 }
Friday 26 October 2012
65. Pinning an API for convenience
// define a command
seneca.add({role:'math', cmd:'sum'},
function(args,callback) {
var sum = args.left + args.right
callback(null,{answer:sum})
})
// pin the API
var math = seneca.pin({role:'math',cmd:'*'})
// call the command
math.sum({left:1,right:2},
function(err,result) {
console.log(result)
})
// prints: { answer: 3 }
Friday 26 October 2012
66. Plugins: commands + HTTP API.
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
Friday 26 October 2012
67. Build a distributed system
// client:
// use transport plugin to calculate product remotely
seneca.use('transport',{
pins:[ {role:'math', cmd:'product'} ]
})
// this will go out over network
seneca.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() )
...
Friday 26 October 2012
69. 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
70. Why did we built it?
builds
Minimum Viable
Products that
become big apps.
Friday 26 October 2012
71. senecajs.org
@nodeseneca
Thanks!
Friday 26 October 2012