<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
  <title>James on Software</title>
  <subtitle>Thoughts on software, testing...</subtitle>
  
  <link href="http://jamesgolick.com/" />
  <updated>2009-06-06T09:25:59-04:00</updated>
  <author>
    <name>James Golick</name>
    <email>jamesgolick@gmail.com</email>
  </author>
  <id>http://jamesgolick.com/</id>
  
  <link rel="self" href="http://feeds.feedburner.com/JamesOnSoftware" type="application/atom+xml" /><entry>
    <title>Introducing Trample: A Better Load Simulator</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/G6ZtaKUXxUY/introducing-trample-a-better-load-simulator.html" />
    <id>tag:jamesgolick.com,2009-06-04:1244141199</id>
    <updated>2009-06-04T14:46:39-04:00</updated>
    <content type="html">&lt;p&gt;
  Most load sim tools make requests to a static list of urls. They spawn n threads and make requests to the urls on the list in succession, in each thread. Unfortunately, though, if your applicaition makes use of any kind of caching (including your database's internal caching facilities), this kind of load simulation is unrealistic.
&lt;/p&gt;

&lt;p&gt;
  The data required to serve a single set of urls is likely to fit nicely in the database server's cache (even on a small server). So, having a single user hammer a finite set of pages will make your application look much faster than it really is.
&lt;/p&gt;

&lt;p&gt;
  Unless your load patterns really look that way, you're testing for a scenario that you'll never see.
&lt;/p&gt;

&lt;h3&gt;Introducing Trample&lt;/h3&gt;

&lt;p&gt;
  Trample is a more flexible load simulator. Instead of a static list of urls, trample's configuration language is ruby. Using ruby's blocks (lambda functions), it's possible to randomize the requests that get made in each thread, as well as the user that logs in.
&lt;/p&gt;

&lt;p&gt;
  Let's look at an example config:
&lt;/p&gt;

&lt;pre class="twilight"&gt;&lt;span class="Support"&gt;Trample&lt;/span&gt;.&lt;span class="Entity"&gt;configure&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
  concurrency &lt;span class="Constant"&gt;20&lt;/span&gt;
  iterations  &lt;span class="Constant"&gt;10&lt;/span&gt;
  login &lt;span class="Keyword"&gt;do&lt;/span&gt;
    post &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;http://mysite.com/login&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
      {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;username&lt;/span&gt; =&amp;gt; &lt;span class="Support"&gt;User&lt;/span&gt;.&lt;span class="Entity"&gt;random&lt;/span&gt;.&lt;span class="Entity"&gt;username&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;password&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;swordfish&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}
    &lt;span class="Keyword"&gt;end&lt;/span&gt;
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
  get &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;http://mysite.com/posts/:id&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
    {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;id&lt;/span&gt; =&amp;gt; &lt;span class="Support"&gt;Post&lt;/span&gt;.&lt;span class="Entity"&gt;random&lt;/span&gt;.&lt;span class="Entity"&gt;id&lt;/span&gt;}
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
  post &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;http://mysite.com/posts/:id/comments&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
    {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;id&lt;/span&gt; =&amp;gt; &lt;span class="Support"&gt;Post&lt;/span&gt;.&lt;span class="Entity"&gt;random&lt;/span&gt;.&lt;span class="Entity"&gt;id&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;author&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;James Golick&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;body&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;lorem ipsum&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;
  This config will cause trample to spawn 20 threads. In each thread:
&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Trample will begin by sending a POST request to http://mysite.com/login with the result of the block as its POST body.&lt;/li&gt;
  &lt;li&gt;Then, trample will GET http://mysite.com/posts/(some interpolated value here, based on the result of the block).&lt;/li&gt;
  &lt;li&gt;Then, trample will POST http://mysite.com/posts/(interpolated value here)/comments with a POST body that includes the remainder of the parameters returned from the block&lt;/li&gt;
  &lt;li&gt;Repeat steps 2-3 nine (iterations - 1) more times.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
  It's possible to create fairly realistic load simulations with a configuration like this. Each thread will start by logging in as a different user. And, the threads will each visit different URLs. The ratio of cache hits to misses should be far closer to what they look like under real load.
&lt;/p&gt;

&lt;h3&gt;Running Trample&lt;/h3&gt;

&lt;p&gt;
  To run trample:
&lt;/p&gt;

&lt;pre class="twilight"&gt;$ trample start &lt;span class="Keyword"&gt;/&lt;/span&gt;path&lt;span class="Keyword"&gt;/&lt;/span&gt;to&lt;span class="Keyword"&gt;/&lt;/span&gt;your&lt;span class="Keyword"&gt;/&lt;/span&gt;trample&lt;span class="Keyword"&gt;/&lt;/span&gt;config.&lt;span class="Entity"&gt;rb&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;
  I've tested trample on ruby 1.8.x, ruby 1.9, and JRuby. JRuby has the advantage of native threading, but the drawback of JVM warmup times. So, theoretically, JRuby should be the best platform for running long tramples. Ruby 1.9 should be fastest for shorter tramples. I could be wrong, though. YMMV.
&lt;/p&gt;

&lt;h3&gt;Get It!&lt;/h3&gt;

&lt;p&gt;
  Get trample as a gem:
&lt;/p&gt;

&lt;pre class="twilight"&gt;$ sudo gem install giraffesoft&lt;span class="Keyword"&gt;-&lt;/span&gt;trample
&lt;/pre&gt;
&lt;p&gt;
  Or get &lt;a href="http://github.com/giraffesoft/trample"&gt;the source from github&lt;/a&gt;.
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/G6ZtaKUXxUY" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/6/4/introducing-trample-a-better-load-simulator.html</feedburner:origLink></entry>
  
  <entry>
    <title>How to Watch Hulu From Canada (or Anywhere Else)</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/O6c5l03Wfk0/how-to-watch-hulu-from-canada-or-anywhere-else.html" />
    <id>tag:jamesgolick.com,2009-05-24:1243210060</id>
    <updated>2009-05-24T20:07:40-04:00</updated>
    <content type="html">&lt;p&gt;
  I live in Canada. We don't have guns. But, we do have health care.
&lt;/p&gt;

&lt;p&gt;
  Okay, so there are a few other things we don't have &amp;mdash; one of them being &lt;a href="http://hulu.com"&gt;hulu&lt;/a&gt;. Yeah, there's always &lt;a href="http://watchtvsitcoms.com"&gt;watchtvsitcoms.com&lt;/a&gt;. But, it's slow, full of annoying flash ads, and the quality of the shows is spotty.
&lt;/p&gt;

&lt;p&gt;
  A while back, I tried to beat hulu's &lt;a href="http://en.wikipedia.org/wiki/Geofencing"&gt;geofencing&lt;/a&gt; (fuck geofencing) by creating an SSH tunnel. That was a miserable failure.  Then, recently, I saw somebody tweet about using &lt;a href="http://openvpn.net"&gt;OpenVPN&lt;/a&gt;. So, I gave it a shot, and it worked! 
&lt;/p&gt;

&lt;h3&gt;How To Do this Yourself&lt;/h3&gt;

&lt;p&gt;
  Now, I could tell you to go and read the &lt;a href="http://openvpn.net/index.php/documentation/howto.html"&gt;official tutorial&lt;/a&gt; on setting up OpenVPN. But, I've got something better.
&lt;/p&gt;

&lt;p&gt;
  I put together a &lt;a href="http://wiki.opscode.com/display/chef/Home"&gt;chef&lt;/a&gt;&lt;sup&gt;&lt;a href="#one"&gt;[1]&lt;/a&gt;&lt;/sup&gt; recipe for installing OpenVPN on a virtual machine. The whole process is automated. So, &lt;strong&gt;you don't really need to know anything about OpenVPN to get up and running&lt;/strong&gt;.
&lt;/p&gt;

&lt;p&gt;Here's the guide:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Get a &lt;a href="http://www.linode.com/index.cfm"&gt;linode&lt;/a&gt; (or equivalent virtual machine, located in the US).&lt;/li&gt;
  &lt;li&gt;Setup your vm with Ubuntu.&lt;/li&gt;
  &lt;li&gt;
    Install ruby &amp;amp; rubygems on the vm:
    &lt;pre class="twilight"&gt;sudo apt&lt;span class="Keyword"&gt;-&lt;/span&gt;get install ruby rubygems
&lt;/pre&gt;  &lt;/li&gt;
  &lt;li&gt;
    On your local machine, clone the cookbook repository:
    &lt;pre class="twilight"&gt;git clone git&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;/&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;github.&lt;span class="Entity"&gt;com&lt;/span&gt;&lt;span class="Keyword"&gt;/&lt;/span&gt;giraffesoft&lt;span class="Keyword"&gt;/&lt;/span&gt;openvpn&lt;span class="Keyword"&gt;-&lt;/span&gt;recipes.git
&lt;/pre&gt;    Or, if you don't have git installed, grab a tarball from &lt;a href="http://github.com/giraffesoft/openvpn-recipes/tree/master"&gt;github&lt;/a&gt;. Then, unarchive it:
    &lt;pre class="twilight"&gt;tar zxvf giraffesoft&lt;span class="Keyword"&gt;-&lt;/span&gt;openvpn&lt;span class="Keyword"&gt;-&lt;/span&gt;recipes&lt;span class="Keyword"&gt;-&lt;/span&gt;xyz.&lt;span class="Entity"&gt;tar&lt;/span&gt;.gz
&lt;/pre&gt;  &lt;/li&gt;
  &lt;li&gt;
    You'll also need capistrano (on your local machine).
    &lt;pre class="twilight"&gt;sudo gem install capistrano
&lt;/pre&gt;  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now, cd in to the dir you cloned or extracted. Then, edit config/deploy.rb to match your settings.&lt;/p&gt;
    &lt;p&gt;You'll want to set :host to your server's domain name or ip address. You'll also want to set user to the name of the user you're going to get ssh'd in as. Finally, set the country, province, city, etc variables. Those are for generating the signing authority.&lt;/p&gt;
    &lt;p&gt;You'll want to &lt;a href="http://ubuntuforums.org/archive/index.php/t-30709.html"&gt;setup an ssh keypair&lt;/a&gt; on your server, too, to make this easier.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    Now that everything is all configured, run chef, by typing this command at the root of the openvpn recipes project:
    &lt;pre class="twilight"&gt;cap run_chef
&lt;/pre&gt;    OpenVPN is now installed and configured!
  &lt;/li&gt;
  &lt;li&gt;
    Now, create a client package by typing:
    &lt;pre class="twilight"&gt;cap generate_client_package
&lt;/pre&gt;  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There should now be a file at build/client.tar.gz. Unarchive this file to wherever you want to keep your OpenVPN configuration. Then, start OpenVPN on your local machine. That's it!&lt;/p&gt;
    &lt;p&gt;Note: if you're using a mac, you'll want to use &lt;a href="http://code.google.com/p/tunnelblick/"&gt;Tunnelblick&lt;/a&gt; to manage your vpn connection. Just unarchive the client package to ~/Library/openvpn and Tunnelblick will take care of the rest.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
  You should now have a working VPN. Enjoy hulu!
&lt;/p&gt;

&lt;p&gt;
  Also, if you're interested, checkout the code &lt;a href="http://github.com/giraffesoft/openvpn-recipes/tree/master"&gt;at github&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  &lt;a name="one"&gt;&lt;/a&gt;
  &lt;sup&gt;[1]&lt;/sup&gt; Incidentally, if you do absolutely any work with servers or systems configuration and you haven't had a look at &lt;a href="http://wiki.opscode.com/display/chef/Home"&gt;chef&lt;/a&gt; yet, you're doing yourself a disservice. Chef allows you to keep all of your servers' configuration in a git (or other scm) repository, edit it locally and deploy it out to your server (or cluster thereof). It also does a lot of other awesome stuff. Check it out!
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/O6c5l03Wfk0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/5/24/how-to-watch-hulu-from-canada-or-anywhere-else.html</feedburner:origLink></entry>
  
  <entry>
    <title>The New and Improved James on Software</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/uOeerx0qiXo/the-new-and-improved-james-on-software.html" />
    <id>tag:jamesgolick.com,2009-04-08:1239200808</id>
    <updated>2009-04-08T10:26:48-04:00</updated>
    <content type="html">&lt;p&gt;
  I finally got around to having this site redesigned &amp;mdash; something I've wanted to do for a while. James on Software plays a large role in my personal brand. So, having great design is of paramount importance.
&lt;/p&gt;

&lt;p&gt;
  There's not much more to &lt;i&gt;say&lt;/i&gt; about the new design, except that I did want to mention the designers.
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://weareagoodcompany.com"&gt;&lt;img src="http://www.weareagoodcompany.com/images/logo.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  When I arrived at &lt;a href="http://weareagoodcompany.com"&gt;a good company&lt;/a&gt;'s site for the first time, I knew I had found my designers. Their work really speaks for itself. Definitely check out their portfolio.
&lt;/p&gt;

&lt;p&gt;
  In addition to being awesome designers, they do great XHTML/CSS and even know some rails. They're spearheading &lt;a href="http://www.theleagueofmoveabletype.com/"&gt;The League of Movable Type&lt;/a&gt;, an open source font movement. So, if you read this blog, there's a good chance you have a lot in common with them.
&lt;/p&gt;

&lt;p&gt;
  If you're looking for a design firm for your next project, you should really check this duo out. 
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/uOeerx0qiXo" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/4/8/the-new-and-improved-james-on-software.html</feedburner:origLink></entry>
  
  <entry>
    <title>Bringing Computer Savvy &amp; Web 2.0 to Pre-Teen Girls</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/Qzs8sXrqBuc/bringing-computer-savvy-and-web-2-0-to-pre-teen-girls.html" />
    <id>tag:jamesgolick.com,2009-03-30:1238431308</id>
    <updated>2009-03-30T16:41:48Z</updated>
    <content type="html">
&lt;p&gt;
  I'm a huge fan of screencasting. It's a great way to &lt;a href="http://peepcode.com"&gt;learn about software development&lt;/a&gt;. Screencasting is also starting to be used to teach &lt;a href="http://www.lynda.com/Default.aspx"&gt;general daily computing topics&lt;/a&gt;. Nevertheless, it remains something of a niche. The general public still doesn't really know about screencasting.
&lt;/p&gt;

&lt;p&gt;There certainly isn't a whole lot of screencast content aimed at kids, except maybe a programming tutorial or two. There's &lt;b&gt;nothing&lt;/b&gt; (I can find) aimed at young girls.&lt;/p&gt;

&lt;p style="text-align:center;"&gt;&lt;a href="http://haileyhacks.com"&gt;&lt;img src="http://static0.shopify.com/s/files/1/0029/9362/assets//logo.png?1238154969 "/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  &lt;a href="http://haileyhacks.com"&gt;Hailey Hacks&lt;/a&gt; aims to fill that void in the market. Hailey is a savvy pre-teen girl. She's fun &amp;mdash; and a little bit rebellious. You might think of her as a cross between Bart and Lisa Simpson.
&lt;/p&gt;

&lt;p&gt;
  In the first episode, titled &lt;a href="http://www.haileyhacks.com/products/april-fools"&gt;April Fools&lt;/a&gt;, Hailey teaches you how to play pranks, low tech and high. First, she suggests that you fill your father's shampoo bottle with ketchup. Later in the episode, she recommends using &lt;a href="http://wakerupper.com"&gt;wakerupper.com&lt;/a&gt; to incessantly ring your father's phone while you're at school. I'll let Hailey show you the rest of them.
&lt;/p&gt;

&lt;div style="text-align:center;"&gt;
  &lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=3867259&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=3867259&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;/div&gt;
&lt;br/&gt;

&lt;p&gt;
  So far, we've got one other episode up there, in which &lt;a href="http://www.haileyhacks.com/products/lolcats"&gt;Hailey teaches you to make your own lolcats&lt;/a&gt;. Lots more are coming. Hear first by following &lt;a href="http://twitter.com/HaileyHacks"&gt;@HaileyHacks&lt;/a&gt; or subscribing to &lt;a href="http://www.haileyhacks.com/blogs/news"&gt;Hailey's blog&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  Despite the fact that this is web 2.0, we're selling the videos for 2$ each over at the &lt;a href="http://haileyhacks.com"&gt;Hailey Hacks site&lt;/a&gt;. We'd love to hear what you and your kids think of them!
&lt;/p&gt;



&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/Qzs8sXrqBuc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/3/30/bringing-computer-savvy-and-web-2-0-to-pre-teen-girls.html</feedburner:origLink></entry>
  
  <entry>
    <title>Firefox-style cmd-1 through cmd-9 shortcuts for switching tabs in Safari!</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/8AkuX2evUuU/firefox-style-cmd-1-through-cmd-9-shortcuts-for-switching-tabs-in-safari.html" />
    <id>tag:jamesgolick.com,2009-02-26:1235659690</id>
    <updated>2009-02-26T14:48:10Z</updated>
    <content type="html">
&lt;p&gt;Safari is by far the best browser on OS X. It's fast, has an awesome UI, and just feels better integrated in to the Mac experience.&lt;/p&gt;

&lt;p&gt;As former die-hard firefox users, though, I couldn't live without cmd-1 through cmd-9 for switching tabs. Thanks to &lt;a href="http://store.giraffesoft.ca"&gt;Safari Commander&lt;/a&gt;, now, I don't have to!

&lt;p&gt;For 5$, one person can use Safari Commander on as many of *their* computers as they like. Two members of the same family with separate computers should purchase two copies.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;WARNING: REQUIRES SAFARI 4 BETA. &lt;a href="http://www.apple.com/safari/download/"&gt;Available for download here&lt;/a&gt;. So far, I've found it very stable and worth it for this extension alone.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Buy it at the &lt;a href="http://store.giraffesoft.ca"&gt;giraffesoft store&lt;/a&gt;!&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/8AkuX2evUuU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/2/26/firefox-style-cmd-1-through-cmd-9-shortcuts-for-switching-tabs-in-safari.html</feedburner:origLink></entry>
  
  <entry>
    <title>FLOSS week</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/TwXC48tjxRg/floss-week.html" />
    <id>tag:jamesgolick.com,2009-02-16:1234818168</id>
    <updated>2009-02-16T21:02:48Z</updated>
    <content type="html">
&lt;p&gt;
  We at &lt;a href="http://giraffesoft.ca"&gt;giraffesoft&lt;/a&gt; went over a year without even having a website. Then, we lasted a few months with a website, but no blog. That ends today, hopefully with something of a bang.
&lt;/p&gt;

&lt;p&gt;
  We're big believers in extracting functionality sooner rather than later. This practice has resulted in a ton of code that we use in all of our projects &amp;mdash; nice and DRY. 
&lt;/p&gt;

&lt;p&gt;
  Only problem is, we never get around to releasing this stuff. Starting a &lt;a href="http://giraffesoft.ca/blog"&gt;blog&lt;/a&gt; seemed like a good excuse to spend some time polishing up some code and, you know, writing READMEs.
&lt;/p&gt;

&lt;p&gt;
  So, starting today, we'll be releasing an open source project every day this week. They'll probably be mostly rails plugins. But, you never know. Something else might float in.
&lt;/p&gt;

&lt;p&gt;
  If you're interested in following along, &lt;a href="http://feeds.giraffesoft.ca/giraffesoft-the-blog"&gt;subscribe to giraffesoft, the blog&lt;/a&gt;. Or, if like me, you don't really use your feed reader anymore, follow &lt;a href="http://twitter.com/giraffesoft"&gt;@giraffesoft&lt;/a&gt; on twitter or &lt;a href="http://github.com/giraffesoft"&gt;github&lt;/a&gt;! See you later with the first project.
&lt;/p&gt;



&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/TwXC48tjxRg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/2/16/floss-week.html</feedburner:origLink></entry>
  
  <entry>
    <title>One Line Tests Without the Smells</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/Bt36otTuoIs/one-line-tests-without-the-smells.html" />
    <id>tag:jamesgolick.com,2009-01-16:1232129606</id>
    <updated>2009-01-16T18:13:26Z</updated>
    <content type="html">
&lt;p&gt;
  Everybody loves one line tests. That's one of the great things about shoulda. It allows you to test a lot of simple functionality using one liners, called "macros". Unfortunately, though, there are a lot of things about shoulda macros that make them less than ideal as a testing mechanism.
&lt;/p&gt;

&lt;p&gt;
   Firstly, they get called at class scope, so the variables from your setup blocks isn't available. A quick read through the archives of the shoulda mailing list proves that this confuses people. The workaround for this issue is a major code smell: string programming. 
&lt;/p&gt;

&lt;p&gt;For example...&lt;/p&gt;

&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre&gt;&lt;span class="ident"&gt;should_redirect_to&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span style="color:#A5C261"&gt;post_url(@post)&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
  Here, 'post_url(@post)' is evaluated at the scope of the controller. A parse error in your string wouldn't point you to your should_redirect_to declaration. It would point you to a line inside of shoulda, where the instance_eval actually happens. Not good. There are lots of other reasons string programming sucks, too, but I won't get in to them here.
&lt;/p&gt;

&lt;p&gt;
  The second issue with macros is that failures often happen deep inside of shoulda. Backtraces often become completely useless, forcing you to open up shoulda and wade through it to figure out why your code is failing. 
&lt;/p&gt;

&lt;h3&gt;One More Problem&lt;/h3&gt;

&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre&gt;&lt;span class="ident"&gt;context&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#A5C261"&gt;A blog post&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;setup&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;
    &lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_person&lt;/span&gt;
    &lt;span style="color:#D0D0FF"&gt;@post&lt;/span&gt;   &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_post&lt;/span&gt; &lt;span style="color:#6E9CBE"&gt;:author&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt;
  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#A5C261"&gt;be editable by its author&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;assert&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;editable_by?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;
&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
  Don't see the problem?
&lt;/p&gt;

&lt;p&gt;
  Why bother writing self-documenting test code if you always have to explain it to the reader? &lt;a href="http://blog.jayfields.com/2008/05/testing-value-of-test-names.html"&gt;Test names are essentially glorified comments&lt;/a&gt; and &lt;a href="http://memeagora.blogspot.com/2008/11/comments-code-smell.html"&gt;comments are frequently code smells&lt;/a&gt;. Furthermore, all the extra code required to create a test (should "" do ... end) almost certainly discourages one assertion per test. If the assertion is one line and the code can explain itself, why bother with all the other crap?
&lt;/p&gt;

&lt;h3&gt;The Solution: Zebra&lt;/h3&gt;

&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre&gt;&lt;span class="ident"&gt;context&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#A5C261"&gt;With a blog post&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;setup&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;
    &lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt;        &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_person&lt;/span&gt;
    &lt;span style="color:#D0D0FF"&gt;@somebody_else&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_person&lt;/span&gt;
    &lt;span style="color:#D0D0FF"&gt;@post&lt;/span&gt;          &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_post&lt;/span&gt; &lt;span style="color:#6E9CBE"&gt;:author&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt;
  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;expect&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to&lt;/span&gt; &lt;span class="ident"&gt;be_editable_by&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;expect&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;not_to&lt;/span&gt; &lt;span class="ident"&gt;be_editable_by&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span style="color:#D0D0FF"&gt;@author&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;But, what about the test name?&lt;/h3&gt;

&lt;p&gt;I'm glad you asked. This is where zebra gets really cool. The above code will create tests with the following names:&lt;/p&gt;

&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#A5C261"&gt;test: With a blog post expect @post.to(be_editable_by(@author))&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#A5C261"&gt;test: With a blog post expect @post.not_to(be_editable_by(@somebody_else))&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, &lt;b&gt;that&lt;/b&gt; is self-documenting code. &lt;/p&gt;

&lt;h3&gt;The right tool for the job&lt;/h3&gt;

&lt;p&gt;
  The cool thing about zebra is that it's an extension to context or shoulda and matchy &lt;strike&gt;(shoulda support coming very soon)&lt;/strike&gt;. If you have a test that belongs in an &lt;tt&gt;it&lt;/tt&gt; or &lt;tt&gt;should&lt;/tt&gt; block, with a big, old-fashioned test name, you can have it. Just use should or it. When you have a short, self-documenting test, use expect. Best of both worlds.
&lt;/p&gt;

&lt;h3&gt;Get It!&lt;/h3&gt;

&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre&gt;`&lt;span class="ident"&gt;sudo&lt;/span&gt; &lt;span class="ident"&gt;gem&lt;/span&gt; &lt;span class="ident"&gt;install&lt;/span&gt; &lt;span class="ident"&gt;giraffesoft&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;zebra`&lt;/span&gt;
&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
  &lt;a href="http://github.com/giraffesoft/zebra"&gt;http://github.com/giraffesoft/zebra&lt;/a&gt;
&lt;/p&gt;



&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/Bt36otTuoIs" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/1/16/one-line-tests-without-the-smells.html</feedburner:origLink></entry>
  
  <entry>
    <title>Speaking at CUSEC</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/0c4OOOmCdAU/speaking-at-cusec.html" />
    <id>tag:jamesgolick.com,2009-01-11:1231687222</id>
    <updated>2009-01-11T15:20:22Z</updated>
    <content type="html">
&lt;p&gt;If you live in the area and you're not going to &lt;a href="http://2009.cusec.net"&gt;CUSEC&lt;/a&gt;, you're crazy. The &lt;a href="http://2009.cusec.net/speakers/"&gt;speaker lineup&lt;/a&gt; is absolutely amazing, including such names as...&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Richard Stallman (yes, the famous RMS)&lt;/li&gt;
  &lt;li&gt;Dan Ingalls&lt;/li&gt;
  &lt;li&gt;Avi Bryant (if you've never heard Avi speak, you don't know what you're missing)&lt;/li&gt;
  &lt;li&gt;Giles Bowkett&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds expensive, right? Wrong.&lt;/p&gt;
  
&lt;p&gt;&lt;b&gt;All three days of the conference cost only $150.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Also, I'll be speaking Friday morning. Here's the abstract...&lt;/p&gt;

&lt;h3&gt;Storming the Java Bastille: a political introduction to dynamic languages&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;Working with rigid, static languages is like living in a communist dictatorship. Your freedom is extremely limited, there’s a lot of bureaucracy, and it’s often painful.&lt;/p&gt;

  &lt;p&gt;Working with dynamic languages, by contrast, is like living under libertarian rule. The government is small and doesn’t like to make decisions on your behalf. They provide you a lot of freedom and leave it up to the community to decide how best to do things. But, with great power comes great responsibility. Dynamic languages are like a chainsaw: powerful, but watch out for your extremities.&lt;/p&gt;

  &lt;p&gt;In this code-heavy session, we’ll take a look at the pros and cons of both styles, hopefully without losing any limbs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If last year's CUSEC was any indication, this is going to be a great conference. Hope to see you there!&lt;/p&gt;


&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/0c4OOOmCdAU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/1/11/speaking-at-cusec.html</feedburner:origLink></entry>
  
  <entry>
    <title>François Beausoleil and Daniel Haran join GiraffeSoft and our new site launches!</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/fRm88hKwy14/francois-beausoleil-and-daniel-haran-join-giraffesoft-and-our-new-site-launches.html" />
    <id>tag:jamesgolick.com,2008-11-22:1227315178</id>
    <updated>2008-11-22T00:52:58Z</updated>
    <content type="html">
&lt;img style="display:block; float:left; margin-right:15px; margin-bottom:10px" src="http://jamesgolick.com/assets/2008/11/22/giraffesoft.gif" /&gt;&lt;p&gt;Let's start with the biggest news. This has been a long time in the making. At &lt;a href="http://rubyfringe.com"&gt;Rubyfringe&lt;/a&gt;, Francois, Daniel, and I had a long conversation about how great it would be if we could work together.&lt;/p&gt;

&lt;p&gt;We gave it a shot for &lt;a href="http://railsrumble.com"&gt;Rails Rumble&lt;/a&gt;, in which we built &lt;a href="http://whatdoesthiserrormean.com"&gt;what does this error mean&lt;/a&gt;. We won for most useful, which we took as a sign that our idea of working together was a good one.&lt;/p&gt;

&lt;p&gt;I can't express how excited I am and privileged I feel to be working with François and Daniel. They are truly top notch in every way. Their contributions to open source, previous projects, and resumes speak for themselves.&lt;/p&gt;

&lt;p&gt;If you don't know these amazing guys, you can read about &lt;a href="http://giraffesoft.ca/team/francois.html"&gt;François&lt;/a&gt; and &lt;a href="http://giraffesoft.ca/team/daniel.html"&gt;Daniel&lt;/a&gt; on our new site!&lt;/p&gt;

&lt;h3&gt;The New giraffesoft.ca&lt;/h3&gt;

&lt;p&gt;Thanks to our good friends over at &lt;a href="http://arktyp.ca"&gt;Arktyp&lt;/a&gt; and the awesome &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt; framework, we finally have a real website. With plenty of work coming in over the last 14 months or so, I was having a really hard time motivating myself to put a full fledged site together.&lt;/p&gt;

&lt;p&gt;Well, now that the &lt;a href="http://giraffesoft.ca/team"&gt;team&lt;/a&gt; is growing, I finally got my shit together to finish up the site. I'm really excited to be able to show off some of our &lt;a href="http://giraffesoft.ca/projects"&gt;past projects&lt;/a&gt; and &lt;a href="http://giraffesoft.ca/open-source"&gt;open source work&lt;/a&gt;. We've got a full range of &lt;a href="http://giraffesoft.ca/products"&gt;services products&lt;/a&gt; and we're finishing up an app or two that you'll hear more about soon. So, &lt;a href="http://giraffesoft.ca"&gt;check it out&lt;/a&gt;. It's awesome.&lt;/p&gt;

&lt;p&gt;This is just the beginning. There'll be some more giraffesoft announcements soon, so stay tuned.&lt;/p&gt;



&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/fRm88hKwy14" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2008/11/22/francois-beausoleil-and-daniel-haran-join-giraffesoft-and-our-new-site-launches.html</feedburner:origLink></entry>
  
  <entry>
    <title>MoR =&gt; open_source_hackfest?</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/817qQfoa4WQ/mor-open_source_hackfest.html" />
    <id>tag:jamesgolick.com,2008-11-04:1225831207</id>
    <updated>2008-11-04T20:40:07Z</updated>
    <content type="html">
&lt;p&gt;Over the last year or so, I’ve really enjoyed Montreal on Rails. There have been lots of awesome presentations, and general good times had by all.&lt;/p&gt;

&lt;p&gt;When Carl asked for feedback on Uservoice, a lot of people seemed interested in more presentations geared towards newbies. While presentations can be really interesting and useful, most of the best programmers I know learned their craft through open source work. There’s no better way to improve your skills (not to mention your profile in the industry).&lt;/p&gt;
 
&lt;p&gt;So, I’ve been thinking about organizing a monthly, open source hackfest.&lt;/p&gt;

&lt;p&gt;It would be an informal evening where people could come and work on FLOSS. If you have a project, it would be a great place to get help from some of your local ruby gurus, or just an excuse to work on your project. If not, it’d be a great place to pick up a project and learn from other developers.&lt;/p&gt;

&lt;p&gt;At the end of every evening, we could have a few lightning talks (5mins), to give people the opportunity to show off what they’ve been working on. Or not, if nobody wants to speak. Only rule: no preparation allowed. No slides. Nothing.&lt;/p&gt;

&lt;p&gt;Think of it sort of like Zed Shaw’s &lt;a href="http://freehackersunion.org/joining.html"&gt;Freehacker’s Union&lt;/a&gt;, minus the hazing ritual for new members.&lt;/p&gt;

&lt;p&gt;So, what do you think? If we turned MoR in to an open source hack fest for a couple of months, would you miss the presentations? Is this something you’re interested in trying out? Will you be offended if we open it up to all things Ruby, instead of just rails?&lt;/p&gt;

&lt;p&gt;Please direct your comments to the post on the &lt;a href="http://www.montrealonrails.com/2008/11/04/mor-open_source_hackfest/#comments"&gt;MoR blog&lt;/a&gt;.&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/817qQfoa4WQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2008/11/4/mor-open_source_hackfest.html</feedburner:origLink></entry>
  
</feed>
