<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>8th Light Blog: Tag Micah</title>
    <link>http://blog.8thlight.com/micah</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In the minds of the craftsmen...</description>
    <item>
      <title>Tag!  I'm it!</title>
      <description>&lt;p&gt;&lt;a href="http://blog.davidchelimsky.net/articles/2008/07/01/how-i-got-started-programming"&gt;David Chelimsky&lt;/a&gt; tagged me with this &amp;#8220;chain-blog&amp;#8221;. I&amp;#8217;ve enjoyed reading other peoples&amp;#8217; stories.  Here&amp;#8217;s mine.&lt;/p&gt;

&lt;h3&gt;How old were you when you started programming.&lt;/h3&gt;

&lt;p&gt;Hard to say.  I suppose I was legitimately writing code at 9 years old&lt;/p&gt;

&lt;h3&gt;How did you get started programming.&lt;/h3&gt;

&lt;p&gt;You might say I was born into programming.  At a very young age, maybe 4 years old, my dad (&lt;a href="http://objectmentor.com/omTeam/martin_r.html"&gt;Unclebob&lt;/a&gt;) would put me on his shoulders and take on a robot&amp;#8217;s personality.  He would remain motionless until I ordered a command.  For example, if I said &amp;#8220;walk&amp;#8221; he would start walking.  If I said &amp;#8220;turn&amp;#8221; he would turn.  And in a very computer-like-fashion, he would follow my orders to the &amp;#8220;T&amp;#8221;.  After a &amp;#8220;walk&amp;#8221; command, my dad would not stop walking until I issued a &amp;#8220;stop&amp;#8221; command.  Poor programming on my behalf often led my dad, with me on his shoulders, straight into a wall.  I used to laugh with delight as he&amp;#8217;d bounce off and walk into the wall again and again until I corrected my programming error.&lt;/p&gt;

&lt;h3&gt;What was your first language?&lt;/h3&gt;

&lt;p&gt;At 9 years old my dad taught me Logo.  I was drawing circles, squares, spirals, and in general making that turtle dizzy.&lt;/p&gt;

&lt;h3&gt;What was the first real program you wrote?&lt;/h3&gt;

&lt;p&gt;In high school I programmed casino games on my TI-81 during physics class.  You could play Black Jack, Roulette, Bet on the Horses, play the One Armed Bandit. My friend Jim Maggio even did some pixel art for the slot machine.  It was pretty sweet.  All the physics students were required to have TI-81&amp;#8217;s so my games ended up getting copied over and over.  My first open source experience I suppose.&lt;/p&gt;

&lt;h3&gt;What languages have you used since you started programming?&lt;/h3&gt;

&lt;p&gt;In chronological order&amp;#8230;&lt;/p&gt;

&lt;p&gt;Logo, Basic, Fortran, Pascal, Forth, C, C++, Scheme, Java, Python, Ruby, JavaScript, C#, Objective-C, Smalltalk, Assembly.&lt;/p&gt;

&lt;p&gt;Whoa! I&amp;#8217;m impressing myself with that list.  But who am I kidding? I doubt I could remember how to write HelloWorld in half those languages now.  &lt;/p&gt;

&lt;h3&gt;What was your first professional programming gig?&lt;/h3&gt;

&lt;p&gt;An internship at &lt;a href="http://objectmentor.com"&gt;Object Mentor&lt;/a&gt;.  I wrote some Java Servlets to automate parts of their website.&lt;/p&gt;

&lt;h3&gt;If there is one thing you learned along the way that you would tell new developers, what would it be?&lt;/h3&gt;

&lt;p&gt;Software is not a spectator sport. ie. Just watching people code won&amp;#8217;t make you a good coder.  Code as much as possible if you want to master your craft. Code at work.  Code at home.  Code on vacation (&lt;em&gt;WARNING&lt;/em&gt; Your spouse may throw your computer off the balcony).  Code for fun.  Code to kill time.  Code while you&amp;#8217;re sleeping (I mean in your dreams).&lt;/p&gt;

&lt;h3&gt;What&#8217;s the most fun you&#8217;ve ever had programming?&lt;/h3&gt;

&lt;p&gt;The project the David Chelimsky referred to was mighty fun.  But I&amp;#8217;d have to say the most fun I&amp;#8217;ve had with my colleagues at 8th Light, Paul Pagel, Jim Suchy, Eric Smith, and Doug Bradbury.  I have never worked with a stronger team. When it comes to software, I imagine we could prevail over any challenge.  Outside of software, our strengths are less impressive&amp;#8230;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We started a basketball league and had a perfect record:  0-10. That&amp;#8217;s right, we lost 10 out of 10 games.&lt;/li&gt;
&lt;li&gt;We went on a ski trip together an managed to loose some family members in the mountains, during a snowstorm, at night.  They lived.&lt;/li&gt;
&lt;li&gt;Doing push ups every hour of every working day surely made us stronger and earned us an infamous reputation in the office.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Up Next&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://blog.8thlight.com/articles/tag/paul"&gt;Paul Pagel&lt;/a&gt;,
&lt;a href="http://blog.8thlight.com/articles/tag/jim"&gt;Jim Suchy&lt;/a&gt;,
&lt;a href="http://blog.8thlight.com/articles/tag/eric"&gt;Eric Smith&lt;/a&gt;,
&lt;a href="http://blog.8thlight.com/articles/tag/doug"&gt;Doug Bradbury&lt;/a&gt;,
&lt;a href="http://www.linkedin.com/pub/4/678/7B4"&gt;Matt Segvich&lt;/a&gt;,
&lt;a href="http://blog.objectmentor.com/articles/category/uncle-bobs-blatherings"&gt;Unclebob&lt;/a&gt;,
&lt;a href="http://blog.objectmentor.com/articles/category/young-bobs-rants"&gt;Bob Koss&lt;/a&gt;,
&lt;a href="http://michaelfeathers.typepad.com/"&gt;Michael Feathers&lt;/a&gt;,
&lt;a href="http://blog.objectmentor.com/articles/category/deans-deprecations"&gt;Dean Wampler&lt;/a&gt;,
&lt;a href="http://blog.objectmentor.com/articles/category/tims-tepid-torrent"&gt;Tim Ottinger&lt;/a&gt;,
&lt;a href="http://chadfowler.com/"&gt;Chad Fowler&lt;/a&gt;,
&lt;a href="http://jakescruggs.blogspot.com/"&gt;Jake Scruggs&lt;/a&gt;,
&lt;a href="http://clarkware.com/cgi/blosxom"&gt;Mike Clark&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tag!  You&amp;#8217;re it!&lt;/p&gt;</description>
      <pubDate>Wed, 02 Jul 2008 14:46:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:6009faa0-6e53-4a7e-8169-2f10311b0908</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2008/07/02/tag-im-it</link>
      <category>Fun</category>
      <category>Micah</category>
    </item>
    <item>
      <title>Announcing Limelight</title>
      <description>&lt;p&gt;I&amp;#8217;m pleased to announce the open source Limelight project: A thin client and application framework written in Ruby (JRuby).&lt;/p&gt;

&lt;div style="text-align: center;"&gt;
&lt;a href="http://limelight.8thlight.com"&gt;&lt;img style="border: 0px;" src="/files/limelight_logo.png"/&gt;&lt;/a&gt;

&lt;a href="http://limelight.8thlight.com"&gt;
    http://limelight.8thlight.com
&lt;/a&gt;
&lt;/div&gt;</description>
      <pubDate>Mon, 02 Jun 2008 20:42:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:53147eae-e5e2-4b46-bbb8-f6f4ca47ec48</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2008/06/02/announcing-limelight</link>
      <category>Coding</category>
      <category>Fun</category>
      <category>Micah</category>
    </item>
    <item>
      <title>LimeLight at RailsConf 2008</title>
      <description>&lt;p&gt;Back at RubyConf 2007 I prepared a &lt;a href="http://rejectconf4.confreaks.com/d2t3_4th_annual_reject_conf_8th_light.html" target="new"&gt;1 minute presentation&lt;/a&gt;, well&amp;#8230; more of a teaser, about an application framework called LimeLight.&lt;/p&gt;

&lt;p&gt;What is it?  LimeLight is a selfish dream of mine.  In a nutshell it&amp;#8217;s a light weight ruby framework for building rich client applications.  To explain further, know this. I hate building web applications.  Not because they&amp;#8217;re hard to build or anything silly like that.  It&amp;#8217;s because they&amp;#8217;re so perverted.  Writing web apps makes me feel dirty; as though I&amp;#8217;ve sunk into a pit of waste and decay where the foundation of my work is a pool of sludge.  No matter how hard I may try, the very nature of modern web apps taints my code and leaves me a sour, grumpy developer.&lt;/p&gt;

&lt;div style="border: 1px solid blue; width: 100px; height: 100px; text-align: center; background-color: white; float: right;"&gt;
    &lt;div id="light" style="border: 1px solid black; width: 50px; height: 35px; margin: 10px 24px 10px 24px; 
                            background-color: red; text-align: center; padding-top: 15px;"&gt;
        Stop
    &lt;/div&gt;
    &lt;input id="button" type="submit" value="Start" onclick="stopOrGo();"/&gt;
    &lt;script type="text/javascript"&gt;
        function stopOrGo() {
            var button = document.getElementById('button');
            var light = document.getElementById('light');
            if(button.value == 'Start') {
                start(button, light);
            }
            else {
                stop(button, light);
            }
        }

        function stop(button, light) {
            light.style.backgroundColor = "red";
            light.innerHTML = "Stop";
            button.value = "Start";
        }

        function start(button, light) {
            light.innerHTML = "Go!";
            button.value = "Stop";
            blink();
        }

        function blink() {
            var light = document.getElementById('light');
            if(light.innerHTML == "Go!")
            {
                if(light.style.backgroundColor == "green") {
                    light.style.backgroundColor = "lightgrey";  
                }
                else {
                    light.style.backgroundColor = "green";
                }
                setTimeout("blink()", 500);
            }
        }
    &lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;To understand what I mean, consider the trivial little widget on the right here.  Try clicking the button and watch the light blink. Simple huh? Can you count the number of languages/technologies used in implementing this widget? And don&amp;#8217;t forget the code required on the server side&amp;#8230;.. &lt;/p&gt;

&lt;p&gt;I count 5.  That is, in most cases this widget would require about 5 or more different languages.  Let&amp;#8217;s count.  HTML of course.  CSS to make it look right.  JavaScript.  That&amp;#8217;s 3, but in most cases you&amp;#8217;ve got server-side code which, if you&amp;#8217;re lucky, involves Ruby and ERB.  Think about it.  You need to know 5 difference languages to build that silly widget. Yikes!&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll include the code below.  Know that I&amp;#8217;ve made every effort to make this code as clean and simple as possible.  Still, I would need to borrow your hands and feet to count all the things I find distasteful about it.  Have a close look.  Ask yourself, &amp;#8220;Couldn&amp;#8217;t there be an easier way to do this?&amp;#8221;  I say there is.    &lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.railsconf.com" style="float: left; margin: 5px;"&gt;
&lt;img src="http://en.oreilly.com/rails2008/public/asset/asset/1174" width="210" height="60"  border="0"  alt="RailsConf 2008" title="RailsConf 2008"  /&gt;
&lt;/a&gt;
If you&amp;#8217;d like to learn more, I&amp;#8217;ll be &lt;a href="http://en.oreilly.com/rails2008/public/schedule/detail/1984" target="new"&gt;presenting on the topic&lt;/a&gt; at RailsConf 2008.  Or you can come back this this blog site later.  I&amp;#8217;ll be sure to post any exciting progress.&lt;/p&gt;

&lt;div&gt;
&lt;pre&gt;
&amp;lt;div style="border: 1px solid blue; width: 100px; height: 100px; 
               text-align: center; background-color: white; 
               float: right;"&amp;gt;
    &amp;lt;div id="light" 
            style="border: 1px solid black; width: 50px; 
            height: 35px; margin: 10px 24px 10px 24px; 
            background-color: red; text-align: center; 
            padding-top: 15px;"&amp;gt;
        Stop
    &amp;lt;/div&amp;gt;
    &amp;lt;input id="button" type="submit" 
              value="Start" onclick="stopOrGo();"/&amp;gt;
    &amp;lt;script type="text/javascript"&amp;gt;
        function stopOrGo() {
            var button = document.getElementById('button');
            var light = document.getElementById('light');
            if(button.value == 'Start') {
                start(button, light);
            }
            else {
                stop(button, light);
            }
        }

        function stop(button, light) {
            light.style.backgroundColor = "red";
            light.innerHTML = "Stop";
            button.value = "Start";
        }

        function start(button, light) {
            light.innerHTML = "Go!";
            button.value = "Stop";
            blink();
        }

        function blink() {
            var light = document.getElementById('light');
            if(light.innerHTML == "Go!")
            {
                if(light.style.backgroundColor == "green") {
                    light.style.backgroundColor = "lightgrey";  
                }
                else {
                    light.style.backgroundColor = "green";
                }
                setTimeout("blink()", 500);
            }
        }
    &amp;lt;/script&amp;gt;
&amp;lt;/div&amp;gt;

&lt;/pre&gt;
&lt;/div&gt;</description>
      <pubDate>Tue, 05 Feb 2008 04:32:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:ff4a010a-3b9e-4b2e-95b3-e8fce2d24838</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2008/02/05/limelight-at-railsconf-2008</link>
      <category>Coding</category>
      <category>Fun</category>
      <category>Micah</category>
    </item>
    <item>
      <title>Micah's General Guidelines on Ruby require</title>
      <description>&lt;p&gt;Ruby files have to require other files.  There&amp;#8217;s not avoiding it.  Techniques to manage require statements are numerous and varied.  Having tried most of them, I&amp;#8217;ve found a system that works well for me.  What follows are the guidelines I use to manage Ruby &lt;code&gt;require&lt;/code&gt; statements.&lt;/p&gt;

&lt;h2&gt;1. Establish a Convenient Search Path&lt;/h2&gt;

&lt;p&gt;Although it&amp;#8217;s possible to use absolute paths or complex relative paths such as below,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require "/Users/micahmartin/Projects/ttt/lib/game"
require File.dirname(__FILE__) + "../../../lib/ai/winner"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this should be avoided as much as possible.  Otherwise you&amp;#8217;ll be fixing dozens of &lt;code&gt;require&lt;/code&gt; statements every time you move a file.  It&amp;#8217;s no fun.  You&amp;#8217;ll want your &lt;code&gt;require&lt;/code&gt;s to look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require "game"
require "ai/winner"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To achieve this, add your lib directory to the ruby search path.&lt;/p&gt;

&lt;p&gt;$: &amp;lt;&amp;lt; File.expand_path(File.dirname(&lt;strong&gt;FILE&lt;/strong&gt;) + &amp;#8220;/../lib&amp;#8221;))&lt;/p&gt;

&lt;p&gt;This will have to go in one of the first files that gets loaded.  If you&amp;#8217;ve got a standalone Ruby app, you could add this to the startup script.  In a Rails app, it can go in environment.rb.  If you&amp;#8217;re using RSpec, you may want to add it to spec_helper.rb.&lt;/p&gt;

&lt;h2&gt;2. Independent Requiring over Require Farms&lt;/h2&gt;

&lt;p&gt;&lt;img src="http://blog.8thlight.com/files/require_farm1.png" style="float: right;"/&gt;
In some projects, you&amp;#8217;ll find files that contain nothing but &lt;code&gt;require&lt;/code&gt; statements.  It&amp;#8217;s common in gem projects.  The advantage is that users of the library need only require one file which in turn requires everything else you&amp;#8217;ll need.  Convenient huh? Sure is. But there are 2 major consequences of this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Maintenance Mayhem&lt;/em&gt; - Every time you add, delete, or rename a file you have to remember to update the require farm file.  It&amp;#8217;s easy to forget.  And the order of requires can get very hard to manage especially if you end up with cyclic dependancies.  &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Drowning in Dependancies&lt;/em&gt; - Require Farms have a tendency to require more than you want.  If there&amp;#8217;s only a portion of the library you&amp;#8217;d like to use, with the Require Farm you get the whole thing.  The extra dependancies will consume more memory at run time and they may add undesired behavior to your system.  In general, this is a violation of the &lt;a href="http://www.objectmentor.com/resources/articles/dip.pdf"&gt;Dependancy Inversion Principle&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rather than build Require Farms, allow each file to be responsible for it&amp;#8217;s own dependancies.  Let each file require the files it needs to work.  This approach can be a bit annoying as you&amp;#8217;ll find your self using altogether more &lt;code&gt;require&lt;/code&gt; statements, but it&amp;#8217;ll pay off in the long run.  With each file independently managing it&amp;#8217;s dependancies, the system will be easier to maintain and it&amp;#8217;s components more reusable. &lt;/p&gt;

&lt;h2&gt;3. Building Absolute Paths&lt;/h2&gt;

&lt;p&gt;Try as you may, you can&amp;#8217;t always avoid using absolute file paths in your &lt;code&gt;require&lt;/code&gt; statements.  The following is reliable way to refer to other files.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;File.join(File.expand_path(File.dirname(__FILE__)), "..", "spec_helper")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let me break it down.  First:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;File.dirname(__FILE__)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This gives you the directory of the current file that is being executed.  However, you never know what you&amp;#8217;re gonna get since the form of the path is based on how the program was executed.  This might give you an absolute path or it might give you a relative path from anywhere on the system.  In some cases, Ruby won&amp;#8217;t do what you expect with relative paths so it&amp;#8217;s best to expand this into an absolute path.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;File.expand_path(File.dirname(__FILE__)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you&amp;#8217;ve got an absolute file path and you just have to add a relative path to the desired file.  Normally I&amp;#8217;d do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;File.expand_path(File.dirname(__FILE__) + "../spec_helper")
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, this is not quite portable since I&amp;#8217;m using forward slashes.  To get this to work on any system independent of file separator, use &lt;code&gt;File.join&lt;/code&gt; as shown above.  Use this technique to require files when you don&amp;#8217;t have your search path configured.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy Requiring!&lt;/em&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 08 Oct 2007 19:10:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:08ac1295-84cd-4503-89ad-901c69c51513</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/10/08/micahs-general-guidelines-on-ruby-require</link>
      <category>Coding</category>
      <category>Micah</category>
    </item>
    <item>
      <title>Ruby DSL Blocks</title>
      <description>&lt;p&gt;There&amp;#8217;s a common pattern I&amp;#8217;ve seen for developing DSLs (Domain Specific Language) in Ruby.  It&amp;#8217;s used in RSpec, the Statemachine Gem, and Unclebob&amp;#8217;s  Clean Code talk at RailsConf 2007.  I haven&amp;#8217;t seen a name for this pattern so I&amp;#8217;ll call it the &lt;strong&gt;DSL Block Pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RSpec&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe "Bowling Game" do
    it "should score 0 on a gutter game" do
        game = Game.new
        20.times { game.roll(0) }
        game.score.should eql(0)
    end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Statemachine&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sm = Statemachine.build do
    trans :locked, :coin, :unlocked
    trans :locked, :pass, :locked
    trans :unlocked, :pass, :locked
    trans :unlocked, :coin, :unlocked
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Parser&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;parser = Args.expect do
    boolean "l"
    number "p"
    string "d"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&amp;#8217;s the problem.  You&amp;#8217;ve got to write code for specific domain such as writing specifications (RSpec), defining a Statemachine, or defining command line arguments (Unclebob&amp;#8217;s Clean Code talk).  These domains have a contained and well defined terminology set.  Often the cleanest, most elegant way to express this code is to create a DSL.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/starbucks.jpg" style="float: right;" width="200"/&gt;
Before diving into the example, let me say that I like coffee as much as the next guy.  But I feel lost when ever I go to a Starbucks.  As you know, Starbucks has a it&amp;#8217;s own language, DSL if you will, for ordering coffee. What follows is a DSL Block for ordering Starbucks coffee.&lt;/p&gt;

&lt;p&gt;The general grammar for ordering coffee is: &lt;em&gt;Size, Adjective (optional), Type of Coffee&lt;/em&gt;.  This is by no means comprehensive but it&amp;#8217;s sufficient for the example.  So if you wanted to order a large coffee, for example,  you would say, &lt;em&gt;Grande Coffee&lt;/em&gt;.  A small espresso: &lt;em&gt;Short Americano&lt;/em&gt;. An extra large mixture of regular and decaffeinated coffee with some half and half: &lt;em&gt;Venti Breve Half Caff&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Given the task to code these coffee orders, I&amp;#8217;d like to be able to code it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; Starbucks.order do
    grande.coffee
    short.americano
    venti.breve.half_caff
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ok that looks good, but as you look closely, you&amp;#8217;ll start to wonder about those methods, &lt;code&gt;grande, short, and venti&lt;/code&gt;  &amp;#8220;Do they have to be defined on the Kernel?&amp;#8221; you may ask. Defining them on the Kernel is a scary prospect. And that may convince you to clutter the syntax by passing an object into the block like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Starbucks.order do |order|
    order.grande.coffee
    order.short.americano
    order.venti.breve.half_caff
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This would allow you to define the &lt;code&gt;grande, short, and venti&lt;/code&gt; methods on the object passed into the block.  Although you do need an object where &lt;code&gt;grande, short, and venti&lt;/code&gt; will be defined, you don&amp;#8217;t need to add an argument to the block.  You&amp;#8217;ll find code out there, such as Migrations, that uses this less optimal route.  It&amp;#8217;s not necessary.  The trick to get rid of the argument is below:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module Starbucks

  def self.order(&amp;amp;block)
    order = Order.new
    order.instance_eval(&amp;amp;block)
    return order.drinks
  end

  class Order

    attr_reader :drinks

    def initialize
      @drinks = []
    end

    def short
      @size = "small"
      return self
    end

    def grande
      @size = "large"
      return self
    end

    def venti
      @size = "extra large"
      return self
    end

    def coffee
      @drink = "coffee"
      build_drink
    end

    def half_caff
      @drink = "regular and decaffeinated coffee mixed together"
      build_drink
    end

    def americano
      @drink = "espresso"
      build_drink
    end

    def breve
      @adjective = "with half and half"
      return self
    end

    private

    def build_drink
      drink = "#{@size} cup of #{@drink}"
      drink &amp;lt;&amp;lt; " #{@adjective}" if @adjective
      @drinks &amp;lt;&amp;lt; drink

      @size = @drink = @adjective = nil
    end
  end

end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see that the &lt;code&gt;Order&lt;/code&gt; object is doing all the work.  It&amp;#8217;s got the responsibility of interpreting the DSL, so let&amp;#8217;s call it the Interpreter Object.  The &lt;code&gt;Module::order&lt;/code&gt; method simply creates an instance of &lt;code&gt;Order&lt;/code&gt; and calls &lt;code&gt;istance_eval&lt;/code&gt; on it.  This causes the block to execute using the binding of the &lt;code&gt;Order&lt;/code&gt; instance.  All of the methods on &lt;code&gt;Order&lt;/code&gt; will be accessible to the block.&lt;/p&gt;

&lt;p&gt;The Interpreter Object can do any number of things as it interprets the DSL.  In this case it simply generates a translation for Starbucks newbies.  But, the sky&amp;#8217;s the limit really.&lt;/p&gt;

&lt;p&gt;&lt;a name="#all_the_source" href="#all_the_source" onclick="document.getElementById('all_the_source').style.display = 'block'"&gt;Show all the source code.&lt;/a&gt;&lt;/p&gt;

&lt;div id="all_the_source" style="display: none;"&gt;
&lt;pre&gt;&lt;code&gt;
    module Starbucks

      def self.order(&amp;block)
        order = Order.new
        order.instance_eval(&amp;block)
        return order.drinks
      end

      class Order

        attr_reader :drinks

        def initialize
          @drinks = []
        end

        def short
          @size = "small"
          return self
        end

        def tall
          @size = "medium"
          return self
        end

        def grande
          @size = "large"
          return self
        end

        def venti
          @size = "extra large"
          return self
        end

        def coffee
          @drink = "coffee"
          build_drink
        end

        def decaf
          @drink = "decaffeinated coffee"
          build_drink
        end

        def half_caff
          @drink = "regular and decaffeinated coffee mixed together"
          build_drink
        end

        def americano
          @drink = "espresso"
          build_drink
        end

        def mocha
          @drink = "espresso mixed with chocolate, milk, and topped with whipped cream"
          build_drink
        end

        def cappuchino
          @drink = "espresso mixed with milk and topped with steamed milk"
          build_drink
        end

        def no_whip
          @adjective = "without the whipped cream"
          return self
        end

        def non_fat
          @adjective = "with non-fat milk"
          return self
        end

        def breve
          @adjective = "with half and half"
          return self
        end

        def extra_shot
          @adjective = "with an extra shot of espresso"
          return self
        end

        def soy
          @adjective = "with soy milk"
          return self
        end

        def extra_hot
          @adjective = "with super heated milk"
          return self
        end


        private

        def build_drink
          drink = "#{@size} cup of #{@drink}"
          drink &lt;&lt; " #{@adjective}" if @adjective
          @drinks &lt;&lt; drink

          @size = @drink = @adjective = nil
        end
      end

    end

    require File.expand_path(File.dirname(__FILE__) + "/starbucks")

    #### Specs ####

    describe "Starbucks" do

      it "should handle empty orders" do
        Starbucks.order {}.should eql([])
      end

      it "should handle regular coffee with all the sizes" do
        Starbucks.order do
          short.coffee
          tall.coffee
          grande.coffee
          venti.coffee
        end.should eql(["small cup of coffee",
                        "medium cup of coffee",
                        "large cup of coffee",
                        "extra large cup of coffee"])
      end


      it "should deal with types of drinks" do
        Starbucks.order do
          short.decaf
          short.half_caff
          short.americano
          short.mocha
          short.cappuchino
        end.should eql(["small cup of decaffeinated coffee",
                        "small cup of regular and decaffeinated coffee mixed together",
                        "small cup of espresso",
                        "small cup of espresso mixed with chocolate, milk, and topped with whipped cream",
                        "small cup of espresso mixed with milk and topped with steamed milk"])
      end

      it "should handle the adjectives" do
        Starbucks.order do
          short.no_whip.coffee
          short.non_fat.coffee
          short.breve.coffee
          short.extra_shot.coffee
          short.soy.coffee
          short.extra_hot.coffee
        end.should eql(["small cup of coffee without the whipped cream",
                        "small cup of coffee with non-fat milk",
                        "small cup of coffee with half and half",
                        "small cup of coffee with an extra shot of espresso",
                        "small cup of coffee with soy milk",
                        "small cup of coffee with super heated milk",])
      end

    end 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
      <pubDate>Sun, 20 May 2007 08:45:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:2c4a8bba-8e80-4918-a66f-727694ba4522</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/05/20/ruby-dls-blocks</link>
      <category>Coding</category>
      <category>Micah</category>
      <enclosure type="image/jpeg" length="12655" url="http://blog.8thlight.com/files/starbucks.jpg"/>
    </item>
    <item>
      <title>Chirb Statemachine Talk</title>
      <description>&lt;p&gt;Last night I presented the Ruby Statemachine Gem to the &lt;a href="http://chirb.org"&gt;Chicago Ruby Users Group (Chirb)&lt;/a&gt; Below are links to download the slides and coding example used.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Finite State Machines and the Statemachine Ruby Gem (Slides):&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="/files/statemachines_chirb0407.pdf"&gt;statemachines_chirb0407.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Statemachine Exercises:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="/files/statemachine_exercise.zip"&gt;statemachine_exercise.zip&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="/files/parser_spec.rb"&gt;parser_spec.rb - Additional specs contributed by Michael Buselli&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Tue, 08 May 2007 07:28:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:99319e73-6711-43e6-9954-9d55a3823c8d</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/05/08/chirb-statemachine-talk</link>
      <category>Statemachine</category>
      <category>Micah</category>
      <enclosure type="text/x-ruby-script" length="1334" url="http://blog.8thlight.com/files/parser_spec.rb"/>
    </item>
    <item>
      <title>Understanding Statemachines, Part 4: Superstates</title>
      <description>&lt;h3&gt;Superstates&lt;/h3&gt;

&lt;p&gt;Often in statemachines, duplication can arise. For example, the vending machine in our examples may need periodic repairs.  It&amp;#8217;s not certain which state the vending machine will be in when the repair man arrives.  So all states should have a transition into the &lt;code&gt;Repair Mode&lt;/code&gt; state.&lt;/p&gt;

&lt;div style="text-align: center;"&gt;&lt;img width="400" style="border: 1px solid black" src="/files/vending_machine4b.png"&gt;&lt;br/&gt;&lt;b&gt;Diagram 1 - Without Superstates&lt;/b&gt;&lt;/div&gt;

&lt;p&gt;In this diagram, both the &lt;code&gt;Waiting&lt;/code&gt; and &lt;code&gt;Paid&lt;/code&gt; states have a transition to the &lt;code&gt;Repair Mode&lt;/code&gt; invoked by the &lt;code&gt;repair&lt;/code&gt; event.  Duplication!  We can dry this up by using the &lt;b&gt;Superstate&lt;/b&gt; construct. See below:&lt;/p&gt;

&lt;div style="text-align: center;"&gt;&lt;img width="400" style="border: 1px solid black" src="/files/vending_machine4a.png"&gt;&lt;br/&gt;&lt;b&gt;Diagram 2 - With Superstates&lt;/b&gt;&lt;/div&gt;

&lt;p&gt;Here we introduce the &lt;code&gt;Operational&lt;/code&gt; superstate.  Both the &lt;code&gt;Waiting&lt;/code&gt; and &lt;code&gt;Paid&lt;/code&gt; states are contained within the superstate which implies that they inherit all of the superstate&amp;#8217;s transitions.  That means we only need one transition into the &lt;code&gt;Repair Mode&lt;/code&gt; state from the &lt;code&gt;Operational&lt;/code&gt; superstate to achieve the same behavior as the solution in &lt;i&gt;diagram 1&lt;/i&gt;.  &lt;/p&gt;

&lt;p&gt;One statemachine may have multiple superstates.  And every superstate may contain other superstates. ie. Superstates can be nested.&lt;/p&gt;

&lt;h3&gt;History State&lt;/h3&gt;

&lt;p&gt;The solution in &lt;i&gt;diagram 2&lt;/i&gt; has an advantage over &lt;i&gt;diagram 1&lt;/i&gt;.  In &lt;i&gt;diagram 1&lt;/i&gt;, once the repair man is done he triggers the &lt;code&gt;operate&lt;/code&gt; event and the vending machine transitions into the &lt;code&gt;Waiting&lt;/code&gt; event.  This is unfortunate.  Even if the vending machine was in the &lt;code&gt;Paid&lt;/code&gt; state before the repair man came along, it will be in the &lt;code&gt;Waiting&lt;/code&gt; state after he leaves.  Shouldn&amp;#8217;t it go back into the &lt;code&gt;Paid&lt;/code&gt; state?&lt;/p&gt;

&lt;p&gt;Superstates come with the &lt;b&gt;history state&lt;/b&gt; which solves this problem.  Every superstate will remember which state it is in before the superstate is exited.  This memory is stored in a pseudo state called the &lt;b&gt;history state&lt;/b&gt;.  Transitions that end in the history state will recall the last active state of the superstate and enter it.  &lt;/p&gt;

&lt;p&gt;You can see the history state being use in &lt;i&gt;diagram 2&lt;/i&gt;.  In this solution, the history state allows the vending machine to return from a repair session into the same state it was in before, as though nothing happened at all.&lt;/p&gt;

&lt;h3&gt;Code&lt;/h3&gt;

&lt;p&gt;The following code builds the statemachine in &lt;i&gt;diagram 2&lt;/i&gt;.  Watch out for the &lt;code&gt;_H&lt;/code&gt;.  This is how the history state is denoted.  If you have a superstate named &lt;code&gt;foo&lt;/code&gt;, then it&amp;#8217;s history state will be named &lt;code&gt;foo_H&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;require 'rubygems'
require 'statemachine'

vending_machine = Statemachine.build do
  superstate :operational do
    trans :waiting, :dollar, :paid
    trans :paid, :selection, :waiting
    trans :waiting, :selection, :waiting
    trans :paid, :dollar, :paid

    event :repair, :repair_mode,  Proc.new { puts "Entering Repair Mode" }
  end

  trans :repair_mode, :operate, :operational_H, Proc.new { puts "Exiting Repair Mode" }

  on_entry_of :waiting, Proc.new { puts "Entering Waiting State" }
  on_entry_of :paid, Proc.new { puts "Entering Paid State" }
end

vending_machine.repair
vending_machine.operate
vending_machine.dollar
vending_machine.repair
vending_machine.operate&lt;/pre&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;pre&gt;Entering Repair Mode
Exiting Repair Mode
Entering Waiting State
Entering Paid State
Entering Repair Mode
Exiting Repair Mode
Entering Paid State&lt;/pre&gt;

&lt;p&gt;Next we should cover pseudo states.&lt;/p&gt;</description>
      <pubDate>Sat, 07 Apr 2007 21:19:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:3fb702aa-c403-4fad-9760-b5431dbf81f7</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/04/07/understanding-statemachines-part-4-superstates</link>
      <category>Coding</category>
      <category>Statemachine</category>
      <category>Micah</category>
    </item>
    <item>
      <title>Storing Binary Data in Postgres? Beware!</title>
      <description>&lt;p&gt;If your situation matches the following conditions, beware!&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;You&amp;#8217;re working in rails.&lt;/li&gt;
    &lt;li&gt;You&amp;#8217;re using Postgresql.&lt;/li&gt;
    &lt;li&gt;You&amp;#8217;re storing binary data in the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This was the situation on a project of mine.  We were storing PDFs and PNG images in our Postgrs database.  Everything was fine during development and testing where we used files that ranged up to a few dozen kilobytes in size.  The situation went rapidly downhill when file sizes got up in the hundreds of kilobytes to megabytes.  The worst part about it was that the errors we got were misleading and seemingly random.  They included:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;undefined method `&lt;&lt;' for nil:NilClass&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;invalid end of buffer&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;undefined class/module Packet&lt;/code&gt; (&lt;code&gt;Packet&lt;/code&gt; being a model class which was definitely defined)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These errors sent us on a wile goose chase.  The clue that finally pointed us toward the problem was the fact that it took 6 seconds to load a 4M PDF  document from the database.  That was far too long especially considering the same document could be loaded from a file instantaneously.&lt;/p&gt;

&lt;p&gt;Apparently, binary data stored in Postgresql&amp;#8217;s &lt;code&gt;bytea&lt;/code&gt; data type has to be parsed on save and load to escape and unescape certain characters.  Unfortunately the native C postgres gem doesn&amp;#8217;t do the parsing.  It&amp;#8217;s done in the &lt;code&gt;PostgreSQLAdapter.unescape_bytea&lt;/code&gt; and &lt;code&gt;PostgreSQLAdapter.escape_bytea&lt;/code&gt; methods (Ruby code) of ActiveRecord and the parsing is a bit too intensive for Ruby.  This is where the meltdown begins.  It consumes too much memory, or too much processing power, or &amp;#8230; well I don&amp;#8217;t know exactly.  But I know it breaks.&lt;/p&gt;

&lt;p&gt;We refactored our model such that all the binary data gets stored in flat files on disk rather than in the database.  After this, our Rails app came back to life.  It was MUCH faster too!  &lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s hoping that if and when you encounter this problem, Google points you to this blog entry and you find it helpful.&lt;/p&gt;</description>
      <pubDate>Sun, 18 Feb 2007 06:05:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:f828a6f0-869a-4c89-86f8-f50cc6561beb</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/02/18/storing-binary-data-in-postgres-beware</link>
      <category>Coding</category>
      <category>Micah</category>
    </item>
    <item>
      <title>Understanding Statemachines, Part 3: Conditional Logic</title>
      <description>&lt;h3&gt;Conditions&lt;/h3&gt;

&lt;p&gt;If you&amp;#8217;re doing any significant amount of work with statmachines, you will most certainly encounter some conditional logic in your statemachines.  Take our vending machine.  When ever a coin is inserted, the invoked event will depend on whether the total amount of money inserted is sufficient to buy something.  If enough money has been tendered, the display should suggest that the customer make a selection.  If insufficient money has been inserted, the customer should be prompted to insert more.
&lt;br/&gt;&lt;br/&gt;
Conditional logic can be accomplished by using &lt;b&gt;entry actions&lt;/b&gt;.  See the diagram below.&lt;/p&gt;

&lt;div style="text-align: center;"&gt;&lt;img width="400" style="border: 1px solid black" src="/files/vending_machine3.png"&gt;&lt;br/&gt;&lt;b&gt;State Diagram with Conditional Logic&lt;/b&gt;&lt;/div&gt;

&lt;p&gt;Starting in the &lt;code&gt;Accept Money&lt;/code&gt; state, when a coin is inserted, the &lt;code&gt;coin&lt;/code&gt; event is fired and the statemachine transitions into the &lt;code&gt;Coin Inserted&lt;/code&gt; state.  This is where it gets fun.  Upon entering of the &lt;code&gt;Coin Inserted&lt;/code&gt; state its entry event is invoked: &lt;code&gt;count_amount_tendered&lt;/code&gt;.  This method will count the money and invoke the &lt;code&gt;not_paid_yet&lt;/code&gt; or &lt;code&gt;paid&lt;/code&gt; event accordingly.  This will cause the statemachine to transition into the appropriate state.
&lt;br/&gt;&lt;br/&gt;
The &lt;code&gt;Coin Inserted&lt;/code&gt; state is unique.  You wouldn&amp;#8217;t expect to find the statemachine in the &lt;code&gt;Coin Inserted&lt;/code&gt; state for any reason except to make this decision.  Once the decision is made, the state changes.  States like this are called &lt;b&gt;Decision States&lt;/b&gt;.&lt;/p&gt;

&lt;h3&gt;Code&lt;/h3&gt;

&lt;pre&gt;require 'rubygems'
require 'statemachine'

class VendingMachineContext

  attr_accessor :statemachine

  def initialize
    @amount_tendered = 0
  end

  def add_coin
    @amount_tendered = @amount_tendered + 25
  end

  def count_amount_tendered
    if @amount_tendered &gt;= 100
      @statemachine.paid
    else
      @statemachine.not_paid_yet
    end
  end

  def prompt_money
    puts "$.#{@amount_tendered}: more money please"
  end

  def prompt_selection
    puts "please make a selection"
  end
end

vending_machine = Statemachine.build do
  trans :accept_money, :coin, :coin_inserted, :add_coin
  state :coin_inserted do
    event :not_paid_yet, :accept_money, :prompt_money
    event :paid, :await_selection, :prompt_selection
    on_entry :count_amount_tendered
  end
  context VendingMachineContext.new
end
vending_machine.context.statemachine = vending_machine

vending_machine.coin
vending_machine.coin
vending_machine.coin
vending_machine.coin&lt;/pre&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;pre&gt;$.25: more money please
$.50: more money please
$.75: more money please
please make a selection&lt;/pre&gt;

&lt;p&gt;Next lesson: Superstates&lt;br/&gt;
&lt;a href="/articles/2007/04/07/understanding-statemachines-part-4-superstates"&gt;Understanding Statemachines, Part 4: Superstates&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 13 Feb 2007 03:34:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:a7c8f8e8-9f01-4b56-90b9-dcedc59b2ede</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/02/13/understanding-statemachines-part-3-conditional-logic</link>
      <category>Coding</category>
      <category>Statemachine</category>
      <category>Micah</category>
      <enclosure type="image/png" length="6987" url="http://blog.8thlight.com/files/vending_machine31.png"/>
    </item>
    <item>
      <title>Clean as You Code</title>
      <description>&lt;p&gt;In my younger days I was a Line Cook at the Olive Garden.  In case you&amp;#8217;ve never worked in the food industry, Line Cooks are the guys putting meals together as fast as customers order them.  At times, it&amp;#8217;s nearly impossible to keep up.  &lt;/p&gt;

&lt;p&gt;Among the most fundamental of the Line Cook&amp;#8217;s principles was &lt;strong&gt;Clean as you go&lt;/strong&gt;.  I can remember clearly the manager walking regally down the line chanting, &amp;#8220;Clean as you go Javier.  Clean as you go Micah. Clean as you go Brian.&amp;#8221;  Cooks would remind each other from time to time too, &amp;#8220;Clean as you go!&amp;#8221;.&lt;/p&gt;

&lt;p&gt;As you&amp;#8217;re realizing, it&amp;#8217;s import to keep your station clean when you&amp;#8217;re a  cook.  Keeping things clean is not easy.  Food gets EVERYWHERE when you&amp;#8217;re putting together hundreds of meals an hour.  Why is it important to keep it clean?  Simple.  When your station is dirty, the system breaks down and it slows you down.  Utensils are dirty or missing, ingredients get mixed together, cooking surfaces are soiled&amp;#8230; Combine this with all the fire, boiling water, and sharp knives, it&amp;#8217;s dangerous too!  Worse, other cooks are not able to help out.  Uncleanliness on the line is a vicious cycle with positive feedback.  Every experienced cook keeps their station spotless at all times and unexperienced cooks learn fast.&lt;/p&gt;

&lt;p&gt;Dirtiness is a sign of trouble too.  Let&amp;#8217;s say that it&amp;#8217;s the middle of a dinner rush.  You look down the line and notice that Javier&amp;#8217;s station is becoming cluttered.  It&amp;#8217;s near certainty that in five minutes Javier&amp;#8217;s system will break down.  Food will be burnt, orders will get lost, and servers will get vocal.  Don&amp;#8217;t get servers mad!  Line Cooks work as a team though. So when you see that Javier&amp;#8217;s station is getting cluttered, you jump over and give Javier a hand every moment you can spare.&lt;/p&gt;

&lt;p&gt;This principle, &amp;#8220;Clean as you go&amp;#8221;, is well applied to software, &amp;#8220;Clean as you code&amp;#8221;.  The analogy is fairly straight forward.  Although I&amp;#8217;ve applied the principle to software for years, it was only recently that I recalled the mantra &amp;#8220;Clean as you go&amp;#8221;.  I&amp;#8217;m sure my teammates will soon grow tired of hearing me chant&amp;#8230; &amp;#8220;Clean as you code!&amp;#8221;&lt;/p&gt;</description>
      <pubDate>Mon, 29 Jan 2007 13:43:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:31876b7b-70a5-4911-adfe-b6007b9b10bb</guid>
      <author>Micah</author>
      <link>http://blog.8thlight.com/articles/2007/01/29/clean-as-you-code</link>
      <category>Craftsmanship</category>
      <category>Coding</category>
      <category>Micah</category>
    </item>
  </channel>
</rss>
