<?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-09-28T15:32:45-07: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" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
    <title>Building clusters in the cloud with conductor</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/qauJi33xT7Y/building-clusters-in-the-cloud-with-conductor.html" />
    <id>tag:jamesgolick.com,2009-09-28:1254173453</id>
    <updated>2009-09-28T14:30:53-07:00</updated>
    <content type="html">&lt;p&gt;
  I've been using &lt;a href="http://opscode.com/chef"&gt;chef&lt;/a&gt; in production for a while now. It saves me untold time and energy. Without it, I couldn't possibly manage our 15+ server cluster, in addition to writing and maintaining our code base. As is often the case, however, removing one bottleneck exposed several more.
&lt;/p&gt;

&lt;p&gt;
  Currently, we use a set of custom rake tasks and capistrano recipes to launch ec2 instances and deploy our chef recipes. For various reasons, this includes committing a sqlite database to a git repository. The system works, but it isn't pretty. Launching and configuring an instance, for example, requires several commands. And, without a running application, things like auto-scaling are basically out of the question.
&lt;/p&gt;

&lt;p&gt;
  I began to see a real need for an always-running application to manage my infrastructure. It would make everything easier, from launching instances to backing up EBS volumes. Today, I'm releasing an early alpha of that application.
&lt;/p&gt;

&lt;h3&gt;conductor&lt;/h3&gt;

&lt;p&gt;
   &lt;a href="http://github.com/giraffesoft/conductor"&gt;Conductor&lt;/a&gt; is the beginnings of an infrastructure management application. The version I'm releasing today has a rather limited feature set. But, the ground work is there. So, most of the fancy stuff should be relatively easy to implement.
&lt;/p&gt;

&lt;p&gt;
  Right now, conductor is able to provision instances from ec2 and configure them with chef. You provide a url to a git repository, which contains your cookbooks and some metadata. Conductor will launch your instances and configure them with the cookbooks from that repository. I'm also releasing a basic &lt;a href="http://github.com/giraffesoft/conductor-rails"&gt;rails stack&lt;/a&gt; that I'll be maintaining. I'm hoping others will contribute stacks for other plaforms.
&lt;/p&gt;

&lt;p&gt;
  Currently, things are tightly coupled to the structure of standard web infrastructure. Only two roles are supported: app, and mysql_master. The next major item on my TODO list is to make the launching system far more flexible, so that conductor can be used to manage any kind of infrastructure. I should get to this soon, since our infrastructure still isn't supported.
&lt;/p&gt;

&lt;h3&gt;Roadmap&lt;/h3&gt;

&lt;p&gt;As much as I hate vaporware, the possibilities for conductor are exciting. Your indulgence is appreciated :-).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;On-demand staging.&lt;/strong&gt; Clone the entire production environment, including databases in one click. Terminate it when you're done. Pay for what you used.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Monitoring and auto-scaling.&lt;/strong&gt; Pipe metrics, like CPU usage in to conductor. If average CPU usage on the app servers gets above a certain threshold, launch another one. If average CPU drops below the threshold, kill one. Only run the servers you actually need.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Coordinated snapshotting of EBS volumes.&lt;/strong&gt; One of the problems with running EBS volumes in a RAID configuration is backups. If you are snapshotting more than one drive at a time, you need some way to keep track of which sets of snapshots go together for recovery. Even better, a central app can be smart enough to perform the recovery itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Follow Along&lt;/h3&gt;

&lt;p&gt;
  As I said, today's release is early alpha. But, I'm going to be putting a lot of work in to this, because it'll make my job a hell of a lot easier, and save us money. So, follow along with the development by &lt;a href="http://github.com/giraffesoft/conductor"&gt;following the github project&lt;/a&gt; or &lt;a href="http://feeds.feedburner.com/JamesOnSoftware"&gt;subscribing to my blog&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  If you want to try conductor out, there's a ton of information in the &lt;a href="https://github.com/giraffesoft/conductor/blob/master/README.rdoc"&gt;README&lt;/a&gt;. I'll be hanging out in #conductorapp on freenode if you're having trouble getting things running.
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/qauJi33xT7Y" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/9/28/building-clusters-in-the-cloud-with-conductor.html</feedburner:origLink></entry>
  
  <entry>
    <title>Observational: Better Observers for ActiveRecord</title>
    <link href="http://feedproxy.google.com/~r/JamesOnSoftware/~3/PXEOs4LnMn4/observational-better-observers-for-activerecord.html" />
    <id>tag:jamesgolick.com,2009-08-05:1249521239</id>
    <updated>2009-08-05T18:13:59-07:00</updated>
    <content type="html">&lt;p&gt;
  This sort of thing appears in just about every rails app I've ever worked on:
&lt;/p&gt;

&lt;a name="figure_1"&gt;&lt;/a&gt;
&lt;pre class="twilight"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;User&lt;/span&gt;
  after_create &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;send_welcome_email&lt;/span&gt;

  &lt;span class="Keyword"&gt;protected&lt;/span&gt;
    &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;send_welcome_email&lt;/span&gt;
      &lt;span class="Support"&gt;Notifier&lt;/span&gt;.&lt;span class="Entity"&gt;deliver_welcome_email&lt;/span&gt;(&lt;span class="Variable"&gt;self&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;
  Why would the user have to ask the notifier to send him his own welcome message? That seems like the Notifier's responsibility, if you ask me.
&lt;/p&gt;

&lt;p&gt;
  Using an ActiveRecord observer, we can absolve the user of that responsibility. That code would look something like this:
&lt;/p&gt;

&lt;pre class="twilight"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;UserObserver&lt;span class="EntityInheritedClass"&gt; &lt;span class="EntityInheritedClass"&gt;&amp;lt;&lt;/span&gt; ActiveRecord::Observer&lt;/span&gt;&lt;/span&gt;
  &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;after_create&lt;/span&gt;(&lt;span class="Variable"&gt;user&lt;/span&gt;)
    &lt;span class="Support"&gt;Notifier&lt;/span&gt;.&lt;span class="Entity"&gt;deliver_welcome_email&lt;/span&gt;(user)
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;
  &lt;i&gt;Note that you'd also have to activate this observer in config/environment.rb.&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
  In some ways, using an observer is better than putting a callback in the User model. It's definitely a better division of responsibilities. But, it feels a little cumbersome.
&lt;/p&gt;

&lt;p&gt;
  In the rails app where I spend most of my time, we currently use callbacks to trigger over a dozen mailers, and almost &lt;i&gt;50&lt;/i&gt; types of activity feed items. So, we'd need a &lt;i&gt;lot&lt;/i&gt; of observer subclasses.
&lt;/p&gt;

&lt;h3&gt;A Better Way&lt;/h3&gt;

&lt;p&gt;
  The observer pattern, in some form, seemed like the right approach. I wanted to find a way to use it without creating &lt;a href="http://socialmediadouchebag.net/"&gt;eleventy billion&lt;/a&gt; observer classes.&lt;/p&gt;

&lt;p&gt;
  I came up with a gem that I call &lt;a href="http://github.com/giraffesoft/observational"&gt;observational&lt;/a&gt;. Here's what it looks like:
&lt;/p&gt;

&lt;pre class="twilight"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;Notifier&lt;span class="EntityInheritedClass"&gt; &lt;span class="EntityInheritedClass"&gt;&amp;lt;&lt;/span&gt; ActionMailer::Base&lt;/span&gt;&lt;/span&gt;
  observes &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;user&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;after&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;create&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;invokes&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;deliver_welcome_email&lt;/span&gt;

  &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;welcome_email&lt;/span&gt;(&lt;span class="Variable"&gt;user&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 example is functionally equivalent to the &lt;a href="#figure_1"&gt;first example&lt;/a&gt; above. Notifier.deliver_welcome_email will be called during the after_create callback of any User object, with the user object as the first and only argument.
&lt;/p&gt;

&lt;p&gt;
  Observational supports any standard ActiveRecord callback. As far as I know, anything you can do with a standard AR observer, you can do with observational. Let me know if I'm wrong about that.
&lt;/p&gt;

&lt;h3&gt;Get It!&lt;/h3&gt;

&lt;pre class="twilight"&gt;sudo gem install giraffesoft&lt;span class="Keyword"&gt;-&lt;/span&gt;observational
&lt;/pre&gt;
&lt;p&gt;
  Fork it &lt;a href="http://github.com/giraffesoft/observational"&gt;at github&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  Or read the &lt;a href="http://yard.soen.ca"&gt;yardoc&lt;/a&gt; at &lt;a href="http://rdoc.info/giraffesoft/observational"&gt;rdoc.info&lt;/a&gt;.
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/JamesOnSoftware/~4/PXEOs4LnMn4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://jamesgolick.com/2009/8/5/observational-better-observers-for-activerecord.html</feedburner:origLink></entry>
  
  <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-04T11:46:39-07: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-24T17:07:40-07: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-08T07:26:48-07: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>
  
</feed>
