<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Kickass Labs</title>
	
	<link>http://www.kickasslabs.com</link>
	<description>We ♥ code.</description>
	<lastBuildDate>Tue, 15 May 2012 13:22:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/KickassLabs" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="kickasslabs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>QuickHits: The great browser data storage debate</title>
		<link>http://www.kickasslabs.com/2012/05/15/quickhits-the-great-browser-data-storage-debate/</link>
		<comments>http://www.kickasslabs.com/2012/05/15/quickhits-the-great-browser-data-storage-debate/#comments</comments>
		<pubDate>Tue, 15 May 2012 13:20:36 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Quick Hits]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=890</guid>
		<description><![CDATA[My new hiccup with &#8220;Comment On The Movies: A Backbone.js tutorial&#8221;, has been deciding how to store our comments.  At first I was simply going to use localStorage.  It&#8217;s supported by multiple modern browsers (albeit inconsistently) &#38; gets the job done.  The &#8230; <a href="http://www.kickasslabs.com/2012/05/15/quickhits-the-great-browser-data-storage-debate/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My new hiccup with &#8220;<a href="http://commentonthemovies.heroku.com/" target="_blank">Comment On The Movies:</a> A Backbone.js tutorial&#8221;, has been deciding how to store our comments.  At first I was simply going to use localStorage.  It&#8217;s <a href="http://caniuse.com/namevalue-storage" target="_blank">supported by multiple modern browsers</a> (albeit inconsistently) &amp; gets the job done.  The api to use it is also easy to undertand which is good for a tutorial.</p>
<p>Everything was fine&#8230;until I saw the <a href="http://html5please.com/#localStorage" target="_blank">localStorage entry</a> on <a href="http://html5please.com/" target="_blank">html5please.com</a>.  Did you know there was such a heated debate to <a href="http://hacks.mozilla.org/2012/03/there-is-no-simple-solution-for-local-storage/" target="_blank">stop using localStorage</a> and <a href="http://paul.kinlan.me/we-need-to-kill-off-the-localstorage-api/" target="_blank">start using IndexDB in tutorials</a>?  I certainly didn&#8217;t.  Suddenly, I was torn!  Do I use the simple solution with limitations OR a robust solution that&#8217;s <a href="http://caniuse.com/#search=indexd" target="_blank">not fully supported</a> (I expected more from you, Safari)?</p>
<p>Then it hit me; this is the web.  As with any web project, let&#8217;s implement the what&#8217;s right and provide support for browsers that haven&#8217;t made it up to us yet.  Therefore, the default storage option in this tutorial will be IndexedDB with a fall back to localStorage.</p>
<p>(Technically, WebSQL is also an option, but <a href="http://caniuse.com/#search=websql" target="_blank">it&#8217;s support/implementation issues</a>.  In addition, it&#8217;s <a href="http://www.w3.org/TR/webdatabase/" target="_blank">spec has been abandoned</a> by the W3C so it&#8217;s off the table.)</p>
<p>The tutorial rolls on!</p>
<p>Happy Coding<br />
-a</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2012%2F05%2F15%2Fquickhits-the-great-browser-data-storage-debate%2F&amp;title=QuickHits%3A%20The%20great%20browser%20data%20storage%20debate" id="wpa2a_2"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2012/05/15/quickhits-the-great-browser-data-storage-debate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Why Can’t I Call the Methods on This Objective-C Category?</title>
		<link>http://www.kickasslabs.com/2012/05/07/quick-hits-why-cant-i-call-the-methods-on-this-objective-c-category/</link>
		<comments>http://www.kickasslabs.com/2012/05/07/quick-hits-why-cant-i-call-the-methods-on-this-objective-c-category/#comments</comments>
		<pubDate>Mon, 07 May 2012 18:14:59 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Quick Hits]]></category>
		<category><![CDATA[Xcode]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[objc]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=877</guid>
		<description><![CDATA[The scenario: You have a category on a common class &#8211; like say, AFNetworking&#8216;s category to make UIImageView load images asynchronously from a URL. The category source lives in a static library that you&#8217;re linking into your main project. (You &#8230; <a href="http://www.kickasslabs.com/2012/05/07/quick-hits-why-cant-i-call-the-methods-on-this-objective-c-category/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The scenario:  You have a category on a common class &#8211; like say, <a href="https://github.com/AFNetworking/AFNetworking" target="afnetworking">AFNetworking</a>&#8216;s category to make UIImageView load images asynchronously from a URL.  The category source lives in a static library that you&#8217;re linking into your main project.  (You may, as I do, have the library as a subproject of your actual project.)  You attempt to call a method on the category, and you get the dreaded <tt>"unrecognized selector sent to instance".</tt>  You <i>know</i> you&#8217;re linking the file into the static library correctly, and that you&#8217;re linking the static library into your project.</p>
<p>Before you commence wailing and gnashing your teeth, add <tt>-all_load</tt> to the &#8220;Other Linker Flags&#8221; build setting in your main project.  Worked for me.</p>
<p>Thanks are due to Dave DeLong for answering <a href="http://stackoverflow.com/questions/3998483/objective-c-category-causing-unrecognized-selector" target="so3998483">this SO question</a>, because otherwise I&#8217;d have probably spent the rest of the day wailing, gnashing my teeth, and ignorantly trying build options until something worked.</p>
<p>Note that the <a href="http://developer.apple.com/library/mac/#qa/qa1490/_index.html" target="appledocs">relevant docs</a> make this feel kind of kludgy &#8211; but I need software that works today, you know?</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2012%2F05%2F07%2Fquick-hits-why-cant-i-call-the-methods-on-this-objective-c-category%2F&amp;title=Quick%20Hits%3A%20Why%20Can%26%238217%3Bt%20I%20Call%20the%20Methods%20on%20This%20Objective-C%20Category%3F" id="wpa2a_4"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2012/05/07/quick-hits-why-cant-i-call-the-methods-on-this-objective-c-category/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Where’s my Backbone.js Tutorial?</title>
		<link>http://www.kickasslabs.com/2012/04/28/quick-hits-wheres-my-backbone-js-tutorial/</link>
		<comments>http://www.kickasslabs.com/2012/04/28/quick-hits-wheres-my-backbone-js-tutorial/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 15:28:29 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Process]]></category>
		<category><![CDATA[Quick Hits]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=852</guid>
		<description><![CDATA[You may be asking this question if you&#8217;ve started down this road (part1 &#38; part2) with me a *year ago.  Since the tutorial started, Backbone.js has changed and matured: The &#8220;Controller&#8221; is now called the &#8220;Router&#8221;. HTML5 PushState New Backbone.sync &#8230; <a href="http://www.kickasslabs.com/2012/04/28/quick-hits-wheres-my-backbone-js-tutorial/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div id="attachment_854" class="wp-caption alignnone" style="width: 650px"><a href="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/double-facepalm.jpg" rel="lightbox[852]"><img class="size-full wp-image-854" title="double-facepalm" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/double-facepalm.jpg" alt="" width="640" height="512" /></a><p class="wp-caption-text">An entire freaking year!? Ugh!</p></div>
<p><span id="more-852"></span>You may be asking this question if you&#8217;ve started down this road (<a title="Yet Another Backbone.js Tutorial – Part 1 – Backbone.js Philosophy" href="http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/" target="_blank">part1</a> &amp; <a title="Yet Another Backbone.js Tutorial – Part 2 – Pre-Reqs &amp; The Spec" href="http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/" target="_blank">part2</a>) with me a *year ago.  Since the tutorial started, <a href="http://documentcloud.github.com/backbone/#" target="_blank">Backbone.js</a> has changed and matured:</p>
<ul>
<li>The &#8220;Controller&#8221; is now called the &#8220;Router&#8221;.</li>
<li>HTML5 PushState</li>
<li>New Backbone.sync params</li>
<li>The handy View.$el</li>
<li>View.setElement() to explicitly set View.el</li>
<li>Multiple **random version number updates (0.3s =&gt; 0.5s =&gt; 0.9s)</li>
</ul>
<p>&#8230;including <a href="http://documentcloud.github.com/backbone/#changelog" target="_blank">a bunch of features, improvements</a>, &amp; <a href="https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources" target="_blank">plugins to extend structure/framework</a>.</p>
<p>I&#8217;ve also learned a lot over this past year:</p>
<ul>
<li>I&#8217;ve figured out better design patterns to use when creating Backbone apps.</li>
<li>Tutorials stand at a specific point in time.  When things change, I can write new revised tutorials <a href="http://railscasts.com/?type=revised" target="_blank">RailsCast</a> style.</li>
<li>I don&#8217;t have to cover every single part of Backbone.js in order to have a good tutorial.</li>
</ul>
<p>With all of that said, the get ready for some action.  I&#8217;m&#8230;</p>
<ol>
<li>upgrading the tutorial app to 0.9.2</li>
<li>revamping the tutorial app with the new design patterns that I&#8217;ve figured out</li>
<li>writing the post explaining the new implementation &amp; only worrying about the important details concerning the implementation.</li>
</ol>
<p>So for those of you who have stuck around this long, I say &#8220;Sorry for the lag &amp; the goods are coming&#8221;</p>
<p>Happy Coding</p>
<hr />
<p>* Giant Double Facepalm on how long this tutorial&#8217;s gone on.  I just realized that it&#8217;s been a year.</p>
<p>** I had a chance to ask Jeremy Ashkenas (<a href="https://twitter.com/#!/jashkenas" target="_blank">@jashkenas</a>; creator of Backbone.js and more) about this when he came to <a href="http://www.meetup.com/NYCBackbone/events/54583402/" target="_blank">NYCBackbone&#8217;s first meetup</a>.  He said that weren&#8217;t following any version numbering patterns for anything under 1.0</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2012%2F04%2F28%2Fquick-hits-wheres-my-backbone-js-tutorial%2F&amp;title=Quick%20Hits%3A%20Where%26%238217%3Bs%20my%20Backbone.js%20Tutorial%3F" id="wpa2a_6"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2012/04/28/quick-hits-wheres-my-backbone-js-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails Conf 2012 – Images</title>
		<link>http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/</link>
		<comments>http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 04:31:42 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=800</guid>
		<description><![CDATA[I got to talk &#38; take pictures with some of my Ruby/Rails heroes while at RailsConf.  If you click on a picture, you can hop to a detail page with an option to download the full rez image.]]></description>
			<content:encoded><![CDATA[<p>I got to talk &amp; take pictures with some of my Ruby/Rails heroes while at RailsConf.  If you click on a picture, you can hop to a detail page with an option to download the full rez image.<span id="more-800"></span></p>

<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0290/' title='RailsConf2012 - Lobby'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0290-150x150.jpg" class="attachment-thumbnail" alt="That&#039;s how we kick things off! :)" title="RailsConf2012 - Lobby" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0293/' title='RailsConf2012 - Hulu Legos'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0293-150x150.jpg" class="attachment-thumbnail" alt="Yeah, Hulu Legos" title="RailsConf2012 - Hulu Legos" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0298/' title='RailsConf2012 - The Ruby Rogues'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0298-150x150.jpg" class="attachment-thumbnail" alt="The boys are back in town (@rubyrogues)" title="RailsConf2012 - The Ruby Rogues" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/photo-4/' title='RailsConf2012 - Dr. Nic'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/photo-4-e1335574947798-150x150.jpg" class="attachment-thumbnail" alt="The Dr. is IN (@drnic)" title="RailsConf2012 - Dr. Nic" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0294/' title='RailsConf2012 - Jim Weirich'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0294-150x150.jpg" class="attachment-thumbnail" alt="Jim Weirich&#039;s (@jimweirich) the friendliest man ever!" title="RailsConf2012 - Jim Weirich" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0299/' title='RailsConf2012 - Steve Klabnik'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0299-150x150.jpg" class="attachment-thumbnail" alt="Rocking with Ruby Hero Steve Klabnik (@steveklabnik)" title="RailsConf2012 - Steve Klabnik" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0300/' title='RailsConf2012 - Michael Hartl'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0300-150x150.jpg" class="attachment-thumbnail" alt="&quot;Ruby on Rails Tutorial&quot; Creator, Theoretical Physicist, &amp; Ruby Hero, Michael Hartl (@mhartl)" title="RailsConf2012 - Michael Hartl" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0301/' title='RailsConf2012 - Yehuda Katz'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0301-150x150.jpg" class="attachment-thumbnail" alt="Yehuda Katz (@wycats) getting mobbed" title="RailsConf2012 - Yehuda Katz" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0296/' title='RailsConf2012 - James Edward Gray II'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0296-150x150.jpg" class="attachment-thumbnail" alt="Hanging with James Edward Gray II (@jeg2)" title="RailsConf2012 - James Edward Gray II" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0304/' title='RailsConf2012 - Aaron Patterson &amp; Josh Susser'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0304-150x150.jpg" class="attachment-thumbnail" alt="Aaron Patterson (@tenderlove) &amp; Josh Susser (@joshsusser) Being Awesome" title="RailsConf2012 - Aaron Patterson &amp; Josh Susser" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0302/' title='RailsConf2012 - Aaron Patterson &amp; Josh Susser &amp; Me'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0302-150x150.jpg" class="attachment-thumbnail" alt="Aaron, Josh, &amp; I play it cool" title="RailsConf2012 - Aaron Patterson &amp; Josh Susser &amp; Me" /></a>
<a href='http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0303/' title='RailsConf2012 - Aaron Patterson &amp; Josh Susser &amp; Me 2'><img width="150" height="150" src="http://www.kickasslabs.com/~kal_www/kickasslabs.com/wp-content/uploads/2012/04/100_0303-150x150.jpg" class="attachment-thumbnail" alt="Aaron, Josh, &amp; I play it whacky!" title="RailsConf2012 - Aaron Patterson &amp; Josh Susser &amp; Me 2" /></a>

<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2012%2F04%2F28%2Frails-conf-2012-images%2F&amp;title=Rails%20Conf%202012%20%26%238211%3B%20Images" id="wpa2a_8"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails Conf 2012 – Thoughts</title>
		<link>http://www.kickasslabs.com/2012/04/27/rails-conf-2012-thoughts/</link>
		<comments>http://www.kickasslabs.com/2012/04/27/rails-conf-2012-thoughts/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 01:04:20 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=792</guid>
		<description><![CDATA[This year was my first RailsConf. For those that don&#8217;t know, RailsConf is &#8220;THE&#8221; Rails conference that brings people in from around the world. It features keynotes &#38; focused talks by the brightest stars in the Rails universe. It&#8217;s story &#8230; <a href="http://www.kickasslabs.com/2012/04/27/rails-conf-2012-thoughts/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This year was my first <a href="http://railsconf2012.com/" target="_blank">RailsConf</a>. For those that don&#8217;t know, RailsConf is &#8220;THE&#8221; Rails conference that brings people in from around the world. It features keynotes &amp; focused talks by the brightest stars in the Rails universe. It&#8217;s story time. <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-792"></span></p>
<p>Before this point, I&#8217;ve only watched keynotes like these:</p>
<ul>
<li><a href="http://www.youtube.com/watch?v=cGdCI2HhfAU" target="_blank">RailsConf 2011, David Heinemeier Hansson</a></li>
<li><a href="http://www.youtube.com/watch?v=kWOAHIpmLAI" target="_blank">RailsConf 2011, Aaron Patterson, &#8220;Double Dream Hands: So Intense!&#8221;</a></li>
<ul>
<li>The ending of this video is important for later.</li>
</ul>
<li><a href="http://www.youtube.com/watch?v=OJ8YfstVWKs" target="_blank">RailsConf 2011: Dr. Nic Williams, &#8220;Ruby Through the Ages&#8221;</a></li>
<li><a href="http://www.youtube.com/watch?v=EqZFMaN6Vx0&amp;feature=relmfu" target="_blank">RailsConf 2011: Ruby Heroes Awards</a></li>
<li><a href="http://www.youtube.com/watch?v=5OFxsarfSxI&amp;feature=relmfu" target="_blank">RailsConf 2011: Corey Haines</a></li>
<li><a href="http://www.youtube.com/watch?v=mo-lMdQMsdw" target="_blank">RailsConf 2010: Yehuda Katz</a></li>
<li><a href="http://www.youtube.com/watch?v=YX3iRjKj7C0" target="_blank">RailsConf 2009: What Killed Smalltalk Could Kill Ruby, Too</a></li>
</ul>
<p>&#8230; and so on &amp; so on.</p>
<p>Sentiments like &#8220;I love Ruby&#8221;, &#8220;<strong>Impossible</strong> is a relative thing&#8221;, &#8220;We&#8217;re going to make rails faster by reducing the stack&#8221;, &#8220;We&#8217;re all awesome in our own way&#8221; are all over these videos.</p>
<p>This year&#8217;s first 2 keynotes had a very different tone. For starters, <a href="http://www.youtube.com/watch?feature=player_embedded&amp;v=VOFTop3AMZ8#!" target="_blank">DHH&#8217;s talk</a> was about &#8220;the skeptical developer&#8221; &amp; &#8220;progress&#8221; and had the following points in it:</p>
<ul>
<li>Don&#8217;t be afraid of change</li>
<li>Don&#8217;t overreact to change</li>
<li>Life will change</li>
<li>Rails will change</li>
</ul>
<p>&#8230;and this point was really hammered home when DHH everyone to read his final slide aloud, mantra-style:</p>
<p>&#8220;I will not fear change, I will not fight progress&#8221;</p>
<p>I realized the decisions like the asset pipeline &amp; defaulting coffee script but not defaulting haml have been controversial. I can understand where he&#8217;s coming from. I also understand some of his responsibilities as the creator of Rails to ensure that people are serious about the platform and where it&#8217;s heading.</p>
<p>Though I was excited to see DHH, I was really excited about seeing Aaron Patterson&#8217;s keynote. I mean, did you see the &#8220;Double Dream Hands&#8221; video from last year? This year, Aaron&#8217;s talk was way more serious and ended with a slide that simply said:</p>
<p>&#8220;We need to be prepared&#8221;</p>
<p>I don&#8217;t know if you follow Aaron on twitter, <a href="https://twitter.com/#!/tenderlove" target="_blank">@tenderlove</a> btw, but it seemed like a large departure from his standard jovial self. I mean, this is the <a href="https://twitter.com/#!/search/%23fridayhug" target="_blank">#fridayhug</a> guy! In December of 2011, the Rails blog stated that <a href="http://weblog.rubyonrails.org/2011/12/20/rails-master-is-now-4-0-0-beta/" target="_blank">the intent for </a><a href="http://weblog.rubyonrails.org/2011/12/20/rails-master-is-now-4-0-0-beta/" target="_blank">Rails 4 (R4) is a smoother transition than upgrading to Rails 3 (R3)</a>. So far things like <a href="http://weblog.rubyonrails.org/2012/3/21/strong-parameters/" target="_blank">strong parameters</a> &amp; <a href="http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/" target="_blank">using patch for updates</a> doesn&#8217;t seem that scary, but the RailsConf keynotes would have you believe that something is on the horizon in R4 that might be a litte shocking.</p>
<p>Even if the changes in R4 are large departures, they&#8217;ll take us to places we want to (or perhaps need to) be. In addition, the existence of R4 doesn&#8217;t undo the great framework that R3 has become. Josh Susser (<a href="https://twitter.com/#!/joshsusser" target="_blank">@joshsusser</a>; one of the <a href="https://twitter.com/#!/rubyrogues" target="_blank">@rubyrogues</a> and all around great guy) <a href="http://speakerdeck.com/u/joshsusser/p/ruby-rogues-live" target="_blank">has a really good &amp; concise slide deck on prudence in which he says</a>:</p>
<p>&#8220;I have a limited budget for risk in my projects [&amp;] I hate having other people spend my risk budget for me&#8221;</p>
<p>I completely agree with Josh. Fortunately, even though my production budget is super tight, my &#8220;personal time&#8221; budget has wiggle room. When R4 comes out, I&#8217;m not going to flip our production servers to it on the first day. I WILL, however, start using it ASAP in personal projects. I&#8217;ll also soak up resources from <a href="http://railscasts.com/" target="_blank">RailsCasts</a> &amp; <a href="https://www.destroyallsoftware.com/" target="_blank">Destroy All Software</a>. Basically I&#8217;ll do what I&#8217;ve always done to stay current. Thousands of other Rails developers will be doing the same. Rails is an exciting and moves fast and we&#8217;re all on board.</p>
<p>The second day of RailsConf had an impromptu panel which featured Aaron Patterson, Yehuda Katz(<a href="https://twitter.com/#!/wycats" target="_blank">@</a><a href="https://twitter.com/#!/wycats" target="_blank">wycats</a>), Santiago Pastorino(<a href="https://twitter.com/#!/spastorino" target="_blank">@spastorino</a>), &amp; Jim Weirich(<a href="https://twitter.com/#!/jimweirich" target="_blank">@jimweirich</a>). The serious tone of the keynotes had time to marinate inside me. When Even Phoenix (<a href="https://twitter.com/#!/evanphx" target="_blank">@evanphx</a>; this years MC) opened the floor for questions, I stepped up to find out what happened to Aaron &amp; the keynote.</p>
<p>When I finally got my chance to ask my question, my fandom started bleeding through my words. I&#8217;m a fan of everyone sitting on the panel who make it possible for me to do what I do. I&#8217;m a fan of RailsConf &amp; how much I knowledge I&#8217;m taking back home with me. Most importantly, I&#8217;m a fan of the rails community and how empowered I feel to be a part of it.</p>
<p>If I had the moment to do over again, I&#8217;d have reminded Aaron that we&#8217;re all here to work together. I&#8217;d also toss in a line like &#8220;Change isn&#8217;t bad news, it&#8217;s just new. New things can rock too&#8221;. I&#8217;ll have to hope my hug said it all. <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2012%2F04%2F27%2Frails-conf-2012-thoughts%2F&amp;title=Rails%20Conf%202012%20%26%238211%3B%20Thoughts" id="wpa2a_10"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2012/04/27/rails-conf-2012-thoughts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Agile vs. No Silver Bullet</title>
		<link>http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/</link>
		<comments>http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 16:48:23 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[Process]]></category>
		<category><![CDATA[Quick Hits]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=770</guid>
		<description><![CDATA[I&#8217;ve been returning to my source materials on Agile software development/project management methods recently, just to stay fresh. As part of my study, I ran across a blog post (more of a petulant rant, actually) that cites (actually, mentions in &#8230; <a href="http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been returning to my source materials on Agile software development/project management methods recently, just to stay fresh.  As part of my study, I ran across a blog post (more of a petulant rant, actually) that cites (actually, mentions in passing, with no real justification) the classic Fred Brooks essay <a href="http://en.wikipedia.org/wiki/No_Silver_Bullet" title="No Silver Bullet" target="nsb"><i>No Silver Bullet</i></a> in support of the assertion that big-A Agile methods cannot possibly be better than other ways of getting software delivered.  Besides suffering from the fallacy of appeal to authority (however meritorious Mr. Brooks&#8217;s authority in our field might be), it also falls a bit flat to cite <i>NSB</i> in an anti-Scrum screed. To wit:</p>
<blockquote><p>Incremental development&#8211;grow, don&#8217;t build, software. I still remember the jolt I felt in 1958 when I first heard a friend talk about building a program, as opposed to writing one. In a flash he broadened my whole view of the software process. The metaphor shift was powerful, and accurate. Today we understand how like other building processes the construction of software is, and we freely use other elements of the metaphor, such as specifications, assembly of components, and scaffolding.</p>
<p>The building metaphor has outlived its usefulness. It is time to change again. If, as I believe, the conceptual structures we construct today are too complicated to be specified accurately in advance, and too complex to be built faultlessly, then we must take a radically different approach.</p>
<p>Let us turn nature and study complexity in living things, instead of just the dead works of man. Here we find constructs whose complexities thrill us with awe. The brain alone is intricate beyond mapping, powerful beyond imitation, rich in diversity, self-protecting, and selfrenewing. The secret is that it is grown, not built.</p>
<p>So it must be with our software-systems. Some years ago Harlan Mills proposed that any software system should be grown by incremental development. That is, the system should first be made to run, even if it does nothing useful except call the proper set of dummy subprograms. Then, bit by bit, it should be fleshed out, with the subprograms in turn being developed&#8211;into actions or calls to empty stubs in the level below.</p>
<p>I have seen most dramatic results since I began urging this technique on the project builders in my Software Engineering Laboratory class. Nothing in the past decade has so radically changed my own practice, or its effectiveness. The approach necessitates top-down design, for it is a top-down growing of the software. It allows easy backtracking. It lends itself to early prototypes. Each added function and new provision for more complex data or circumstances grows organically out of what is already there.</p>
<p>The morale effects are startling. Enthusiasm jumps when there is a running system, even a simple one. Efforts redouble when the first picture from a new graphics software system appears on the screen, even if it is only a rectangle. One always has, at every stage in the process, a working system. I find that teams can grow much more complex entities in four months than they can build.</p></blockquote>
<p>(The above is, of course, excerpted from Brooks&#8217;s essay.)</p>
<p>Iterative development that delivers frequent releases of working software, and uses feedback to determine the direction of growth for the next increment? And a report of empirical (if decidedly anecdotal) support for the notion?</p>
<p>Sounds pretty Agile to me.</p>
<p>(The full essay is available in <i><a href="http://www.amazon.com/gp/product/0201835959/ref=as_li_ss_tl?ie=UTF8&#038;tag=bradandkristshom&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0201835959" target="mmm">The Mythical Man-Month: Essays on Software Engineering</a><img src="http://www.assoc-amazon.com/e/ir?t=bradandkristshom&#038;l=as2&#038;o=1&#038;a=0201835959" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />,</i> which I recommend to anyone who writes, builds, grows, or otherwise makes software.)</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F12%2F28%2Fagile-vs-no-silver-bullet%2F&amp;title=Agile%20vs.%20No%20Silver%20Bullet" id="wpa2a_12"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/12/28/agile-vs-no-silver-bullet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yet Another Backbone.js Tutorial – Part 2 – Pre-Reqs &amp; The Spec</title>
		<link>http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/</link>
		<comments>http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/#comments</comments>
		<pubDate>Sun, 27 Nov 2011 04:50:01 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[underscore.js]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=529</guid>
		<description><![CDATA[Please checkout Part 1 where I explain the philosophy behind Backbone.js It&#8217;s time to build our Backbone.js app, &#8220;Comment on the Movies&#8221;.  This tutorial will, ideally, give you something interesting to build.  Take a look at the finished app (so far) on &#8230; <a href="http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em><a title="Yet Another Backbone.js Tutorial – Part 1 – Backbone.js Philosophy" href="http://www.kickasslabs.com/2011/04/16/yet-another-backbone-js-tutorial-part-1-backbone-js-philosophy/">Please checkout <strong>Part 1</strong> where I explain the philosophy behind Backbone.js</a></em></p>
<p>It&#8217;s time to build our Backbone.js app, &#8220;Comment on the Movies&#8221;.  This tutorial will, ideally, give you something interesting to build.  Take a look at <strong><a href="http://commentonthemovies.heroku.com" target="_blank">the finished app (so far) on Heroku</a></strong> &amp; feel free to <strong><a href="https://github.com/abelmartin/Comment-On-The-Movies/tree/KAL_Post_Part_2" target="_blank">pull it from GitHub</a></strong>.  In addition, I&#8217;ve updated the code to use Backbone.js 0.5.3, Underscore 1.2.2, Mustache 0.3 &amp; jQuery 1.7.1.  Let&#8217;s do this!<span id="more-529"></span></p>
<p>*Before we get started, check out one more resource: Charlie Robbins (Co-Founder of <a href="http://nodejitsu.com/" target="_blank">Nodejitsu</a>) wrote an awesome article about <a href="http://blog.nodejitsu.com/scaling-isomorphic-javascript-code" target="_blank">Scaling Isomorphic Javascript Code</a>.  In the writeup, he describes popular methodologies in retrieving data and presenting it to the user.  It&#8217;s a great read.  The image below from that article:</p>
<div class="wp-caption aligncenter" style="width: 450px"><img src="http://blog.nodejitsu.com/scaling-isomorphic-javascript-code/mvvm.png" alt="" width="440" height="369" /><p class="wp-caption-text">Backbone.js interactions: Model-View-ViewModel</p></div>
<h2>Prerequisites:  Rotten Tomatoes API Account, Ruby, Sinatra, &amp; Haml</h2>
<h3>Rotten Tomatoes API Account</h3>
<p>The app we&#8217;re writing is called &#8220;Comment On The Movies&#8221;.  The RottenTomatoes API is full of well formed data (which is more than I can say about the New York Times movie api calls).  Real data is always more interesting than building dummy datasets ourselves.</p>
<p><strong><a href="http://developer.rottentomatoes.com/" target="_blank">The Rotten Tomatoes API registration is free, quick &amp; painless</a></strong>.  Get your api_key &amp; come back to this tutorial.</p>
<p>We&#8217;ll also be using <strong><a href="http://images.rottentomatoes.com/assets.html" target="_blank">the R.T. assets</a></strong>.  R.T. makes their images available to developers to use in their apps and we&#8217;ll be taking advantage.</p>
<h3>Ruby (<a href="http://www.ruby-lang.org/en/" target="_blank">Project Site</a>)</h3>
<p>Realistically, if you&#8217;re reading this webpage, you probably already have it installed (even if you don&#8217;t use it) <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> .  I chose Ruby here because I 9-5 in Ruby and I really enjoy it.  You can use ANY server side scripting language here (PHP, Asp.NET, JSP), but <span style="text-decoration: underline;"><strong>you need to use something</strong></span>. You don&#8217;t want to simply expose your R.T. API App Key to the world.  By using a server side language, you can create a proxy page that protects your API App Key.  Here&#8217;s how this app will work:</p>
<ol>
<li>Your Backbone app makes an AJAX call with R.T. API parameters to the proxy page</li>
<li>The proxy page appends your API_KEY &amp; makes the call to a R.T. servers</li>
<li>The proxy page receives the response and returns it to your Backbone app</li>
<li>The Backbone app updates it&#8217;s UI.</li>
</ol>
<h3>Sinatra (<a href="http://www.sinatrarb.com/intro" target="_blank">Project Site</a>)</h3>
<p>Since we only need an index page and a proxy, Sinatra is a perfect option here.  A full Rails app would be WAY too much.</p>
<h3>Haml (<a href="http://haml-lang.com/" target="_blank">Project Site</a>)</h3>
<p>I enjoy haml.  It&#8217;s really easy to create markup with it.</p>
<h2>The &#8220;Comment on the Movies&#8221; Spec</h2>
<p>Here&#8217;s what the app needs to accomplish:<br />
<span style="color: #ff6600;">**Items in orange will be implemented in future tutorial posts**</span></p>
<ul>
<li>Users should be able to switch between the various lists of R.T. data:</li>
<ul>
<li>Box Office (default view on page load)</li>
<li>In Theaters</li>
<li>Opening</li>
<li>Upcoming</li>
</ul>
<li>The &#8220;Movies Table&#8221; should display:
<ul>
<li>Title</li>
<li>Year</li>
<li>MPAA Rating (R, PG-13, etc)</li>
<li>Runtime</li>
<li>Release Date (default sort)</li>
<li>Critic&#8217;s Score</li>
<ul>
<li>If it&#8217;s &#8216;certified fresh&#8217; that should be indicated.</li>
</ul>
<li><span style="color: #ff6600;">Number of comments</span></li>
</ul>
</li>
<li><span class="Apple-style-span" style="color: #000000;">Clicking on a table column title should sort the current set of movies in the table.</span></li>
<li><span style="color: #ff6600;">Clicking on a movie&#8217;s row should take you to a &#8220;detailed&#8221; view of the film.  The &#8220;detailed&#8221; view should display: </span>
<ul>
<li><span style="color: #ff6600;">Links [all links that lead us away from the site should open in a new window] to&#8230;</span>
<ul>
<li><span style="color: #ff6600;">Showtimes</span></li>
<li><span style="color: #ff6600;">Awards (if any)</span></li>
<li><span style="color: #ff6600;">Trailers</span></li>
<li><span style="color: #ff6600;">Abridged Cast</span></li>
<li><span style="color: #ff6600;">IMDB records</span></li>
</ul>
</li>
</ul>
</li>
<li><span style="color: #ff6600;">Comments </span>
<ul>
<li><span class="Apple-style-span" style="color: #ff6600;">Add a new comment</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Edit an existing comment</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Delete a comment</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Require that the review indicates if the comment is BEFORE or AFTER you&#8217;ve seen the movie</span></li>
<li><span class="Apple-style-span" style="color: #ff6600;">Comments should persists across browser restarts</span></li>
</ul>
</li>
<li>The app needs to be crawl-able by Google.</li>
<li><span style="color: #ff6600;">It needs to be well tested</span></li>
</ul>
<h2>Make your Backbone App Google Crawl-able via hashbang URLs</h2>
<p>Hashbanging (/#!) your URLs let&#8217;s the <a href="http://code.google.com/web/ajaxcrawling/docs/getting-started.html">Google crawling bot know that there&#8217;s AJAXed content on this page</a>.  Fortunately, it&#8217;s really easy in Backbone.js <a href="http://commentonthemovies.heroku.com/" target="_blank">as you can see in the live demo</a></p>
<h2>In The Next Post&#8230;</h2>
<p>I&#8217;ll explain how I implemented the app thus far.  That&#8217;ll include the filling the index view &amp; the hashbang technique mentioned above.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F11%2F27%2Fyet-another-backbone-js-tutorial-%25e2%2580%2593-part-2-%25e2%2580%2593-prereqs-and-the-spec%2F&amp;title=Yet%20Another%20Backbone.js%20Tutorial%20%E2%80%93%20Part%202%20%E2%80%93%20Pre-Reqs%20%26%23038%3B%20The%20Spec" id="wpa2a_14"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/11/27/yet-another-backbone-js-tutorial-%e2%80%93-part-2-%e2%80%93-prereqs-and-the-spec/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Traveling Salesman Attack! (Hadoop and Genetic Algorithms)</title>
		<link>http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/</link>
		<comments>http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 15:49:15 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[hadoop]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Just for Kicks]]></category>
		<category><![CDATA[genetic algorithms]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[traveling salesman]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=669</guid>
		<description><![CDATA[For one of my &#8220;coffee projects&#8221; (things I work on for about 20-30 minutes each morning to warm my brain up and stay amused), I wrote a genetic algorithm attack on the Traveling Salesman problem. Because I&#8217;m a Big Data &#8230; <a href="http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For one of my &#8220;coffee projects&#8221; (things I work on for about 20-30 minutes each morning to warm my brain up and stay amused), I wrote a <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">genetic algorithm</a> attack on the <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">Traveling Salesman problem</a>. Because I&#8217;m a Big Data geek, I parallelized it with <a href="http://hadoop.apache.org">Hadoop</a>.</p>
<p><i>(Note:  I actually gave a talk on this topic some time back, having implemented this same concept in Ruby using Hadoop Streaming.  That implementation contained a number of flaws, some of which I&#8217;m attempting to rectify.  Also, <a href="http://scholar.google.com/scholar?q=hadoop+genetic+algorithm&#038;hl=en&#038;as_sdt=0&#038;as_vis=1&#038;oi=scholart">it&#8217;s not as though I&#8217;m the first guy to work this angle</a>. I haven&#8217;t perused the latest Hadoop/GA work in the field yet, because I wanted to maximize my first-hand learning at this stage &#8211; but I&#8217;ll be looking to other sources for inspiration as I develop and generalize this code.)</i></p>
<p>This was just done for my own edification; I haven&#8217;t put enough effort into tuning this software or studying its properties for this to be considered a serious work of research (yet). I&#8217;m not a specialist or any kind of expert with genetic algorithms, beyond my recreational reading. That said, I had some success at building a gene representation and evolutionary mechanisms that drove a population of solutions for an NP-hard problem toward (mostly) monotonic improvement.</p>
<p>What follows is a brief description of my approach to the problem, with code attached. If you <em>are</em> an expert with GAs, I&#8217;d love to hear your feedback on what I could do better.</p>
<p>I haven&#8217;t spent any effort in this post describing the <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">Traveling Salesman problem</a>, <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">genetic algorithms</a>, or <a href="http://hadoop.apache.org">Hadoop</a>/MapReduce. (It was plenty long already.)  If you&#8217;re interested in any of those topics but need to brush up on the basics, check out the preceding links.</p>
<p>More geekery below the fold&#8230;</p>
<p><span id="more-669"></span></p>
<p><strong>The Map</strong></p>
<p>A &#8220;city&#8221; in my representation is an (x, y) coordinate pair, with each coordinate having a floating-point value in [0.0, 1.0). The software can take any arrangement of cities, but for testing I used an arrangement with a set of trivial solutions:</p>
<table>
<tbody>
<tr>
<td>(0.0, 0.0)</td>
<td>(0.0, 0.2)</td>
<td>(0.0, 0.4)</td>
<td>(0.0, 0.6)</td>
<td>(0.0, 0.8)</td>
</tr>
<tr>
<td>(0.0, 1.0)</td>
<td>(0.2, 1.0)</td>
<td>(0.4, 1.0)</td>
<td>(0.6, 1.0)</td>
<td>(0.8, 1.0)</td>
</tr>
<tr>
<td>(1.0, 1.0)</td>
<td>(1.0, 0.8)</td>
<td>(1.0, 0.6)</td>
<td>(1.0, 0.4)</td>
<td>(1.0, 0.2)</td>
</tr>
<tr>
<td>(1.0, 0.0)</td>
<td>(0.8, 0.0)</td>
<td>(0.6, 0.0)</td>
<td>(0.4, 0.0)</td>
<td>(0.2, 0.0)</td>
</tr>
</tbody>
</table>
<p><strong>Gene Representation</strong></p>
<p>When choosing a non-repeating path among <em>N</em> distinct cities, there are <em>N</em> possible choices for the first city; <em>N-1</em> choices for the second city, and so on; and only one choice for the final city.</p>
<p>In my representation, a chromosome has <em>N &#8211; 1</em> integer genes. For a gene <em>G<sub>n</sub>,</em> valid values are <em>[0, N - n)</em> &#8211; thus, the first gene has <em>N</em> valid values, the second gene <em>N &#8211; 1,</em> and so on. Each gene corresponds to the 0-based index of a city in an ordered collection of the cities not yet accounted for in the path. For example, if we start with an ordered collection of cities <em>{C<sub>0</sub>, C<sub>1</sub>, C<sub>2</sub>},</em> and the chromosome<em> {0, 0}:</em></p>
<ul>
<li>The first city in this candidate solution path is at index 0 in the collection:  <em>C<sub>0</sub></em></li>
<li>The second city in the path is at index 0 in the collection of remaining cities, <em>{C<sub>1</sub>, C<sub>2</sub>}: C<sub>1</sub></em></li>
<li>The final city is trivially <em>C<sub>2</sub></em>.</li>
</ul>
<p>Likewise, the chromosome <em>{1, 1}</em> encodes the path <em>C<sub>1</sub> -&gt; C<sub>2</sub> -&gt; C<sub>0</sub>.</em></p>
<p><strong>Fitness Scoring</strong></p>
<p>Here I&#8217;ve implemented the <i>symmetric</i> Traveling Salesman problem (the distance/cost from <i>C<sub>1</sub></i> to <i>C<sub>2</sub></i> is the same as from <i>C<sub>2</sub></i> to <i>C<sub>1</sub></i>), and the distance between cities is just the Cartesian distance between their coordinates.  The maximum possible distance between any two cities in the landscape I&#8217;ve defined is <em>√<span style="text-decoration: overline;">2</span></em>, so the maximum/worst-case distance possible for an <em>N</em>-city map is <em>(N &#8211; 1) * √<span style="text-decoration: overline;">2</span></em>.</p>
<p>A chromosome&#8217;s score is this worst-case distance minus the actual distance of the path it encodes; thus, the greater the improvement over the theoretically pessimal case, the higher the chromomsome&#8217;s score.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ChromosomeScorer <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">ArrayList</span> cities<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">ArrayList</span> citiesUsed<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">double</span> SQRT2 <span style="color: #339933;">=</span> <span style="color: #003399;">Math</span>.<span style="color: #006633;">sqrt</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2.0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">double</span> maxDistance<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> ChromosomeScorer<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> cityString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        cities <span style="color: #339933;">=</span> getCitiesFromString<span style="color: #009900;">&#40;</span>cityString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        citiesUsed <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span>cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        maxDistance <span style="color: #339933;">=</span> SQRT2 <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            citiesUsed.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">Boolean</span>.<span style="color: #000066; font-weight: bold;">FALSE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">double</span> score<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> chromosomeString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">ArrayList</span> route <span style="color: #339933;">=</span> getRouteFromChromosome<span style="color: #009900;">&#40;</span>chromosomeString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">double</span> distance <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0.0</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cities.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">int</span> city1Index <span style="color: #339933;">=</span> route.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">int</span> city2Index <span style="color: #339933;">=</span> route.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> city1 <span style="color: #339933;">=</span> cities.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>city1Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> city2 <span style="color: #339933;">=</span> cities.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>city2Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span> city1x <span style="color: #339933;">=</span> city1<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">double</span> city1y <span style="color: #339933;">=</span> city1<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">double</span> city2x <span style="color: #339933;">=</span> city2<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">double</span> city2y <span style="color: #339933;">=</span> city2<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
            distance <span style="color: #339933;">+=</span> <span style="color: #003399;">Math</span>.<span style="color: #006633;">sqrt</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>city1x <span style="color: #339933;">-</span> city2x<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>city1x <span style="color: #339933;">-</span> city2x<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>city1y <span style="color: #339933;">-</span> city2y<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>city1y <span style="color: #339933;">-</span> city2y<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> maxDistance <span style="color: #339933;">-</span> distance<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// city string parsing code elided</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The <tt>ArrayList</tt> is a list of flags indicating whether a city has been added to the route yet; it&#8217;s for implementing the chromosome parsing I described above. In my example, I described the process in terms of pulling elements from an ordered collection, and performing further operations on the reduced collection. Regenerating the ordered list of cities and manipulating it in this way every time I wanted to score a chromosome sounded computationally expensive; flipping booleans sounded cheaper. (I could probably get cheaper still using actual bit flags, but I was trying to keep the code both readable and writable at this stage. Optimizations will come later.)</p>
<p><strong>Initial Population</strong></p>
<p>The following code creates an initial population of chromosomes (encoded as Strings) and dumps them to a requested file:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> createInitialPopulation<span style="color: #009900;">&#40;</span>FSDataOutputStream populationOutfile, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> populationSize, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> numCities<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> populationSize<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> j <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;</span> <span style="color: #009900;">&#40;</span>numCities <span style="color: #339933;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>j<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
             <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                populationOutfile.<span style="color: #006633;">writeBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            populationOutfile.<span style="color: #006633;">writeBytes</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span>.<span style="color: #006633;">format</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;%d&quot;</span>, random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>numCities <span style="color: #339933;">-</span> j<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        populationOutfile.<span style="color: #006633;">writeBytes</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    populationOutfile.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>At a later time, I&#8217;ll experiment with using Hadoop&#8217;s ArrayWritable or other serialization schemes for more efficient representation of the chromosomes; at this stage, it was important to me to keep the data human-readable.</p>
<p>There&#8217;s a mapper dedicated to scoring generation 0:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ScoringMapper <span style="color: #000000; font-weight: bold;">extends</span> Mapper <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> Text outKey <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Text<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> DoubleWritable outValue <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DoubleWritable<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">protected</span> ChromosomeScorer scorer <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> map<span style="color: #009900;">&#40;</span>LongWritable key, Text value, <span style="color: #003399;">Context</span> context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">String</span> incomingValue<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> value.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">split</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003399;">String</span> chromosome <span style="color: #339933;">=</span> incomingValue<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">double</span> score <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0.0</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>incomingValue.<span style="color: #006633;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003399;">String</span> scoreString <span style="color: #339933;">=</span> incomingValue<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
                score <span style="color: #339933;">=</span> <span style="color: #003399;">Double</span>.<span style="color: #006633;">parseDouble</span><span style="color: #009900;">&#40;</span>scoreString<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">NumberFormatException</span> nfe<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// weird - but let's try re-generating the score</span>
                score <span style="color: #339933;">=</span> scorer.<span style="color: #006633;">score</span><span style="color: #009900;">&#40;</span>value.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">// we only go through the scoring process if we don't have a map</span>
            score <span style="color: #339933;">=</span> scorer.<span style="color: #006633;">score</span><span style="color: #009900;">&#40;</span>value.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        outValue.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>score<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	outKey.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>chromosome<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	context.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>outKey, outValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// setup code elided</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Subsequent Generations</strong></p>
<p>I managed to cram the rest of the operations for each generation into one mapper and one reducer &#8211; really, into one reducer, since the map function just randomly assigns chromosomes to groups:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> map<span style="color: #009900;">&#40;</span>LongWritable key, Text value, <span style="color: #003399;">Context</span> context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        outKey.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>numBins<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        context.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>outKey, value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// shuffle</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>So why am I shuffling the chromosomes thus? Most methods of population <a href="http://en.wikipedia.org/wiki/Selection_(genetic_algorithm)">selection</a> involve having some view over the data; the naïve method of <a href="http://en.wikipedia.org/wiki/Truncation_selection">truncation selection</a> is an extreme example, where you need to sort the entire population, and keep some fraction of the highest-scoring individuals. This is hard to parallelize, and not especially scalable for large populations.</p>
<p>Other selection methods such as <a href="http://en.wikipedia.org/wiki/Fitness_proportionate_selection">fitness proportionate selection</a>, however, look like they&#8217;d retain their properties well if the total population was divided into large, random subpopulations. (I have yet to do a detailed mathematical treatment of this, but some combination of intuition and cocktail napkin calculation has convinced me of this well enough to forge ahead.) To this end, I&#8217;ve set up the system to randomly distribute the full population into a user-settable number of subpopulations; the size of these subpopulations can be tuned to fit within the memory allocated to a reducer instance. (Naturally, the ideal would be to have a subpopulation just large enough to be handled by one reducer instance.) Assuming that the subpopulations are sufficiently large, the random distribution should retain the aggregate characteristics (distribution of fitness scores, &amp;c) of the total population, and give similar results under fitness proportionate selection.</p>
<p>After this subdivision of the population, a reducer instance receives a subpopulation, and is then responsible for selecting survivors from that population, breeding replacement members of the population from the survivors, and scoring the new population members.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> reduce<span style="color: #009900;">&#40;</span>VIntWritable key, Iterable values, <span style="color: #003399;">Context</span> context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span>, <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">TreeSet</span> sortedChromosomes <span style="color: #339933;">=</span> getSortedChromosomeSet<span style="color: #009900;">&#40;</span>values<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        normalizeScores<span style="color: #009900;">&#40;</span>sortedChromosomes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">int</span> survivorsWanted <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">double</span><span style="color: #009900;">&#41;</span> sortedChromosomes.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> survivorProportion<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003399;">Set</span> survivors <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashSet</span><span style="color: #009900;">&#40;</span>survivorsWanted<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>survivors.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> survivorsWanted<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            survivors.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>selectSurvivor<span style="color: #009900;">&#40;</span>sortedChromosomes<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003399;">ArrayList</span> parentPool <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span>survivors<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>survivors.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> desiredPopulationSize<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            survivors.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>makeOffspring<span style="color: #009900;">&#40;</span>parentPool<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003399;">Iterator</span> iter <span style="color: #339933;">=</span> survivors.<span style="color: #006633;">iterator</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>iter.<span style="color: #006633;">hasNext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            ScoredChromosome sc <span style="color: #339933;">=</span> iter.<span style="color: #006633;">next</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            outKey.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>sc.<span style="color: #006633;">chromosome</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            outValue.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span>sc.<span style="color: #006633;">score</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            context.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>outKey, outValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Selection:</strong> The first step in fitness proportionate selection is to sort the new members according to their score, ascending. After that, survivors are selected from the population randomly, weighted by their scores (the higher a chromosome&#8217;s score, the more likely it is to survive).</p>
<p><strong>Repopulation:</strong> Surviving chromosomes are used to breed back up to our original population numbers. I used single crossover and random mutations (maximum of one mutation per chromosome per generation):</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">protected</span> ScoredChromosome makeOffspring<span style="color: #009900;">&#40;</span><span style="color: #003399;">ArrayList</span> parentPool<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">InterruptedException</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">int</span> parent1Index <span style="color: #339933;">=</span> random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>parentPool.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">int</span> parent2Index <span style="color: #339933;">=</span> parent1Index<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>parent2Index <span style="color: #339933;">==</span> parent1Index<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            parent2Index <span style="color: #339933;">=</span> random.<span style="color: #006633;">nextInt</span><span style="color: #009900;">&#40;</span>parentPool.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        ScoredChromosome parent1 <span style="color: #339933;">=</span> parentPool.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>parent1Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ScoredChromosome parent2 <span style="color: #339933;">=</span> parentPool.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>parent2Index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        ScoredChromosome offspring <span style="color: #339933;">=</span> crossover<span style="color: #009900;">&#40;</span>parent1, parent2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>random.<span style="color: #006633;">nextDouble</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> mutationChance<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            mutate<span style="color: #009900;">&#40;</span>offspring<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        offspring.<span style="color: #006633;">score</span> <span style="color: #339933;">=</span> scorer.<span style="color: #006633;">score</span><span style="color: #009900;">&#40;</span>offspring.<span style="color: #006633;">chromosome</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> offspring<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Scoring:</strong> Finally, all unscored population members are scored in preparation for the next round.</p>
<p>This process is repeated for as many generations as is specified at the beginning of the run.  (Later, I plan to allow the number of generations to be unspecified, and have the algorithm terminate when the maximum score starts to settle/converge.)</p>
<p><strong>Parameters</strong></p>
<ul>
<li>Number of cities</li>
<li>Population size</li>
<li>Proportion of survivors in each generation</li>
<li>Subpopulation size (see above for rationale for dividing up the population, and thoughts on tuning)</li>
<li>Chance of random mutation</li>
<li>Number of generations</li>
</ul>
<p><strong>Results</strong></p>
<p>I&#8217;ve thrown the data for min/max/mean scores for each generation of each run into a <a href="https://docs.google.com/spreadsheet/ccc?key=0AkBz3y6su8VvdHNkMGdFYnlSdmNhZ1hNOW5GTWwtb0E&#038;hl=en_US">Google spreadsheet</a>, and made some simple graphs.</p>
<p>The first run was done with 10,000-member population, 30% survival chance, 500 generations.  There&#8217;s an unmistakable fitness increase over time, and it gets pretty close to the theoretical maximum for my test city (~23.066).</p>
<p>The second run was done with a 100,000-member population and 50% survival chance, 500 generations.  It gets off to a slower start, but there&#8217;s a burst of improvement late in the 500-generation run and it gets pretty close to the optimum.</p>
<p>The difference in early-stage performance of the second run had me kicking myself for changing <i>two</i> inputs.  I switched back to a 30% survival chance but kept the larger population.  This run landed in the same neighborhood as the others, and looked like it still had room to settle.</p>
<p>Interesting to note on all 3 runs is that all start with a few generations of quick improvement, then flatten out, then have an inflection point after which there&#8217;s a burst of quick improvement.  (<a href="http://en.wikipedia.org/wiki/Punctuated_equilibrium">Punctuated equilibrium</a>?)  All runs seem to still be on the climb; I suspect that a moving average over a few generations and/or some statistical tests for convergence would give a clearer picture of what&#8217;s happening with the max trend; the average was still definitely on the rise at the end of all three runs.</p>
<p><strong>Notes</strong></p>
<p>Test coverage could be improved, especially with the use of mocks.  I may move to <a href="https://ccp.cloudera.com/display/SUPPORT/Downloads">CDH3</a> and try <a href="http://www.cloudera.com/blog/2009/07/debugging-mapreduce-programs-with-mrunit/">MRUnit</a> to ease test design.  As it stands I&#8217;m taking most of the logic out of the mappers and reducers and just using the overridden map() and reduce() functions to coordinate the calls that do the actual work, largely to make it easier to test the logic in isolation.</p>
<p>For the sake of speed, I could probably take out some of the square roots and do my scoring using the squares of the distances.</p>
<p>On my 13&#8243; MacBook Pro with Core Duo processor running 2 mappers and 2 reducers, a population of 10,000 took 45-60 seconds to cull, breed, and score. The time per generation didn&#8217;t change appreciably when I went from 10,000 chromomsomes per generation to a population of 100,000 &#8211; which means most of my time is still spent in Hadoop overhead, which means that even on my little laptop, I could put up much bigger populations (or much bigger maps) and still run 500 generations in about 6 hours.</p>
<p>I haven&#8217;t bothered taking the simulation parameters in via the command line yet; this would be an obvious improvement, and probably the next thing I&#8217;ll do. I was a lot more focused on getting the GA code right and checking that it behaved as expected than I was with making a usable tool.  I&#8217;ve gotten the itch to generalize and grow this thing, though, so I&#8217;ll need to start making it usable &amp; configurable &amp; scriptable.</p>
<p>Clearly, this is not a general toolkit for GA, or even GA applied to NP-hard problems. (I don&#8217;t like to generalize without at least two cases.) I do see plenty of places where it is generalizable, though, and will starting doing so as soon as I pick a second problem to attack. A long-term goal is to factor out a library/API for doing GA on Hadoop.</p>
<p>Genetic algorithms are not one single thing &#8211; there are multiple strategies for culling populations, doing crossover/breeding, etc. A longer-term design goal is to make each of those variable pieces of the algorithm into pluggable strategies selectable from the command line.</p>
<p>There&#8217;s optimization to do all over the place, e.g. with the multiple copies of data kept in the reducer. I chose the data structures I used for ease of implementing the algorithm &#8211; e.g., picking a Set to hold survivors so as to avoid picking up duplicate survivors &#8211; with the intent to get working software quickly, and <a href="http://www.irocon.com/blog/2006/09/07/optimize-last.aspx">optimize last</a>.</p>
<p><strong>The Code</strong></p>
<p>The code, such as it is, is in a <a href="https://github.com/bradheintz/TravSales">public repository on GitHub</a>.  More to come.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F10%2F10%2Ftraveling-salesman-attack%2F&amp;title=Traveling%20Salesman%20Attack%21%20%28Hadoop%20and%20Genetic%20Algorithms%29" id="wpa2a_16"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/10/10/traveling-salesman-attack/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Node Knockout 2011 Post Mortem</title>
		<link>http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/</link>
		<comments>http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 07:21:40 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Nodejs]]></category>
		<category><![CDATA[Post Mortem]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[competition]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[nodeknockout]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=633</guid>
		<description><![CDATA[Node Knockout 2011 took place this past weekend.  I signed up with the hope of being a &#8220;One Man Army&#8221; &#38; winning the solo contestant award.  I figured that NodeJs was so easy to use and so powerful (seriously, it&#8217;s freaking awesome) that &#8230; <a href="http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://nodeknockout.com/" target="_blank">Node Knockout 2011</a> took place this past weekend.  I signed up with the hope of being a &#8220;One Man Army&#8221; &amp; winning the <a href="http://nodeknockout.com/prizes" target="_blank">solo contestant</a> award.  I figured that <a href="http://nodejs.org/" target="_blank">NodeJs</a> was so easy to use and so powerful (seriously, it&#8217;s freaking awesome) that it&#8217;d be child&#8217;s play.  I unfortunately bit more than I can chew however.</p>
<p><a href="https://twitter.com/codinghorror" target="_blank">Jeff Atwood</a> once blogged: &#8220;<a href="http://www.codinghorror.com/blog/2006/11/the-project-postmortem.html" target="_blank">I don&#8217;t think it matters how you conduct the postmortem, as long as you do it</a>&#8220;.  To that end, here&#8217;s my post mortem of the app I <strong>didn&#8217;t</strong> finish.  Ideally  other developers will learn from my successes and mistakes.  :)</p>
<p><span id="more-633"></span><span style="text-decoration: underline;"><strong>The App/Idea</strong></span>: A web version of my iphone app ( <a href="http://www.touchplaybook.com/" target="_blank">Touch Playbook</a> ) called Playbook Nodes.  I learned a lot creating TPB and I figured I&#8217;d learn a lot porting the code as well.  I emailed the contest organizers early to make sure I wasn&#8217;t going to violate the following rule:</p>
<p style="padding-left: 30px;">&#8220;Of course, feel free to work on the concept for your application before the competition starts: pretty hand-drawn pictures on napkins, angry email threads between team members on two-space or four-space indentation, schema designs, finite state machines.  Just no digital assets including graphic design assets, code, etc.&#8221;</p>
<p style="padding-left: 30px;">~<a href="http://nodeknockout.com/rules">Node Knockout Rules</a></p>
<p>They gave me the green light, so I starting researching the parts of the app I&#8217;d need to understand.  Looking back, here were my mistakes:</p>
<p><span style="text-decoration: underline;"><strong>Mistake #1: Doing too much</strong></span><br />
Heading into the competition, my goal was to recreate the entire app.  That includes the user interactions (dragging players, passing the ball, shooting, etc), full replay animation logic, &amp; state management.  On top of that, I wanted to add new features like user accounts and the ability to share pays.  Considering that it took me 5 months to build TPB (1 month to spec / 3 months to implement / 1 month of user testing ), this order was WAY too tall.  In hindsight, <strong>I should have simply picked another project</strong>.  Anything TPB inspired that&#8217;d be worthwhile would simply take too long.</p>
<p><span style="text-decoration: underline;"><strong>Mistake #2: Assuming that things will simply fit together</strong></span><br />
I assumed that I&#8217;d simply figure out how to elegantly draw paths as the user dragged players (and animate the process later) despite the fact that I couldn&#8217;t find good examples of animating the drawing of paths and I&#8217;d never done it before using Raphael.  I also assumed Mongoose-Auth would be easily to implement and&#8230;well..would just work.  Both of these assumptions cost me precious time.</p>
<p><span style="text-decoration: underline;"><strong>Mistake #3: Oversleeping</strong></span><br />
I was hoping to get about 5-6 hours of sleep each night.  Instead I got 7-8 each night.  I felt great, but I wish I had the extra hours to code.</p>
<p><span style="text-decoration: underline;"><strong>Mistake #4: Failing to achieve a &#8220;thin line through&#8221; in the first 24 hours</strong></span><br />
This might be the most telling sign of failure in a 48 hour competition.  It&#8217;s really important to get a barebones version of your app working before you continue working on the features in your spec.  The 24 span INCLUDES server setup.</p>
<p>It wasn&#8217;t all bad though.  Here are some things I did right:</p>
<p><span style="text-decoration: underline;"><strong>Success #1: Spec&#8217;d as much as I could BEFORE the competition</strong></span><br />
<a href="https://gomockingbird.com/" target="_blank">Mockingbird</a> was super handy way to mock views &amp; my trusty notebook saved my thoughts in the weeks leading to the competition.  Also, I was able to pull my notes from the creation of TPB which helped a bunch.</p>
<p><span style="text-decoration: underline;"><strong>Success #2: Improved my overall JavaScript skills &amp; got comfortable writing node JavaScript before the competition</strong></span><br />
I&#8217;m new to Node.js, but I&#8217;m not new to web development.  I have to shamefully admit that I used to think of JavaScript as a sub-language whose only use were silly DOM tricks.  Fortunately, I started following the works of Douglas Crockford and saw the light.  Not too long after that, I start hearing about NodeJS &amp; I started soaking up examples around the first week in August.  I turned my knowledge harvesting into overdrive &amp; gained the confidence I needed to enter the competition .  Here are some of the things that I did:</p>
<ul>
<li><a href="http://www.yuiblog.com/crockford/" target="_blank">Watched 7.5 hours</a> of Douglas Crockford&#8217;s presentations</li>
<ul>
<li>Also kept a copy of &#8220;<a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/ref=sr_1_1?ie=UTF8&amp;qid=1314686380&amp;sr=8-1" target="_blank">Javascript: The Good Parts</a>&#8221; close by at all times <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<li>Attending a free training by the co-founders of <a href="http://nodejitsu.com/" target="_blank">Nodejitsu</a>, (<a href="https://twitter.com/hij1nx" target="_blank">@hij1nx</a> &amp; <a href="https://twitter.com/indexzero" target="_blank">@indexzero</a>)</li>
<li>Watching as many <a href="http://nodetuts.com/" target="_blank">NodeTuts</a> as I possible could and coding the examples in the vids.</li>
<li><a href="http://nodeguide.com/" target="_blank">Felix&#8217;s Node.js Guide</a></li>
<ul>
<li>Tons of links to helpful content &amp; people to follow (twitter, blogs, etc).</li>
</ul>
<li>Watching videos by <a href="http://twitter.com/ryah" target="_blank">Ryan Dahl</a>, the creator of Node.js</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Success #3: I went with Heroku instead of Linode or Joyent</strong></span><br />
I didn&#8217;t want to lose time configuring a server.  The purpose of the competition is the app that I create, not testing my Sys-Admin skills.  Going with Heroku saved me the headache that many of my fellow participants faced.  Some teams never got their server setup, but I was deploying early and easily.</p>
<p><span style="text-decoration: underline;"><strong>Success #4: Logging my actions</strong></span><br />
Every hour, on the hour, I wrote a summary of how I spent my time.  If I started writing a bunch of code, I&#8217;d shorten my logging to 30 minute intervals.  This was helpful because it drove me to get small victories at least once an hour.</p>
<p><span style="text-decoration: underline;"><strong>Success #5: In Backbone.js apps, add a global logging function</strong></span><br />
I started doing this in every Backbone app that I create.  I add 3 simple methods to my controller/router definition.  This gives me a name-spaced way to log &amp; benchmark events from my controllers, models &amp; views.  It also gives me a clean way to disable logging when I deploy to production &amp; an easy way to toggle the logging once the code is deployed to prod.</p>
<ul>
<li>debugEnv()</li>
<ul>
<li>The router/controller has a variable called &#8216;debug&#8217; which is set to true/false.</li>
<li>The first line of the method looks like this:<br />
<strong>return (this.debug &amp;&amp; (typeof console !== &#8216;undefined&#8217;)); </strong></li>
</ul>
<li>logEvent(message)</li>
<ul>
<li>This method returns if the controller/router&#8217;s debug method is off<br />
<strong>if(! this.debugEnv() ){ return; }  </strong></li>
<li>Otherwise:<br />
<strong>console.log( (new Date()).toTimeString() + &#8220;: &#8221; + message); </strong></li>
</ul>
<li>benchEvent(handle, operand_string)</li>
<ul>
<li>This method needs to use console.time() &amp; console.timeEnd() so it makes sure that we can debug AND that the &#8216;time&#8217; method exists (This is a problem on IE):<br />
<strong>if(! this.debugEnv() || typeof console.time === &#8216;undefined&#8217; ){ return; }</strong></li>
<li>Otherwise, depending on the &#8216;operand_string&#8217;, &#8230;<br />
<strong>case &#8216;+&#8217; : console.time(handle); break;</strong><br />
<strong>case &#8216;-&#8217;: console.timeEnd(handle); break;</strong></li>
</ul>
</ul>
<p><span class="Apple-style-span" style="color: #444444; font-family: Georgia, 'Bitstream Charter', serif; font-size: 16px; line-height: 24px;">This makes it really easy to track what my app is doing and provides simple benchmarking.  I find it super helpful! </span></p>
<p><span style="text-decoration: underline;"><strong>Success #6: Entering Node Knockout 2011</strong></span><br />
The biggest success was taking part in the competition.   I learned so much more about <a href="http://www.expressjs.com/" target="_blank">ExpressJS</a>, <a href="https://github.com/visionmedia/jade" target="_blank">Jade</a>, <a href="http://learnboost.github.com/stylus/docs/js.html" target="_blank">Stylus</a>, <a href="http://mongoosejs.com/" target="_blank">Mongoose</a>, <a href="http://www.mongodb.org/" target="_blank">MongoDB</a>, <a href="http://www.colorzilla.com/gradient-editor/" target="_blank">CSS3 Gradients</a>, and more because I challenged myself.  Was I ready for every single challenge I faced? Absolutely not!  However, failing with focused effort is better than never trying at all.</p>
<p><span style="text-decoration: underline;"><strong>In Conclusion</strong></span><br />
I look forward to Node Knockout 2012.  I&#8217;m probably going to start spec&#8217;ing even earlier and I&#8217;ll be more realistic about what can be accomplished in 48 hours.  I also intend to complete PlaybookNodes.  While I didn&#8217;t get everything done in 48 hours, I put together a LOT of plumbing and I feel that I&#8217;m potentially only a few days away from a finished product.  I hope my experiences help you plan your next 48 coding session better than I did. <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Oh, and now that I&#8217;m done with NKO2011, Part 2 of the Backbone.JS tutorial is on it&#8217;s way!</p>
<p>Till next time, Happy Coding!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F08%2F30%2Fnode-knockout-2011-post-mortem%2F&amp;title=Node%20Knockout%202011%20Post%20Mortem" id="wpa2a_18"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/08/30/node-knockout-2011-post-mortem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Gotchas while Deploying a Sinatra App to Heroku</title>
		<link>http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/</link>
		<comments>http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/#comments</comments>
		<pubDate>Wed, 11 May 2011 05:03:37 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Heroku]]></category>
		<category><![CDATA[Sinatra]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=597</guid>
		<description><![CDATA[I figured it&#8217;d nice to deploy the tutorial Backbone.js app to Heroku.  The tutorial app that we&#8217;re building, &#8220;Comment on the movies&#8221;, has a simple Sinatra backend &#38; Heroku welcomes Rails &#38; Rack-based apps.  Here are the 2 gotchas that I &#8230; <a href="http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I figured it&#8217;d nice to deploy the tutorial Backbone.js app to Heroku.  The tutorial app that we&#8217;re building, &#8220;Comment on the movies&#8221;, has a simple Sinatra backend &amp; <a href="http://devcenter.heroku.com/articles/rack" target="_blank">Heroku welcomes Rails &amp; Rack-based apps</a>.  Here are the 2 gotchas that I needed to deal with in order to deploy to Heroku:<span id="more-597"></span></p>
<h2>Gotcha 1 &#8211; The .gems file:</h2>
<p>The &#8216;.gems&#8217; file is <strong>SUPER</strong> important.  Without it, Heroku won&#8217;t be able to install the gems that your app needs to function properly ( like&#8230;say&#8230;Sinatra <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).  It&#8217;s mentioned as a single line in the linked page above, but it&#8217;s worth mentioning because it&#8217;s easy to miss.</p>
<h2>Gotcha 2 &#8211; Heroku&#8217;s read-only Filesystem:</h2>
<p>There are certain files that you shouldn&#8217;t put into source control, like an API key from the New York Times (hint, hint).  Historically, I&#8217;ve added files like these to the server directly (along with other sensitive keys/data).  <a href="http://devcenter.heroku.com/articles/read-only-filesystem" target="_blank">While Heroku&#8217;s read-only file system doesn&#8217;t allow this</a>, it does have a nice solution:  Define sensitive values <a href="http://devcenter.heroku.com/articles/config-vars#cli_usage" target="_blank">via the Command Line Interface</a>:</p>
<blockquote><p>heroku config:add API_KEY=&#8217;ABC123&#8242;</p></blockquote>
<p>&#8230; and reference them in code like this:</p>
<blockquote><p>my_key = ENV['API_KEY']</p></blockquote>
<p>Those are the two <strong>VERY</strong> simple gotchas I ran into which shouldn&#8217;t distract from how awesome Heroku is.  Create your free account and play with it.</p>
<p>In other news, Part 2 of the Backbone.js tutorial series is coming soon.  In fact, the site&#8217;s layout was changed to accomodate the code and text for the tutorial.  You can watch the unfinished product evolve on <a href="https://github.com/abelmartin/Comment-On-The-Movies" target="_blank">GitHub</a> &amp; <a href="http://commentonthemovies.heroku.com/" target="_blank">play with it on Heroku</a>.</p>
<p>Happy Coding!</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2011%2F05%2F11%2Fquick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku%2F&amp;title=Quick%20Hits%3A%20Gotchas%20while%20Deploying%20a%20Sinatra%20App%20to%20Heroku" id="wpa2a_20"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2011/05/11/quick-hits-gotchas-while-deploying-a-sinatra-app-to-heroku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

