coffeescript design patterns

64
CoffeeScript Design Patterns Presented by Trevor Burnham at Øredev 2011

Upload: trevorburnham

Post on 12-May-2015

5.333 views

Category:

Technology


0 download

DESCRIPTION

Talk given at Øredev 2011 by the author of http://pragprog.com/book/tbcoffee/coffeescript

TRANSCRIPT

Page 1: CoffeeScript Design Patterns

CoffeeScript Design Patterns

Presented by Trevor Burnham at Øredev 2011

Page 2: CoffeeScript Design Patterns

The Compleat History of JavaScript

Preface

Page 3: CoffeeScript Design Patterns

1995 to 2003: Ancient JavaScript

Page 4: CoffeeScript Design Patterns

Paul Graham on JavaScript:

“I would not even use Javascript, if I were you... Most of the Javascript I see on the Web isn’t necessary, and much of it breaks.”

(“The Other Road Ahead,” 2001)

Page 5: CoffeeScript Design Patterns

2004-2008: Medieval JavaScript

Page 6: CoffeeScript Design Patterns

Ajax!

Page 7: CoffeeScript Design Patterns

Solid libraries!

...And probably others!

Page 8: CoffeeScript Design Patterns

2009-: Modern JavaScript

Page 9: CoffeeScript Design Patterns

The New First Language?

Page 10: CoffeeScript Design Patterns

JavaScript is Now FAST!

Page 11: CoffeeScript Design Patterns

JavaScript on the Server

Page 12: CoffeeScript Design Patterns

Everyone Who Knows JavaScriptFeels Like Superman!

Page 13: CoffeeScript Design Patterns
Page 15: CoffeeScript Design Patterns

“A Little Language”

Page 17: CoffeeScript Design Patterns

Ward Cunningham

“CoffeeScript and the environment will all the powerful browsers is the closest I felt to the power I had twenty years ago in Smalltalk.”

—Interview with InfoQ, November 2011

Page 18: CoffeeScript Design Patterns

Brendan Eich (!)

CoffeeScript user

Page 19: CoffeeScript Design Patterns

Eich + Ashkenas at JsConf 2011

Page 20: CoffeeScript Design Patterns

CoffeeScript: A Bird’s-Eye View

I

Page 21: CoffeeScript Design Patterns

Things CoffeeScript Isn’t:

Ruby/Python

jQuery

GWT

Dart

alert  'Hello  World!'    #  1  line!!!

Page 22: CoffeeScript Design Patterns

“It’s Just JavaScript”

a  =  b          #  var  a  =  b;

x  is  y        #  x  ===  y;

f  arg          #  f(arg);

f  =  -­‐>  x#  var  f  =  function()  {return  x;};

No standard library. No additional types.Nothing but sweet, sweet syntax!

Page 23: CoffeeScript Design Patterns

More Syntactic Sugar

f()  if  z    #  if  (z)  {  f();  }

f?()            #  if  (...)  {  f();  }

obj?            #  obj  !=  null;

key:  val    #  {key:  val};

Plus, significant whitespace...

Page 24: CoffeeScript Design Patterns

The Beauty of Indentation

for  ext  in  exts    sourcePath  =  stripExt(route)  +  ".#{ext}"    try        stats  =  fs.statSync  @absPath(sourcePath)        if  ext  is  'css'            {mtime}  =  stats            if  timeEq  mtime,  @cache.map[route]?.mtime                css  =  @cache.map[route].data            else                css  =  fs.readFileSync  @absPath(sourcePath)

source: https://github.com/TrevorBurnham/connect-assets

Page 25: CoffeeScript Design Patterns

The Curly-Braced Equivalentvar  css,  ext,  mtime,  sourcePath,  stats,  _i,  _len,  _ref;for  (_i  =  0,  _len  =  exts.length;  _i  <  _len;  _i++)  {    ext  =  exts[_i];    sourcePath  =  stripExt(route)  +  ("."  +  ext);    try  {        stats  =  fs.statSync(this.absPath(sourcePath));        if  (ext  ===  'css')  {            mtime  =  stats.mtime;            if  (timeEq(mtime,  (_ref  =  this.cache.map[route])  !=  null  ?  _ref.mtime  :  void  0))  {                css  =  this.cache.map[route].data;            }  else  {                css  =  fs.readFileSync(this.absPath(sourcePath));            }        }    }  catch  (_e)  {}}

Page 26: CoffeeScript Design Patterns
Page 27: CoffeeScript Design Patterns

Baked-In Patterns

II

Page 28: CoffeeScript Design Patterns

The Wrapper

CoffeeScript in:

console.log  i  for  i  in  arr

JavaScript out:(function()  {    var  i,  _i,  _len;    for  (_i  =  0,  _len  =  arr.length;  _i  <  _len;  _i++)  {        i  =  arr[_i];        console.log(i);    }}).call(this);

Page 30: CoffeeScript Design Patterns
Page 31: CoffeeScript Design Patterns

Things That Don’t Create Scopein JavaScript

Conditionals

Parentheses

Objects

Loops

Files (!)

Page 32: CoffeeScript Design Patterns
Page 34: CoffeeScript Design Patterns

CoffeeScripters Need No var!

console.log  i  for  i  in  arr

(function()  {    var  i,  _i,  _len;    for  (_i  =  0,  _len  =  arr.length;  _i  <  _len;  _i++)  {        i  =  arr[_i];        console.log(i);    }}).call(this);

Page 35: CoffeeScript Design Patterns

JS Best Practices,CoffeeScript Defaults!

Parappa the Wrapper

Proper Indentation

Avoiding ==

Packaging extensible objects as “classes”

Page 36: CoffeeScript Design Patterns

Plain, Ordinary JavaScript Objects

lifeEtAl = answer: 42 showAnswer: -> console.log @answer #  @  ==  this

lifeEtAl.showAnswer()

setTimeout  lifeEtAl.showAnswer,  10

Page 37: CoffeeScript Design Patterns
Page 38: CoffeeScript Design Patterns

Classes to the Rescue!

class LifeEtAl answer: 42 showAnswer: => # fat -> console.log @answer

myLife = new LifeEtAl

setTimeout myLife.showAnswer, 10

Page 39: CoffeeScript Design Patterns

How About a Little Privacy?

class LifeEtAl answer = 42 showAnswer: -> console.log answer

myLife = new LifeEtAl

setTimeout myLife.showAnswer, 10

Page 40: CoffeeScript Design Patterns

class Circle twoPi = Math.PI * 2 constructor: (@radius) -> @radiusSqr = Math.pow @radius, 2 diameter: => twoPi * @radius area: => Math.PI * @radiusSqr

c = new Circle(5)console.log c.diameter() # 31.4159console.log c.area() # 78.5398

Using a Constructor

Page 41: CoffeeScript Design Patterns

Let’s Try a Little Inheritance

class  Document  extends  Backbone.Model    defaults:        title:  'Untitled'

Page 42: CoffeeScript Design Patterns

Doing Inheritance via aJavaScript Library

var  Document  =  Backbone.Model.extend({    defaults:  {        title:  'Untitled'    }});

Page 43: CoffeeScript Design Patterns
Page 44: CoffeeScript Design Patterns

I. The Prototype Chainclass  Document  extends  Backbone.Model    defaults:        title:  'Untitled'

doc  =  new  Document

Document::  is  Document.prototype

doc.defaults  is  Document::defaults

doc.validate  is  Backbone.Model::validate

doc.hasOwnProperty  is  Object::hasOwnProperty

Page 45: CoffeeScript Design Patterns

II. Superclass Methods Can BeInvoked With super

class  AppleDevice    constructor:  (cost)  -­‐>        bankAccount.deduct  cost        bankAccount.deduct  cost  /  4  #  AppleCare

class  iPhone  extends  AppleDevice    constructor:  (cost)  -­‐>        super    #  equivalent  to  super(cost)        setInterval  (-­‐>            bankAccount.deduct  cost  /  4        ),  ONE_MONTH

Page 46: CoffeeScript Design Patterns

III. Superclass Properties are Copied

class  Primate    @thumbs  =  'opposable'

class  Human  extends  Primate

Human.thumbs  is  Primate.thumbs  is  'opposable'

Page 47: CoffeeScript Design Patterns
Page 48: CoffeeScript Design Patterns

MVC

Page 49: CoffeeScript Design Patterns

Project Patterns

III

Page 50: CoffeeScript Design Patterns

Compiling

Rails 3.1 / other web frameworks

Middleman / other static web frameworks

LiveReload / CodeKit (Mac)

coffee -w

Write a Cakefile

Page 51: CoffeeScript Design Patterns

A Piece of Cake

build = (watch, callback) ->  if typeof watch is 'function'    callback = watch    watch = false  options = ['-c', '-o', 'lib', 'src']  options.unshift '-w' if watch  coffee = spawn 'coffee', options  coffee.stdout.on 'data', (data) -> print data.toString()  coffee.stderr.on 'data', (data) -> print data.toString()  coffee.on 'exit', (status) -> callback?() if status is 0

task 'build', 'Compile CoffeeScript source files', ->  build()

task 'test', 'Run the test suite', ->  build ->    require.paths.unshift __dirname + "/lib"    {reporters} = require 'nodeunit'    process.chdir __dirname    reporters.default.run ['test']

source: https://github.com/sstephenson/node-coffee-project/

Page 52: CoffeeScript Design Patterns

Another Piece of Cake

task 'build', 'Compile CoffeeScript source files', ->  build()

task 'test', 'Run the test suite (and re-run if anything changes)', ->  suite = null  build ->    do runTests = ->      suite?.kill()      suiteNames = [        'DevelopmentIntegration'        'ProductionIntegration'      ]      suiteIndex = 0      do runNextTestSuite = ->        return unless suiteName = suiteNames[suiteIndex]        suite = spawn "coffee", ["-e", "{reporters} = require 'nodeunit'; reporters.default.run ['#{suiteName}.coffee']"], cwd: 'test'        suite.stdout.on 'data', (data) -> print data.toString()        suite.stderr.on 'data', (data) -> print data.toString()        suite.on 'exit', -> suiteIndex++; runNextTestSuite()      invoke 'docs' # lest I forget    testWatcher = watchTree 'test', 'sample-rate': 5    testWatcher.on 'fileModified', runTests    libWatcher = watchTree 'src', 'sample-rate': 5    libWatcher.on 'fileModified', -> build(-> runTests())

source: https://github.com/TrevorBurnham/connect-assets

Page 53: CoffeeScript Design Patterns
Page 54: CoffeeScript Design Patterns

Documentingsource: http://coffeescript.org/documentation/docs/grammar.html

Page 55: CoffeeScript Design Patterns

Testing

QUnit

Nodeunit

Jasmine BDD

js-test-driver

Page 56: CoffeeScript Design Patterns

The Future

IV

Page 59: CoffeeScript Design Patterns

Breaking the Client-ServerBoundaries

Stitch (37signals)

browserify

jsdom

Page 60: CoffeeScript Design Patterns
Page 61: CoffeeScript Design Patterns
Page 62: CoffeeScript Design Patterns

http://pragprog.com/book/tbcoffee/coffeescript

“This book helps readers become better JavaScripters in the process of learning CoffeeScript. What’s more, this book is a blast to read.”—Brendan Eich

Page 63: CoffeeScript Design Patterns

Search KickStarter for “Rethink”

Page 64: CoffeeScript Design Patterns

Thanks! Questions?

Follow me @trevorburnham and @coffeescript