<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

	<title>Benjamin Thomas</title>
	<link href="http://benjaminthomas.org/atom.xml" rel="self"/>
	<link href="http://benjaminthomas.org/"/>
	<updated>2010-09-09T04:10:57-06:00</updated>
	<id>http://benjaminthomas.org/</id>
	<author>
		<name>Benjamin Thomas</name>
		<email>benjamin@benjaminthomas.org</email>
	</author>

	
	<entry>
    <title>&#8226; Saying Goodbye to Apple</title>
		<link href="http://benjaminthomas.org/2010-03-14/saying-goodbye-to-apple.html"/>
		<updated>2010-03-14T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2010-03-14/saying-goodbye-to-apple</id>
		<content type="html">&lt;p&gt;It is no secret that I am a pretty big fan of the things that Apple makes. I got my first Apple laptop on January 15th in 2005. Five short years ago *sniff*. &lt;a href='http://www.flickr.com/photos/ker_bbs/4433375606/'&gt;I loved&lt;/a&gt; that laptop like nothing else. It was small and portable, it was beautiful, and the operating system worked great. I now recommend to everyone, get an Apple computer. They just work. And they work very well.&lt;/p&gt;

&lt;p&gt;It was with that in mind that last week I installed Linux on my laptop, making a full commitment to different operating system. When I say I switched operating systems, I mean to say that I have completely changed the most fundamental part of how I use my computer. I spend 12-plus hours a day on my computer. Needless to say, this is a Big Deal.&lt;/p&gt;

&lt;p&gt;The &amp;#8220;big-deal-ness&amp;#8221; is compounded by how big a fan I am of the things Apple makes. I think Apple makes the best laptops you can buy. I think Apple makes the best phone you can buy. I think Apple makes the best MP3 player you can buy. I think Apple makes the most user-friendly operating system you can use. Basically, Apple is like no other company in the world in terms of making absolutely top-notch products.&lt;/p&gt;

&lt;p&gt;So, what am I replacing Apple&amp;#8217;s operating system with? Linux, of course!&lt;/p&gt;

&lt;p&gt;But here is the million dollar question: Why am I switching?&lt;/p&gt;

&lt;p&gt;Two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basically, to use an over-used buzzword, Linux is more &amp;#8220;open&amp;#8221; than both Windows and Mac OS X.&lt;/li&gt;

&lt;li&gt;Apple has been making decisions lately that I philosophically disagree with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About a month ago Apple announced its latest and greatest product, the &lt;a href='http://www.apple.com/ipad/'&gt;iPad&lt;/a&gt;. While the iPad looks &lt;em&gt;awesome&lt;/em&gt;, it continues the model set up by the iPhone, where if you want to write an application for the device you have to get Apple&amp;#8217;s approval first. I don&amp;#8217;t like this model. I&amp;#8217;ll even go so far as to say I &lt;em&gt;hate&lt;/em&gt; this model. I don&amp;#8217;t think this model is in the best interest of the consumers of Apple&amp;#8217;s devices. With the iPhone, it was at least excusable, because you could argue that Apple had to lock the system down tight because they were operating on AT&amp;amp;T&amp;#8217;s phone network. But with the iPad, while there is a 3G option, it doesn&amp;#8217;t feel as excusable. Maybe it still is. But the main point is, that if the future of Apple&amp;#8217;s products are devices like this, where you have to ask Apple&amp;#8217;s permission to install something on your computer, well, that&amp;#8217;s bullshit.&lt;/p&gt;

&lt;p&gt;Let me quote what I said in a conversation with &lt;a href='http://petercompernolle.com'&gt;a friend&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But the more Apple locks up (even if it is design perfection) the more I am going to push against it. I don&amp;#8217;t like patents. I don&amp;#8217;t like secrets. I don&amp;#8217;t like rules. I believe in a very communistic approach to development: I will never keep the things I develop all to myself. If anyone wants it, I would be happy to give it to them. I feel this way because it is precisely the projects that do this that make it fun for me to use my computer. PHP, MySQL, CouchDB, Sqlite, Apache, Vim, Node, V8, Ruby, Python, Inkscape, JQuery. I use computers a lot because I like to program and design. I don&amp;#8217;t use computers a lot for any other reason. If I didn&amp;#8217;t program/design I would only use computers as a communication tool. And judging by how much I do that, it wouldn&amp;#8217;t be a lot.&lt;/p&gt;

&lt;p&gt;So, openness and freedom are the single most important part of what make computers enjoyable for me. Period.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then last week it was announced that Apple was suing another cellphone maker called HTC for patent infringement. And well, that just pissed me off.&lt;/p&gt;

&lt;p&gt;I love math. That&amp;#8217;s why it was one of my majors in college. In math you take a set of assumptions and constraints and then see what other rules, shortcuts, algorithms, systems you can develop from those rules. It is that simple, yet from that you get things like Calculus. Now, I don&amp;#8217;t think many people out there would argue that you should be able to patent Math. Imagine if someone had a patent on Calculus.&lt;/p&gt;

&lt;p&gt;Well, computer science is no different than math. Computer science is in fact just applied math. Just math with a different set of assumptions and constraints. So, it seems completely illogical that software patents are legal.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m sure economists might argue that patents are valuable from a market point of view, and that a lot of research and development wouldn&amp;#8217;t happen without the promise of exclusivity. While that might be true, that doesn&amp;#8217;t make them right. (And I am in no way saying software patents are similar to slavery) but it can probably be argued that slavery is better for a certain market (namely better for the slave holders) but that doesn&amp;#8217;t make it right.&lt;/p&gt;

&lt;p&gt;I see software patents as a great wrong. And something that currently and actively makes the world a worse place.&lt;/p&gt;

&lt;p&gt;[As a quick aside, I&amp;#8217;m not completely sure what this means for my opinions on patents in general, but I am pretty sure that I think the whole patent system should be abolished. You shouldn&amp;#8217;t be able to own ideas.]&lt;/p&gt;

&lt;p&gt;My aforementioned friend had the following to say in response to my complaints about Apple&amp;#8217;s lawsuit:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;unfortunately for us, we don&amp;#8217;t live in a land where unicorns&amp;#8217; tears make everyone happy and everyone only wants to make the world a better place. apple is a company, a huge one, just like Microsoft and google. and their goal is not our goal; their goal is to make more money, using their innovation to do it. I just wish they didn&amp;#8217;t have to hurt others&amp;#8217; innovation to do it too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I agree with my friend in that I wish Apple wasn&amp;#8217;t doing this. But when I read that, I realized I could no longer support Apple. I can no longer support an entity that is willing to sacrifice what I see as moral obligations in the pursuit of making more money.&lt;/p&gt;

&lt;p&gt;I acknowledge though, that Apple is a company. And it needs to make money or it wouldn&amp;#8217;t exist. But my money is a way of voting. And when I spend my money on Apple products I am saying that I endorse what they are doing. When I use their operating system, I am telling the world and my friends that this company is worth choosing.&lt;/p&gt;

&lt;p&gt;I have decided to put my vote elsewhere.&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt; So, I am switching operating systems. I know I will be faced with a tough choice in the future when I need a new laptop or computer and have to choose who I am going to buy it from. I&amp;#8217;ll have to choose the company that is the least &amp;#8220;evil&amp;#8221; I guess.&lt;/p&gt;

&lt;p&gt;The operating system I chose (the Ubuntu variant of Linux) was named after a &lt;a href='http://en.wikipedia.org/wiki/Desmond_Tutu'&gt;South African philosophy called &amp;#8220;Ubuntu&amp;#8221;&lt;/a&gt;. To quote from Desmond Tutu:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the sayings in our country is Ubuntu - the essence of being human. Ubuntu speaks particularly about the fact that you can&amp;#8217;t exist as a human being in isolation. It speaks about our interconnectedness. You can&amp;#8217;t be human all by yourself, and when you have this quality - Ubuntu - you are known for your generosity.&lt;/p&gt;

&lt;p&gt;We think of ourselves far too frequently as just individuals, separated from one another, whereas you are connected and what you do affects the whole world. When you do well, it spreads out; it is for the whole of humanity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An operating system with that as its guiding philosophy? &lt;em&gt;That&lt;/em&gt; I can get behind.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;As to what I think other people should do is another issue. I don&amp;#8217;t think Linux is at the stage where non-computer people can use it enjoyably. So, most people are faced with a choice between Windows and Mac OS X. In that case both choices are &amp;#8220;evil&amp;#8221; and I would choose Mac OS X. Google is coming out with an operating system this year called &amp;#8220;Chrome OS&amp;#8221; which will be completely open sourced. Maybe use that. Though, I am not sure how well it is going to work without an internet connection, since it is highly based on their Chrome internet browser.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
	</entry>
	
	<entry>
    <title>On the Interwebs, number 20</title>
		<link href="http://benjaminthomas.org/2010-01-11/on-the-interwebs-20.html"/>
		<updated>2010-01-11T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2010-01-11/on-the-interwebs-20</id>
		<content type="html">&lt;p&gt;&lt;a href='http://blog.jozilla.net/2008/06/27/fun-with-python-opencv-and-face-detection/'&gt;Fun with Python, OpenCV and face detection&lt;/a&gt; &amp;#8212; I have been looking for an article on this for a while. This is so amazingly cool!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://weblog.bocoup.com/reading-the-audio-stream-from-firefox-3-7'&gt;Reading the Audio Stream from Firefox 3.7&lt;/a&gt; &amp;#8212; I hope all the browsers get on this. This would be absolutely awesome.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://dailyjs.com/2010/01/07/ecmascript5-date/?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+dailyjs+%28DailyJS%29'&gt;ECMAScript 5&amp;#8217;s Date Extensions&lt;/a&gt; &amp;#8212; Some long time coming changes to the date object in Javascript (aka ECMAScript). The most welcome of which are the new ways to instantiate a Date object.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://github.com/ry/node/wiki/ECMA-5-Mozilla-Features-Implemented-in-V8'&gt;ECMA 5/Mozilla Features Implemented in V8&lt;/a&gt; &amp;#8212; Speaking of ECMAScript 5 features, a list of which ones are supported by V8, the javascript engine behind Google Chrome and Node.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://andialbrecht.wordpress.com/2009/05/09/when-merging-fails/'&gt;How Do You Look When Merging Fails ;-)&lt;/a&gt; &amp;#8212; A script that takes a picture with your webcam every time your merge fails. Pretty funny idea. Though, Mercurial only as far as I can tell.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://nichol.as/asynchronous-servers-in-python'&gt;Asynchronous Servers in Python&lt;/a&gt; &amp;#8212; A list of all the async web servers available in Python with example code. It is interesting to see the different approaches to one problem.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://github.com/rails/arel'&gt;arel&lt;/a&gt; &amp;#8212; A way to write SQL in Ruby without having to worry about different SQL engines. I was going to try and write something like this, so it saved me a lot of trouble!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.engineyard.com/blog/2010/rails-and-merb-merge-plugin-api-part-3-of-6/'&gt;Rails and Merb Merge: Plugin API (Part 3 of 6)&lt;/a&gt; &amp;#8212; With this merge with Merb, Rails is taking the &amp;#8220;framework wars&amp;#8221; up a notch. The stuff they are doing is really cool. Also checkout &lt;a href='http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/'&gt;ActiveModel&lt;/a&gt; and &lt;a href='http://yehudakatz.com/2009/12/20/generic-actions-in-rails-3/'&gt;Generic Actions&lt;/a&gt;.&lt;/p&gt;</content>
	</entry>
	
	<entry>
    <title>On the Interwebs, number 19</title>
		<link href="http://benjaminthomas.org/2010-01-06/on-the-interwebs-19.html"/>
		<updated>2010-01-06T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2010-01-06/on-the-interwebs-19</id>
		<content type="html">&lt;p&gt;&lt;a href='http://rishida.net/tools/conversion/'&gt;Unicode Code Converter&lt;/a&gt; &amp;#8212; Displays the given text in many different escaped formats like HTML, URLs, Javascript, etc. Sounds odd at first, but just try the example and it will instantly make sense.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://blog.leetsoft.com/2009/12/6/clarity-in-log-files'&gt;Clarity&lt;/a&gt; &amp;#8212; Looks like a great tool for monitoring log files remotely.&lt;/p&gt;

&lt;p&gt;File APIs in Firefox 3.6 &amp;#8212; &lt;a href='http://hacks.mozilla.org/'&gt;hacks.mozilla.org&lt;/a&gt; has a &lt;a href='http://hacks.mozilla.org/2009/12/w3c-fileapi-in-firefox-3-6/'&gt;great&lt;/a&gt; &lt;a href='http://hacks.mozilla.org/2009/12/firefox-36-fileapi-demo-reading-exif-data-from-a-local-jpeg-file/'&gt;series&lt;/a&gt; &lt;a href='http://hacks.mozilla.org/2009/12/multiple-file-input-in-firefox-3-6/'&gt;of&lt;/a&gt; &lt;a href='http://hacks.mozilla.org/2009/12/uploading-files-with-xmlhttprequest/'&gt;articles&lt;/a&gt; on using the new File APIs in the upcoming Firefox 3.6.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://blog.new-bamboo.co.uk/2009/12/7/real-time-online-activity-monitor-example-with-node-js-and-websocket'&gt;Real time online activity monitor example with node.js and WebSocket&lt;/a&gt; &amp;#8212; Websockets look really powerful. And we already know I am obsessed with Node.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://antennasoft.net/robcee/2009/12/15/firebug-and-the-jit/'&gt;Firebug and the JIT&lt;/a&gt; &amp;#8212; Even if you don&amp;#8217;t have Firebug enabled it is probably slowing down your browsing experience.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://dailyjs.com/2009/12/16/node-irc/'&gt;Node.js on IRC&lt;/a&gt; &amp;#8212; A post with a collection of links on using Node with IRC.&lt;/p&gt;</content>
	</entry>
	
	<entry>
    <title>On the Interwebs, number 18</title>
		<link href="http://benjaminthomas.org/2009-12-19/on-the-interwebs-18.html"/>
		<updated>2009-12-19T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2009-12-19/on-the-interwebs-18</id>
		<content type="html">&lt;p&gt;&lt;a href='http://www.theinvisibl.com/news/2009/12/08/a-piece-with-a-lot-of-screenshots-about-the-close-tab-behaviour-in-google-chrome/'&gt;A piece with a lot of screenshots about the close tab behaviour in Google Chrome&lt;/a&gt; &amp;#8212; Excellent write up about some excellent design. There has been &lt;a href='http://code.google.com/p/chromium/issues/detail?id=12035'&gt;a bug filed for Chrome&lt;/a&gt; to change this behavior on Mac OS X so that the close button goes on the left. I think this is lunacy, the Chrome guys did a great job here.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://hacks.mozilla.org/2009/12/css-backgrounds-firefox-36/'&gt;CSS Backgrounds in Firefox 3.6&lt;/a&gt; &amp;#8212; Finally we are getting the ability to manipulate CSS background images. Though we still don&amp;#8217;t have the one feature I want: the ability to specify positions relative to a given point, like &amp;#8220;put this image 6px to the right of center&amp;#8221;.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.wait-till-i.com/2009/12/08/using-yql-to-load-and-convert-rss-feeds-really-really-fast/'&gt;Using YQL to load and convert RSS feeds really, really fast&lt;/a&gt; &amp;#8212; I really need to get around to wrapping my head around &lt;a href='http://developer.yahoo.com/yql/'&gt;YQL&lt;/a&gt;. I just wish it was more distributed so you aren&amp;#8217;t relaying entirely on Yahoo.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://debuggable.com/posts/rightjs-1-5-6-8-times-faster-than-jquery:4b1fc009-1940-4d26-bdc6-0af2cbdd56cb'&gt;RightJS 1.5: 6-8 times faster than jQuery&lt;/a&gt; &amp;#8212; Some excellent analysis of performance claims. The moral? Don&amp;#8217;t trust everything you read without looking at the details!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.stevesouders.com/blog/2009/11/16/cssembed-automatically-data-uri-ize/'&gt;CSSEmbed&lt;/a&gt; &amp;#8212; Convert images referenced in a CSS file into &lt;a href='http://en.wikipedia.org/wiki/Data_URI_scheme'&gt;data URIs&lt;/a&gt;. Pretty cool!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://ahathereitis.blogspot.com/2009/12/how-it-works.html'&gt;Looking for tennis courts on aerial photos&lt;/a&gt; &amp;#8212; I wish I was better at Computer Vision techniques. But this is a nice explanation!&lt;/p&gt;</content>
	</entry>
	
	<entry>
    <title>On the Interwebs, number 17</title>
		<link href="http://benjaminthomas.org/2009-12-18/on-the-interwebs-17.html"/>
		<updated>2009-12-18T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2009-12-18/on-the-interwebs-17</id>
		<content type="html">&lt;p&gt;&lt;a href='http://www.bytestrom.eu/blog/2009/1120a_jpeg_encoder_for_javascript'&gt;A JPEG Encoder for JavaScript&lt;/a&gt; &amp;#8212; Just what it says. Pretty amazing feat actually. Javascript is really coming along these days!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://blog.apparentsoft.com/business/124/is-paypal-good-for-your-microisv-business-a-short-paypal-horror-story/'&gt;A short PayPal horror story&lt;/a&gt; &amp;#8212; I have not had a good experience with using PayPal as a vendor either. From this day forth, when presented with an option on checking out I am not longer going to choose PayPal.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://24ways.org/'&gt;24 Ways&lt;/a&gt; &amp;#8212; 24 Ways is back this year, and has some good stuff. 24 Ways is a CSS advent calendar with 24 articles on CSS, one a day until Christmas.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.phpied.com/performance-advent-calendar-2009/'&gt;Performance Advent Calendar 2009&lt;/a&gt; &amp;#8212; Inspired by 24 Ways, but about performance.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://ditz.rubyforge.org/'&gt;Ditz&lt;/a&gt; &amp;#8212; Issue tracker intended to be embeded in your source. I love this idea.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://imageoptim.pornel.net/'&gt;ImageOptim&lt;/a&gt; &amp;#8212; Just what it says: &amp;#8220;ImageOptim optimizes images — so they take up less disk space and load faster.&amp;#8221; Dead simple and works well.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://dailyjs.com/2009/12/15/javascript-charts-roundup/'&gt;JavaScript Charts Roundup&lt;/a&gt; &amp;#8212; Summarizes different javascript libraries for graphing. I&amp;#8217;ll be looking at this for &lt;a href='http://github.com/bentomas/simple-analytics'&gt;a project I started a little while ago&lt;/a&gt;.&lt;/p&gt;</content>
	</entry>
	
	<entry>
    <title>&#8226; Bomber &#8211; a Node web framework &#8212; Actions</title>
		<link href="http://benjaminthomas.org/2009-11-29/bomber-actions.html"/>
		<updated>2009-11-29T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2009-11-29/bomber-actions</id>
		<content type="html">&lt;p&gt;This is another post in my series of posts about designing a web framework using &lt;a href='http://nodejs.org'&gt;Node&lt;/a&gt;. Catch the first two &lt;a href='/2009-11-20/designing-a-web-framework.html'&gt;here&lt;/a&gt; and &lt;a href='/2009-11-24/bomber-routing.html'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='a_new_website'&gt;A New Website&lt;/h2&gt;

&lt;p&gt;First a quick update: last night I decided Bomber needed its own place on the web, so I threw together a website for it. It is mostly based on the code for this site, so it was pretty quick. Anyway&amp;#8230;&lt;/p&gt;

&lt;p&gt;Announcing &lt;a href='http://bomber.obtdev.com/'&gt;bomber.obtdev.com&lt;/a&gt;! I&amp;#8217;m pretty proud of the icon, so make sure to check it out. Now I have a place to put documentation and more details then are appropriate for blog posts.&lt;/p&gt;

&lt;h2 id='actions'&gt;Actions&lt;/h2&gt;

&lt;p&gt;Today&amp;#8217;s installment is going to be about what I am calling &amp;#8220;actions&amp;#8221;, by which I mean, the code that is run for each request. The last post talked about routing, which was the business of figuring out from the URL which code should be run. So, this is the second half of that equation. For comparison, &lt;a href='http://rubyonrails.org/'&gt;Rails&lt;/a&gt; calls these &amp;#8220;actions&amp;#8221; and &lt;a href='http://www.djangoproject.com/'&gt;Django&lt;/a&gt; calls them &amp;#8220;views&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Conceptually actions are pretty simple. Given a request, it is their role to generate a response. If you requested an HTML list of blog posts, it is the job of the action to generate that HTML document. In an &lt;a href='http://en.wikipedia.org/wiki/Model–view–controller'&gt;MVC&lt;/a&gt; framework, the action plays the role of the glue between all the different parts of application: the database, the templates, the cookie or session variables, etc. Here is an example of an action from Rails, generated by its &lt;code&gt;scaffold&lt;/code&gt; command:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;index&lt;/span&gt;
  &lt;span class='vi'&gt;@photos&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Photo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;

  &lt;span class='n'&gt;respond_to&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='c1'&gt;# index.html.erb&lt;/span&gt;
    &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt;  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:xml&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@photos&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The code is pretty straightforward (even if you aren&amp;#8217;t familiar with Rails). It loads a list of photos from the database, and then depending on the requested format it either renders the &amp;#8216;index.html.erb&amp;#8217; template, or converts the list to an XML document.&lt;/p&gt;

&lt;p&gt;Actions have a lot of different needs. The two most basic are dealing with the request and the response:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An action needs to have access to the details of the request: What HTTP method was it? What headers were sent? What were the query parameters? What was the body of the request? What POST variables were sent? What cookies were sent? What session is it associated with? What session variables are set? Where is the request from? What browser is the request from? And so on.&lt;/li&gt;

&lt;li&gt;An action needs to be able to modify all the details of the response that it is creating. Primarily, that is setting headers, cookies, or session variables and generating the HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='giving_users_access_to_the_response_and_the_request_in_existing_frameworks'&gt;Giving users access to the Response and the Request in existing frameworks&lt;/h2&gt;

&lt;p&gt;Django is very explicit, here&amp;#8217;s an example of &lt;a href='http://docs.djangoproject.com/en/dev/topics/http/views/#a-simple-view'&gt;a simple view from the docs&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='kn'&gt;from&lt;/span&gt; &lt;span class='nn'&gt;django.http&lt;/span&gt; &lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='n'&gt;HttpResponse&lt;/span&gt;
&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;datetime&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;current_datetime&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;request&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;now&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;datetime&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;datetime&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;now&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
    &lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;It is now &lt;/span&gt;&lt;span class='si'&gt;%s&lt;/span&gt;&lt;span class='s'&gt;.&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='n'&gt;now&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;HttpResponse&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You are given a request, and you return a response. This is very intuitive, and powerful but can be a bit of a pain sometimes when you don&amp;#8217;t want to be writing all that boilerplate code over and over again. I wish I just didn&amp;#8217;t have to type quite so much. (This is a complaint I keep coming back to over and over again with Django, and it really isn&amp;#8217;t a strike against Django. Django is this way precisely because they don&amp;#8217;t want to pigeon hole you into writing your projects in a specific way. But sometimes I just wish they &lt;em&gt;would&lt;/em&gt; pick a way for me)&lt;/p&gt;

&lt;p&gt;Rails is a bit more &amp;#8220;magical&amp;#8221; in the sense that a lot of the code happens behind the scenes. With Rails, an &lt;code&gt;ActionController&lt;/code&gt; object is iniated for each request, and then the requested action method is called on that object. And because &lt;code&gt;self&lt;/code&gt; is optional in Rails it seems like things just come out of nowhere. Here&amp;#8217;s an example action:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;show&lt;/span&gt;
  &lt;span class='vi'&gt;@photo&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Photo&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:id&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

  &lt;span class='c1'&gt;# just so you can see what it is like to set session and cookie vars&lt;/span&gt;
  &lt;span class='n'&gt;log&lt;/span&gt; &lt;span class='n'&gt;session&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='c1'&gt;# get the session variable from the response&lt;/span&gt;
  &lt;span class='n'&gt;session&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# set the session variable for the response&lt;/span&gt;

  &lt;span class='n'&gt;cookies&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;value&amp;quot;&lt;/span&gt;

  &lt;span class='c1'&gt;# and setting headers&lt;/span&gt;
  &lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;headers&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;application/pdf&amp;quot;&lt;/span&gt;

  &lt;span class='n'&gt;respond_to&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='c1'&gt;# show.html.erb&lt;/span&gt;
    &lt;span class='nb'&gt;format&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;xml&lt;/span&gt;  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;render&lt;/span&gt; &lt;span class='ss'&gt;:xml&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@photo&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;What is going on is &lt;code&gt;params&lt;/code&gt;, &lt;code&gt;session&lt;/code&gt;, &lt;code&gt;cookies&lt;/code&gt;, &lt;code&gt;response&lt;/code&gt; and &lt;code&gt;respond_to&lt;/code&gt; are all actually methods on the &lt;code&gt;ActionController&lt;/code&gt; object. To return a response you call a method like &lt;code&gt;render&lt;/code&gt;, or &lt;code&gt;redirect_to&lt;/code&gt;. I really do feel like writing applications in Rails is like writing in a-whole-nother language. Rails has request and response objects, but you generally don&amp;#8217;t use them in favor of the other simpler methods. With Rails there isn&amp;#8217;t a very clear distinction between requests and responses like there is in Django.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.sinatrarb.com/'&gt;Sinatra&lt;/a&gt; works in a very similar way to Rails. And of the Node frameworks, the majority of them are Sinatra like in spirit.&lt;/p&gt;

&lt;h2 id='evented_programming'&gt;Evented programming&lt;/h2&gt;

&lt;p&gt;If we already didn&amp;#8217;t have enough choices for how to design an API for a web framework, Node then adds an additional level of complexity due to its evented nature.&lt;/p&gt;

&lt;p&gt;What does that mean? Well, Node lives by the philosophy that a program should never just sit there and do nothing while it is waiting for input or output to finish. Here&amp;#8217;s an example of what not to do from &lt;a href='http://nodejs.org/jsconf.pdf'&gt;Ryan&amp;#8217;s presentation at JSConf this year&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;result&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT..&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ryan asks a simple question, &amp;#8220;What is the software doing while it queries the database?&amp;#8221; Well, with most libraries it is doing nothing, it is just sitting there waiting for the database to do its thing. This is inefficient. An evented library uses callbacks, so instead of waiting for the database to return, it does some other computation, and then when the database query is done, it calls the callback function. Here&amp;#8217;s Ryan&amp;#8217;s example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT..&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;result&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; 
  &lt;span class='c1'&gt;// use result&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is pretty straight forward but what if you need to make a second database call depending on the result of the first one, and then use both those results? You&amp;#8217;d get something like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT..&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;result1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; 
  &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT..&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;result2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='c1'&gt;// use both results here&lt;/span&gt;
  &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And what if you need to load in a template file (which would mean reading the file from disk) and use that template to format your results?&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT..&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;result1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; 
  &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT..&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;result2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;templates&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;load&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;file-name&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;template&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='c1'&gt;// use both results and the template here&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
  &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There is an additional problem here. How do you keep track of state between all these different functions? In the previous example it is easy because a function is aware of all the local variables that exist at the time it is created, so the last function has access to &lt;code&gt;result1&lt;/code&gt; and &lt;code&gt;result2&lt;/code&gt; but this isn&amp;#8217;t always the case. Especially if you are trying to reuse functions in different parts of the app.&lt;/p&gt;

&lt;p&gt;This is very quickly getting unwieldy. And thus far none of the Node frameworks have addressed this issue head on. There have been some talks on the mailing list of adding &lt;a href='http://api.dojotoolkit.org/jsdoc/1.3.2/dojo.Deferred'&gt;deferred&lt;/a&gt; objects to Node and I think many people hope that this is going to solve the problem of writing evented web frameworks. While I think deferreds would be awesome, I think the solution needs to be a little more integrated then that.&lt;/p&gt;

&lt;h2 id='bomber_actions'&gt;Bomber Actions&lt;/h2&gt;

&lt;p&gt;(Note, this is the API I plan to implement in Bomber, but not all of it is completely written yet. Some of it though!)&lt;/p&gt;

&lt;p&gt;In Bomber, the solution is &lt;code&gt;Action&lt;/code&gt; objects, which have deferred functionality, but are a little more aware of the problem they are trying to address. Specifically, an &lt;code&gt;Action&lt;/code&gt; has a list of tasks that should be run to complete the action. And just like with deferreds, the result of a previous task is passed to the next task. This way it is easy chain functions to be run after one another. However, (and this is the real bread and butter of &lt;code&gt;Action&lt;/code&gt;s) unlike with deferreds (at least as far as I can tell) if the return result of a previous task is itself a deferred (or a Promise in Node-speak), the &lt;code&gt;Action&lt;/code&gt; will wait for that deferred to finish its task before calling the next task. Now you can chain up all your tasks, and not worry about the asynchronicity of the different parts.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Action&lt;/code&gt; objects have a couple other tricks up their sleeves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They will make sure that all tasks are bound to the action object itself, so you can keep track of state between tasks by setting variables on &lt;code&gt;this&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;Every task will be called with the request and the response for that &lt;code&gt;Action&lt;/code&gt; as the first two arguments. This makes it easy to access those objects so you can get/set cookies, sessions or headers.&lt;/li&gt;

&lt;li&gt;If any task returns a certain kind of object (like a &amp;#8216;404 error&amp;#8217; object &amp;#8211; I haven&amp;#8217;t decided what to call it, yet) Node will stop running the tasks for that &lt;code&gt;Action&lt;/code&gt; and send that as the response for this request.&lt;/li&gt;

&lt;li&gt;If the result of the last task is a string or an object, Node assumes you want to use this value for the body of the request. If it is a string it assumes it is HTML and if it is any thing other than either a string or one of the objects in the previous bullet point, it converts it to JSON and sends that. This allows you to easily construct simple responses, but if you want more control you can just return &lt;code&gt;null&lt;/code&gt; and manage it yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is how the Server initializes an &lt;code&gt;Action&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;action&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;Action&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;response&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;view_function&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='nx'&gt;action&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;start&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then a possible &lt;code&gt;view_function&lt;/code&gt; could look like this (to tackle the example from the section on evented programming):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;view_function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;response&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='c1'&gt;// in this case the db.query function is assumed to return a deferred object&lt;/span&gt;
  &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addTask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;response&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT...&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt; 
  &lt;span class='p'&gt;});&lt;/span&gt;

  &lt;span class='c1'&gt;// the next task is called with the result from the previous deferred object&lt;/span&gt;
  &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addTask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;response&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;result1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;result1&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;result1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SELECT...&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt; 
  &lt;span class='p'&gt;});&lt;/span&gt;

  &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addTask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;response&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;result2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;result2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;result2&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='c1'&gt;// I&amp;#39;m assuming templates.load is a deferred object as well...&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;templates&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;load&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;file-name&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
  &lt;span class='p'&gt;});&lt;/span&gt;

  &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;addTask&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;response&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;template&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='c1'&gt;// use both results and the template here&lt;/span&gt;
  &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, I admit that at this point this looks like it might have been more work. But I guess I am going to have to try it out some to really see. I think this potentially could allow for better use of &lt;abbr title='Don&amp;apos;t Repeat Yourself'&gt;DRY&lt;/abbr&gt; programming because now it is trivial to use predeclared javascript functions as opposed to anonymous ones. That with the additional benefit of being able to return 404 errors or 3xx redirects at any point in that process will make this pretty handy.&lt;/p&gt;

&lt;p&gt;I have one more post planned about this Bomber design stuff but it might be a little while before I get to it. (I need to figure out how I want templating to work before I can write it! But I have some ideas&amp;#8230;)&lt;/p&gt;</content>
	</entry>
	
	<entry>
    <title>On the Interwebs, number 16</title>
		<link href="http://benjaminthomas.org/2009-11-28/on-the-interwebs-16.html"/>
		<updated>2009-11-28T00:00:00-07:00</updated>
    <id>tag:benjaminthomas.org,2009-10-22:/2009-11-28/on-the-interwebs-16</id>
		<content type="html">&lt;p&gt;Some websites I have found interesting recently (in no particular order):&lt;/p&gt;

&lt;p&gt;(Whew! This is a long one! Apparently I waited a little too long to post these!)&lt;/p&gt;

&lt;p&gt;&lt;a href='http://code.quirkey.com/sammy/index.html'&gt;Sammy&lt;/a&gt; &amp;#8212; A &lt;a href='http://www.sinatrarb.com/'&gt;Sinatra&lt;/a&gt; inspired framework for making browser based javascript applications. This is seriously cool. (Don&amp;#8217;t confuse this with server side javascript applications. This is for writing an application that lives entirely in a browser.)&lt;/p&gt;

&lt;p&gt;&lt;a href='http://github.com/mikel/mail'&gt;Mail&lt;/a&gt; &amp;#8212; What appears to be a spectacular Ruby library for checking/sending/generating/parsing emails.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.azarask.in/blog/post/identity-in-the-browser-firefox/'&gt;Identity in the Browser&lt;/a&gt; &amp;#8212; A very cool mockup of what it would look like if logging-in and managing accounts on websites was built into the browser. This feels like a hint of the future. And I can&amp;#8217;t wait! Putting the controls in the URL bar makes perfect sense.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://books.couchdb.org/relax/reference/views-for-sql-jockeys'&gt;View Cookbook for SQL Jockeys&lt;/a&gt; &amp;#8212; An explanation of &lt;a href='http://couchdb.apache.org/'&gt;CouchDB&lt;/a&gt; views for SQL people. Honestly, while this was helpful, I need a lot more examples before I am going to truely get this map/reduce stuff for CouchDB.&lt;/p&gt;

&lt;p&gt;&lt;a href='https://developer.mozilla.org/en/Using_files_from_web_applications'&gt;Using files from web applications&lt;/a&gt; &amp;#8212; Mozilla&amp;#8217;s documentation on a new javascript feature that allows you to access files without having to upload them to a server first. Bit by bit browsers are aquiring the tools to completely replace native apps. I can&amp;#8217;t wait!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://blog.getify.com/2009/11/labjs-new-hotness-for-script-loading/'&gt;LABjs: new hotness for script loading&lt;/a&gt; &amp;#8212; A new library for getting your javascript files to download more quickly. I take a different approach (which is to make sure I am only using 1 javascript file) but this looks pretty useful for larger applications that have lots of dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.notonebit.com/s'&gt;An interesting 404 error&lt;/a&gt; &amp;#8212; Seems like it would only be interesting to people who are familiar with HTTP status codes, though.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;And now some &lt;a href='http://nodejs.org/'&gt;Node.js&lt;/a&gt; links (I&amp;#8217;m grouping them here in case you aren&amp;#8217;t interested in my latest obsession):&lt;/p&gt;

&lt;p&gt;&lt;a href='http://jsconf.eu/2009/video_nodejs_by_ryan_dahl.html'&gt;Video: Node.js by Ryan Dahl&lt;/a&gt;: Video of the talk whose &lt;a href='/2009-11-18/on-the-interwebs-15.html#p_nth_2'&gt;slides I linked to last week&lt;/a&gt;. The talk honestly doesn&amp;#8217;t add that much to the slides (he did some good work with those!) but it is really fun to put a face to the person.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://github.com/danwrong/restler'&gt;restler&lt;/a&gt; &amp;#8212; A super simple library for making HTTP requests from Node. I don&amp;#8217;t need this currently, but this looks like everything I would want.&lt;/p&gt;</content>
	</entry>
	

</feed>

