Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hipsterware

 Hipsterware

A look at four trendy projects.

Chris Dillon

October 15, 2012
Tweet

More Decks by Chris Dillon

Other Decks in Programming

Transcript

  1. "Bring your hipsterware to me so that I may prepend

    its name with lol." -- @squarism Monday, October 15, 12
  2. Glasses + Mustaches Plaid Fixed wheel bicycles Living in the

    Mission in SF Drinks Pabst Blue Ribbon (PBR) Irony Bands you’ve never heard of Hipster Monday, October 15, 12
  3. It’s server side javascript. Node.js $ node hello_world.js Quick Unix-y

    One language Evented Not a web framework NPM Few Books Low Level C syscall bindings Monday, October 15, 12
  4. Node.js // Load the http module to create an http

    server. var http = require('http'); // Configure our HTTP server to respond with Hello World to all requests. var server = http.createServer(function (request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.end("Hello World\n"); }); // Listen on port 8000, IP defaults to 127.0.0.1 server.listen(8000); // Put a friendly message on the terminal console.log("Server running at 127.0.0.1:8000”); $ node hello_world.js Monday, October 15, 12
  5. Beyond the Basics Node.js Webframeworks Protocol libs http ftp smtp

    xmpp tor dns ssh . . . Database drivers Content Management Systems Message Queues Testing tools Command Line Tool libs ePub and Office docs in JS ... on and on, you know ... a language Monday, October 15, 12
  6. Hot Few Libraries Node.js Express web framework (has views, models

    etc) public/ routes/ views/ app.js package.json Socket.IO event based messaging client and server lib events over the wire websockets etc abstraction Monday, October 15, 12
  7. Jake Build tool like Make (define Jakefile) $ jake build:all

    Expresso TDD framework assert.eql(1, 1) # Existence: alert "I knew it!" if elvis? // equivalent javascript :( if (typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); } Monday, October 15, 12
  8. When to use? Bad question, my question. Node.js First, play

    and grok. After deep understanding, you see use cases. Sick of EventMachine (Ruby) and Twisted (Python)? Want one language stack? Want websockets? Want a proxy, load balancer, simple TCP server? Monday, October 15, 12
  9. non-exhaustive mortal ramblings When not to use Node.js Anti Javascript

    Low Level You need a job in DC Solved Callbacks Websockets, feh Monday, October 15, 12
  10. Key Value Database Redis Low Level Demo Online Shell Simple

    Protocol Fast enough to cache Jagged Columns Monday, October 15, 12
  11. Example Redis $ redis-cli redis 127.0.0.1:6379> set x 10 OK

    redis 127.0.0.1:6379> get x "10" redis 127.0.0.1:6379> incr x (integer) 11 redis 127.0.0.1:6379> get x "11" Monday, October 15, 12
  12. Has PubSub Built In Redis Pubsub? I think chat server.

    channels listen on channel get messages Example uses Live Map Forum Watch Wire up two languages? IPC? Monday, October 15, 12
  13. Redis Chat Example Redis io redis_chat ‹master*› > ps -ef|grep

    redis 501 321 227 redis-server /usr/local/etc/redis.conf Monday, October 15, 12
  14. Jagged Database Redis require  'redis' redis  =  Redis.new redis.set  'users:credit_cards:[email protected]',

     123.. redis.set  'users:[email protected]:enabled',  true redis.get  'users:[email protected]:enabled' =>  "true" Monday, October 15, 12
  15. The Problem Single File SQL HTML CSS Ala Vanilla PHP

    Vanilla JSP mod_perl old Cold Fusion? circa 2001 web technologies The App Monday, October 15, 12
  16. The Problem Concerns Data Layout Logic Styling URLs Sessions Caching

    Authentication APIs / REST Everything Single File SQL HTML CSS Ala Vanilla PHP Vanilla JSP mod_perl old Cold Fusion? circa 2001 web technologies The App Monday, October 15, 12
  17. The Problem Concerns Data Layout Logic Styling URLs Sessions Caching

    Authentication APIs / REST Everything Single File SQL HTML CSS Ala Vanilla PHP Vanilla JSP mod_perl old Cold Fusion? circa 2001 web technologies Problems Multiple Concerns DRY SQL everywhere New devs are confused Spaghetti Procedural Brittle ... The App Monday, October 15, 12
  18. Javascript has the same problems Problems DRY Ajax everywhere New

    devs are confused Event spaghetti Data mixed in with view Javascript in your app Ajax HTML Clicks Monday, October 15, 12
  19. Javascript has the same problems Problems DRY Ajax everywhere New

    devs are confused Event spaghetti Data mixed in with view Javascript in your app Ajax HTML Clicks Data DOM Callbacks Monday, October 15, 12
  20. Javascript has the same problems Problems DRY Ajax everywhere New

    devs are confused Event spaghetti Data mixed in with view Javascript in your app Ajax HTML Clicks Data DOM Callbacks MVC Pattern Model View Controller Monday, October 15, 12
  21. Give Javascript Structure Backbone.js It’s MVC in javascript-land™ models/ -

    Put JS data objects in model definition collections/ - Are many models routers/ - Wire URL paths to methods views/ - Render template, written in code (controller) templates/ - HTML with dynamic code tags <%= foo %> Monday, October 15, 12
  22. Update Views When Data Changes Backbone.js Simple Example File Layout

    simple.html js/lib/jquery-1.8.2.min.js js/lib/underscore-min.js js/lib/backbone.js js/simple.js Logic Flow html “sets” a message greeting model is created view uses model when model changes, trigger view reacts to trigger, renders Monday, October 15, 12
  23. simple.html -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ <html> <head>    <title>Simple  Example</title>    <!-­‐-­‐  order

     matters  in  the  libs  below  -­‐-­‐>    <script  src="js/lib/jquery-­‐1.8.2.min.js"></script>    <script  src="js/lib/underscore-­‐min.js"></script>    <script  src="js/lib/backbone.js"></script>    <script  src="js/simple.js"></script>    <style  type="text/css">    #greeting  {        padding-­‐top:  2em;        text-­‐align:  center;        vertical-­‐align:  center;    }    </style> </head> <body>    <div  id="greeting">        <h1>This  is  HTML.</h1>    </div> </body> </html> Monday, October 15, 12
  24. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); Monday, October 15, 12
  25. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  26. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  27. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  28. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  bindAll  makes  'this'  be  the  view  inside  render() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  29. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  bindAll  makes  'this'  be  the  view  inside  render() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  you  can  drop  :message  to  fire  on  all  change  events        change  is  a  built-­‐in  event,  see  FAQ  for  list <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  30. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  very  critical  to  use  model.get() <-­‐-­‐  bindAll  makes  'this'  be  the  view  inside  render() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  you  can  drop  :message  to  fire  on  all  change  events        change  is  a  built-­‐in  event,  see  FAQ  for  list <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  31. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  very  critical  to  use  model.get() <-­‐-­‐  bindAll  makes  'this'  be  the  view  inside  render() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  you  can  drop  :message  to  fire  on  all  change  events        change  is  a  built-­‐in  event,  see  FAQ  for  list <-­‐-­‐  el  helps  backbone  bind  itself  to  one  part  of  the  DOM,  reduce  drawing <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  32. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  very  critical  to  use  model.get() <-­‐-­‐  bindAll  makes  'this'  be  the  view  inside  render() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  you  can  drop  :message  to  fire  on  all  change  events        change  is  a  built-­‐in  event,  see  FAQ  for  list <-­‐-­‐  el  helps  backbone  bind  itself  to  one  part  of  the  DOM,  reduce  drawing <-­‐-­‐  tack  .el  on  the  end  for  render  chaining <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done Monday, October 15, 12
  33. lib/simple.js -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ $(document).ready(function(){    Greeting  =  Backbone.Model.extend({      

     initialize:  function(message)  {            this.set('message',  message);        }    });    GreetingView  =  Backbone.View.extend({        el:  $('#greeting  h1'),        initialize:  function(){            _.bindAll(this,  'render');            this.render();            this.model.bind("change:message",  this.render);        },        render:  function(){            var  message_attr  =  this.model.get('message');            $(this.el).text(message_attr).el;        }    });    window.greeting  =  new  Greeting("Hello  from  Model  initialize.");    window.greetingView  =  new  GreetingView({model:  greeting}); }); <-­‐-­‐  very  critical  to  use  model.set() <-­‐-­‐  very  critical  to  use  model.get() <-­‐-­‐  bindAll  makes  'this'  be  the  view  inside  render() <-­‐-­‐  use  window.global  variable  scope        for  js  browser  console  demo <-­‐-­‐  you  can  drop  :message  to  fire  on  all  change  events        change  is  a  built-­‐in  event,  see  FAQ  for  list <-­‐-­‐  el  helps  backbone  bind  itself  to  one  part  of  the  DOM,  reduce  drawing <-­‐-­‐  tack  .el  on  the  end  for  render  chaining <-­‐-­‐  normal  jQuery  onLoad()  event,  starts  this  whole  thing  up  after  page  done > greeting.set({message:'hello from js console!'}) Monday, October 15, 12
  34. Another Webserver Nginx "Apache is like Microsoft Word, it has

    a million options but you only need six. Nginx does those six things, and it does five of them 50 times faster than Apache." -- Chris Lea, WordCamp 2008 Short config Unpopular Wordpress.com, Github, Sourceforge, Netflix Small Memory Monday, October 15, 12
  35. Nginx one thread, events Apache many threads, processes Apache runs

    fine under light load Nginx runs fine under light and heavy load So Monday, October 15, 12
  36. 10k concurrent connections on a laptop “Apache used four worker

    processes (threaded mode), 30% CPU and 17MB of memory to serve 6,500 requests per second. Nginx used one worker, 15% CPU and 1MB of memory to serve 11,500 requests per second.” Monday, October 15, 12
  37. Example Uses Nginx Load balancer Middle-tier (mod_php, mod_rails, mod_perl) Mail

    proxy?! I used it to front Apache because of websockets Monday, October 15, 12
  38. Load Balancer Example Config Nginx upstream apacheboxes { server 192.168.1.15

    weight=10 max_fails=3 fail_timeout=30s; server 192.168.1.16 weight=10 max_fails=3 fail_timeout=30s; # only comes alive when above two fails server 192.168.1.23 weight=1 backup; } ## Start www.example.com ## server { listen 3.3.3.3:80; server_name www.example.com; ## send request back to apacheboxes ## location / { proxy_pass http://apacheboxes; # what cases the request will be transmitted to the next server proxy_next_upstream error timeout invalid_header http_500 http_502 ... ; proxy_redirect off; proxy_buffering off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } Monday, October 15, 12
  39. @hipsterhacker “Getting hired at an Oracle shop is like going

    to an open bar party where the only beer is Heineken.” “If it's not MongoDB, it's the WrongoDB.” “Ruby on Rails is a lot like my Chuck Taylors: basically pretty cool, but such a frequent accessory for poseurs that I had to give them up.” hipstergrammers.tumblr.com Everything on Hacker News More Sources Parody Accounts and Srs Bsns Monday, October 15, 12