<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>8th Light - Home</title>
  <id>tag:blog.8thlight.com,2009:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://blog.8thlight.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.8thlight.com/" rel="alternate" type="text/html"/>
  <updated>2008-12-30T23:03:37Z</updated>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-12-30:4238</id>
    <published>2008-12-30T22:59:00Z</published>
    <updated>2008-12-30T23:03:37Z</updated>
    <category term="Coding"/>
    <category term="Doug"/>
    <category term="doug"/>
    <category term="embedded"/>
    <category term="ruby"/>
    <link href="http://blog.8thlight.com/articles/2008/12/30/embedded-ruby-sings-sinatra" rel="alternate" type="text/html"/>
    <title>Embedded Ruby Sings Sinatra</title>
<content type="html">
            &lt;a href=&quot;http://blog.8thlight.com/articles/2008/12/20/embedded-ruby-first-steps&quot;&gt;Last Time&lt;/a&gt; I got ruby up and running on my Arm based embedded development platform. Here is a quick summary of what Santa and I did over Christmas.

&lt;h3&gt;Sockets&lt;/h3&gt;
Getting support for sockets built into Ruby turned out to not be hard at all.  All I had to do has uncomment the extensions I wanted in ext/Setup.  Here is everything I decided to turn on.
&lt;pre&gt;&lt;code&gt;etc
fcntl
iconv
socket
stringio
strscan
syck
thread
zlib&lt;/code&gt;&lt;/pre&gt;

After a rebuild and reinstall, I could require and use 'socket.'  Welcome, Ruby, to the outside world!

&lt;h3&gt;Relocating Ruby&lt;/h3&gt;
I decided to move ruby to the 'standard' install directory (/usr/local/) instead of the root that I had done in the first iteration.  This would avoid having to set the RUBYLIB environment variable and keep any mess I made out out of the main system /bin and /lib directories.

First I removed the --prefix from the configure script I had written last time.  This will cause Ruby to build assuming the default install location (/usr/local/).
&lt;pre&gt;&lt;code&gt;#! /bin/sh
export ARM_TOOLS=/usr/local/arm/gcc-4.2.3-glibc-2.3.3/arm-unknown-linux-gnu/bin
export CC=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
export LD=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
export AR=$ARM_TOOLS/arm-unknown-linux-gnu-ar
export RANLIB=$ARM_TOOLS/arm-unknown-linux-gnu-ranlib

export ac_cv_func_getpgrp_void=yes
export ac_cv_func_setpgrp_void=yes

./configure --host=arm-unknown-linux --enable-wide-getaddrinfo&lt;/code&gt;&lt;/pre&gt;

After Ruby was built, but before installing it (make install), I hacked the DESTDIR in rbconfig.rb
&lt;pre&gt;&lt;code&gt;...
TOPDIR = File.dirname(__FILE__).chomp!(&quot;/lib/ruby/1.8/arm-linux&quot;)
DESTDIR = &quot;/~/ruby/install&quot;
CONFIG = {}
...&lt;/pre&gt;&lt;/code&gt;

This created the /usr/local tree inside my install directory.  I created a /usr/local/ on my file system and copied that tree over.  The only problem with this process is that the sh-bang line on the top of all of the ruby scrips (irb, testrb, etc.) had the wrong path in them.  They had the install path on the host machine (/~/ruby/install/usr/local/bin/ruby) instead of the actual path on the target (/usr/local/bin/ruby).  I changed those by hand.

&lt;h3&gt;Sinatra&lt;/h3&gt;
Ahh, now the good part.  Using a gem on an embedded system is an interesting problem.  I didn't want to build and install rubygems on the target.  There is no need to load down an embedded system with a package manager.  I wanted to be able to just load the gem onto the network file system I has set up from last time.  I downloaded &lt;a href=&quot;http://rubyforge.org/frs/?group_id=4415&quot;&gt;Sinatra&lt;/a&gt; and &lt;a href=&quot;http://chneukirchen.org/releases/gems/gems/rack-0.4.0.gem&quot;&gt;Rack&lt;/a&gt; and then manually installed them into my target's file system on the host machine.  Note that /arm/fs/ is the root of my networked file system. I switched off rdoc and ri to help keep the install small.

&lt;pre&gt;&lt;code&gt;sudo gem install sinatra-0.3.2.gem  -i /arm/fs/usr/local/lib/ruby/gems/1.8 --no-rdoc --no-ri
sudo gem install rack-0.4.0.gem  -i /arm/fs/usr/local/lib/ruby/gems/1.8 --no-rdoc --no-ri&lt;/code&gt;&lt;/pre&gt;

With Sinatra installed and ready to go, I wrote a quick Sinatra app.  Sinatra runs on Mongrel by default, but I wanted to run on the lighter weight Webrick web server which was already in my ruby installation.
&lt;pre&gt;&lt;code&gt;require 'rubygems'

require 'rack/handler/webrick'
require 'sinatra'

Sinatra::Application.default_options.merge!(
   :run =&gt; false,
   :env =&gt; :production,
   :port =&gt; 80
 )
  
get '/' do
	&quot;Hello Sinatra!&quot;
end

Rack::Handler::WEBrick.run Sinatra.application&lt;/pre&gt;&lt;/code&gt;

Drum roll please ...&lt;br /&gt;
&lt;img src=&quot;http://blog.8thlight.com/files/hello_sinatra.jpg&quot; /&gt;

&lt;h3&gt;Next Steps&lt;/h3&gt;
I've been plugging away on the linux device and ruby extension side of the project.  I'm still on the steep side of the learning curve, but making progress.  I'm still after that elusive blinking LED!
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-12-20:3182</id>
    <published>2008-12-20T05:00:00Z</published>
    <updated>2008-12-30T22:59:29Z</updated>
    <category term="Coding"/>
    <category term="Doug"/>
    <category term="doug"/>
    <category term="embedded"/>
    <category term="ruby"/>
    <link href="http://blog.8thlight.com/articles/2008/12/20/embedded-ruby-first-steps" rel="alternate" type="text/html"/>
    <title>Embedded Ruby - First Steps</title>
<content type="html">
            I spent the beginning of my career working on embedded systems for &lt;a href=&quot;http://www.shure.com&quot;&gt;some audio company&lt;/a&gt;.  These embedded systems were my first love in programming and to me, no flashy css on a web page can beat the thrill of writing some code that flashes an LED.  I've been working lately with Ruby a lot.  I love it. I love that the language nearly disappears and I am able to express pure intent.  Ok, so there is still syntax and such, but I can create so much more with so much less code.&lt;br /&gt;

I hate living a fragmented existence, so I've been working the last few days on bridging these two worlds of mine.  I figured that it will also give me a chance to get more familiar with linux and the latest in the embedded world.&lt;br /&gt;

&lt;h3&gt;First up, pick a platform.&lt;/h3&gt;
I chose &lt;a href=&quot;http://www.glomationinc.com/product_2440.html&quot;&gt;this&lt;/a&gt; single board computer from Glomation.  It has an ARM920T core and an LCD / touch screen interface which may be fun later.

&lt;h3&gt;Next, Tools.&lt;/h3&gt;
I was determined that I could get a toolchain up and running on my MAC, but eventually ended up running linux in a virtual machine.  Glomation had a set of tools and a pre-patched kernel already to go on their &lt;a href=&quot;http://www.glomationinc.com/support.html&quot;&gt;support page&lt;/a&gt; and our apprentice had a virtualbox linux image that he let me copy, so I was up and running quickly.&lt;br /&gt;
I do want to share with you a few of the resources I found in the processes.&lt;br /&gt;
&lt;ul&gt;
   &lt;li&gt;I began with the &lt;a href=&quot;http://www.gnuarm.com/&quot;&gt;GNUARM&lt;/a&gt; project. &lt;/li&gt;
   &lt;li&gt;Tom Walsh on the gnuarm mailing list was helpful and pointed me to his &lt;a href=&quot;http://www.openhardware.net/Embedded_ARM/Toolchain/&quot;&gt;scripts&lt;/a&gt;.  I came real close to a working toolchain on the Mac with his help.&lt;/li&gt;
   &lt;li&gt;I also gave the &lt;a href=&quot;http://www.kegel.com/crosstool/&quot;&gt;Crosstools&lt;/a&gt; project a try but ended up in the same place I was before.&lt;/li&gt;
   &lt;li&gt;Thanks to &lt;a href=&quot;http://rubyconf2008.confreaks.com/ruby-for-embedded-applications.html&quot;&gt;David Goodlad's RubyConf 2008 presentation&lt;/a&gt; I discovered &lt;a href=&quot;http://wiki.openembedded.net/index.php/Main_Page&quot;&gt;Open Embedded&lt;/a&gt;.  This seems to be where the momentum is right now.  I imagine I will give this project a careful look soon.  I wish I would have started here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Cross-Compiling Ruby&lt;/h3&gt;
A few folks have had some success cross compiling ruby and Goodlad's presentation claimed that ruby is a part of the open embedded project. I built ruby 1.8.6-p111 because that what was on my linux distribution and it seems to be a well distributed release.  Here is the script I used to configure ruby for cross compilation.  Thanks to &lt;a href=&quot;http://zenmachine.wordpress.com/cross-compiling-ruby-to-arm-processors-the-not-so-zen-way/&quot;&gt;The Zen Machine&lt;/a&gt; blog for the skeleton of this script.
&lt;pre&gt;
&lt;code&gt;
#! /bin/sh
export ARM_TOOLS=/usr/.../arm-unknown-linux-gnu/bin
export CC=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
export LD=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
export AR=$ARM_TOOLS/arm-unknown-linux-gnu-ar
export RANLIB=$ARM_TOOLS/arm-unknown-linux-gnu-ranlib

export ac_cv_func_getpgrp_void=yes
export ac_cv_func_setpgrp_void=yes

./configure --host=arm-unknown-linux --prefix=$HOME/ruby/install
&lt;/code&gt;
&lt;/pre&gt;
ARM_TOOLS is where I installed the cross compiler.  The prefix is just the place where 'make install' will drop the results of the build.

The configure script generates a file in the ruby root director called fake.rb that causes some problems when I went to 'make'  
&lt;pre&gt;
	&lt;code&gt;
/ruby-1.8.6-p111/fake.rb:12: unterminated string meets end of file (SyntaxError)	&lt;/code&gt;
&lt;/pre&gt;
I opened it up and it has a very obvious syntax error in it.  I added the missing backslash on line 12 and ruby built fine from there.
&lt;pre&gt;
	&lt;code&gt;
12           ALT_SEPARATOR = &quot;\&quot;; 	&lt;/code&gt;
&lt;/pre&gt;
becomes . . .
&lt;pre&gt;
	&lt;code&gt;
12           ALT_SEPARATOR = &quot;\\&quot;; 	&lt;/code&gt;
&lt;/pre&gt;

'make' then 'make install' and I had my cross compiled ruby&lt;br /&gt;

&lt;h3&gt;Getting Ruby onto the Target&lt;/h3&gt;
The last step to seeing little rubies flying on my ARM core was to get the build onto the target.  The Glomation board came preloaded with a kernel and a root file system.  The kernel source was provided on the &lt;a href=&quot;http://www.glomationinc.com/support.html&quot;&gt;support page&lt;/a&gt; but not the root file system.  I asked their support guy and he kindly &lt;a href=&quot;http://glomationinc.com/download1/rootfs.img&quot;&gt;posted&lt;/a&gt; it for me.  I was dreading having to rebuild a file system from scratch, so I was grateful for his help.&lt;br /&gt;

I decided that the best option would be to just have the target load of the root file system over the network on boot.  I followed &lt;a href=&quot;http://wiki.buici.com/wiki/Mounting_JFFS2_Filesystem_in_RAM&quot;&gt;these instructions&lt;/a&gt; for mounting the image on my linux VM and &lt;a href=&quot;http://ubuntuguide.org/wiki/Ubuntu:Gutsy#NFS_Server&quot;&gt;these instructions&lt;/a&gt; for setting up an NFS Server.  Mounting the file system over the network is a great option because now I can edit the file system from my Mac or linux VM and have the target see the changes without even rebooting.  Perfect!  The 2440 board came loaded with UBoot and all I had to do to load the file system over the network was to set the nfsroot in the bootargs from the bootloader's command line.&lt;br /&gt;
&lt;pre&gt;
	&lt;code&gt;
set bootargs 'nfsroot=10.0.1.151:/arm/fs rw console=ttySAC0,115200 ip=dhcp init=/linuxrc'
&lt;/code&gt;
&lt;/pre&gt;

Once booted, I only needed to set the RUBYLIB environment variable so that ruby knows where to find the libraries.  I added this to my init script.

&lt;pre&gt;
	&lt;code&gt;
export RUBYLIB=/lib/ruby/1.8&lt;/code&gt;
&lt;/pre&gt;

And there you have it.  Ruby running on my ARM board:
&lt;img src=&quot;http://blog.8thlight.com/files/hello_ruby.jpg&quot; /&gt;

&lt;h3&gt;Next Steps&lt;/h3&gt;
Here is where I want to go from here.
&lt;ul&gt;
	&lt;li&gt;Sockets.  I need to build openssl support for ruby so that I can talk to the world from Ruby.  &lt;a href=&quot;http://zenmachine.wordpress.com/cross-compiling-ruby-to-arm-processors-the-not-so-zen-way/&quot;&gt;The Zen Machine&lt;/a&gt; ought to help me out here.&lt;/li&gt;
	&lt;li&gt;Sinatra - I'd like to run Sinatra on the target and start serving up some web pages&lt;/li&gt;
        &lt;li&gt;RTC - I want to get that on chip Real Time Clock working so that it's not always 1970&lt;/li&gt;
	&lt;li&gt;Drivers and extensions - I want to be able to control some hardware from Ruby.  I've got a lot to learn here but I'll have to find or write a linux driver and then build a Ruby extension on top of it.  I'm imagining something like led.on and led.flash.&lt;/li&gt;
	&lt;li&gt;Submit to ESC.  I'm hoping to submit my work to the &lt;a href=&quot;https://www.cmpevents.com/ESCw09/a.asp?option=N&amp;amp;V=1&quot;&gt;Embedded Systems Conference.&lt;/a&gt;  I hope that Ruby can start picking up some momentum in the space and save embedded developers gobs of time like it has done in the web development world.&lt;/li&gt;
&lt;/ul&gt;

Thanks for reading.  Let me know if you have any ideas or suggestions!
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-12-03:2234</id>
    <published>2008-12-03T04:13:00Z</published>
    <updated>2008-12-17T17:36:03Z</updated>
    <category term="Coding"/>
    <category term="Jim"/>
    <category term="jim"/>
    <link href="http://blog.8thlight.com/articles/2008/12/3/one-take-on-configuring-rails-routes-and-asset-host" rel="alternate" type="text/html"/>
    <title>One Take on Configuring Rails Routes and asset_host</title>
<content type="html">
            &lt;p&gt;We recently had an interesting requirement surface.  In anticipation of the release of a number of demo environments, our customer requested that system configuration be able to be done at the server level.  The goal was to avoid being forced to use source control to manage configuration files.&lt;/p&gt;

&lt;p&gt;A little background is in order.  The systems that we are working on are pretty large.  There are two distinct, decoupled systems, each consisting of between 10 and 40 subsystems.  Of these subsystems, a handful on each side are Rails applications.  Most others are small Ruby application that talk a central &lt;a href=&quot;http://blog.8thlight.com/rinda&quot;&gt;Rinda&lt;/a&gt; server.  We already have a configuration strategy in place for the two systems, which involves a central configuration file per system which populates a globally-accessible configuration hash.&lt;/p&gt;

&lt;p&gt;The directory structure looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;p&gt;
/deployment
/deployment/system_one
/deployment/system_one/etc
/deployment/system_one/etc/config.rb
/deployment/system_one/rails_app_one
/deployment/system_one/non_rails_subsystem_one
&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;The system&lt;em&gt;one/etc/config.rb file creates the configuration hash and populates it with all of the appropriate configurations (in practice, config.rb actually loads the appropriate configuration file based on an environment variable, i.e. RAILS&lt;/em&gt;ENV, but we will ignore that here for brevity and clarity):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;APPLICATION_CONFIGURATION ||= {}
APPLICATION_CONFIGURATION[:foo] = &quot;bar&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the context of a Rails application, this central configuration file is loaded from rails&lt;em&gt;app&lt;/em&gt;one/config/environment.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Load the system configuration
require File.expand_path(&quot;/deployment/system_one/etc/config&quot;)

# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this configuration strategy in place already, the team was tasked with setting up multiple demo environments for the entire system, each deployed on a different server and accessed through a different external URL.  We could have attempted to solve the configuration issues by just adding many separate Rails environments, say demo1 and demo2, but there were a couple problems with that.  First, the configurations for the different environments would have been nearly identical.  Second, we wanted to avoid the complexity of relying on source control to manage the configurations for each deployment.  In most cases, relying on the Rails convention of setting up a new environment makes a lot of sense.  However, in our case, the only differences between the environments would be setting the asset_host and routes.  Storing this in source control means that in order to make a change to the external URL means that files under source control need to be modified, checked in and then redeployed to the affected system.  It makes much more sense to have some reasonable defaults in source control and then provide a mechanism to override these configurations at the server level.&lt;/p&gt;

&lt;p&gt;The solution to this problem ended up being quite simple.  We first agreed on an acceptable location for the server configuration file:&lt;/p&gt;

&lt;pre&gt;&lt;p&gt;
deployment/config
deployment/config/server_config.rb
&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;In order to allow for overriding the system configuration, this code was added to /deployment/system_one/etc/config.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Allow for configuration to be overridden by a config file that is not under source control
server_config_file = File.expand_path(&quot;/deployment/config/server_config.rb&quot;)
require server_config_file if File.exists?(server_config_file)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The server configuration in deployment/config/server&lt;em&gt;config.rb will be loaded (and executed), if it exists.  If it doesn&#8217;t exist, the default configurations will be used, which is the desirable behavior.  The first task was to configure the asset&lt;/em&gt;host.  To start with, we add the desired asset&lt;em&gt;host configuration to /deployment/config/server&lt;/em&gt;config.rb&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;APPLICATION_CONFIGURATION[:my_rails_app_asset_host] = &quot;https://www.example.com/my_rails_app/demo&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For each Rails environment that we want the asset&lt;em&gt;host to be configurable from the server configuration file, just add this line to the appropriate config file, e.g. deployment/system&lt;/em&gt;one/rails&lt;em&gt;app&lt;/em&gt;one/config/environments/demo.rb: &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;config.action_controller.asset_host = APPLICATION_CONFIGURATION[:my_rails_app_asset_host]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You would want to add a separate asset&lt;em&gt;host configuration for each Rails application, and each Rails application would set its own asset&lt;/em&gt;host to the appropriate configuration.  For a simple configuration like asset_host, this works great.  For routes, though, it gets a bit more complicated.  We need a &lt;a href=&quot;http://api.rubyonrails.org/classes/ActionController/Routing/RouteSet/Mapper.html&quot;&gt;Mapper&lt;/a&gt; instance in order to build a route.  For example, your routes configuration looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ActionController::Routing::Routes.draw do |map|
    map.connect ':controller/:action/:id'
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We initially saw two options.  1) Create a data structure representing the desired routes, store it in the configuration, then from the routes file iterate through the structure created in the configuration file, creating the appropriate routes; or 2) Store some Ruby code in the configuration so that the context (i.e. the Mapper instance) can be passed to the block at the run-time.  This second option eliminates the need for a secondary data structure to represent the routes.  How better to configure the routes than with the actual code used to configure them?&lt;/p&gt;

&lt;p&gt;It turned out that this was nearly as simple as the asset&lt;em&gt;host configuration.  First, let&#8217;s define the routes in /deployment/config/server&lt;/em&gt;config.rb:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;APPLICATION_CONFIGURATION[:my_rails_app_routes] = lambda do |map|
  map.connect 'my_rails_app/demo/:controller/:action/:id'
  map.connect 'my_rails_app/demo',           :controller =&gt; &quot;login&quot;, :action =&gt; &quot;index&quot;
  map.login   'my_rails_app/demo/login', :controller =&gt; &quot;login&quot;, :action =&gt; &quot;index&quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We have used the lambda method to convert a block into a Proc object.  The Proc object is stored as a value in a hash which can be executed later.  The rest should look familiar to anyone using Rails; it is exactly what we would have had in our routes file.  Now, from /deployment/system&lt;em&gt;one/rails&lt;/em&gt;app_one/config/routes.rb, we can do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ActionController::Routing::Routes.draw do |map|
    APPLICATION_CONFIGURATION[:my_rails_app_routes].call(map) if APPLICATION_CONFIGURATION[:my_rails_app_routes]
    # Install the default route as the lowest priority.
    map.connect ':controller/:action/:id.:format'
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to invoke the Proc object stored in server&lt;em&gt;config.rb, we just send the call message to the Proc stored in the configuration hash, if it exists.  In our implementation, we invoke the Proc configured in server&lt;/em&gt;config.rb before all of the other (default) routes, with the assumption that the configured routes should have the highest priority.  If we run into a case where this isn&#8217;t the case, we can address that problem then.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-11-17:1345</id>
    <published>2008-11-17T20:58:00Z</published>
    <updated>2008-11-18T13:43:44Z</updated>
    <category term="Craftsmanship"/>
    <category term="Paul"/>
    <category term="paul"/>
    <link href="http://blog.8thlight.com/articles/2008/11/17/observing-a-craftsman" rel="alternate" type="text/html"/>
    <title>Observing a Craftsman</title>
<content type="html">
            &lt;p&gt;&#8220;Knowledge can be communicated, but not wisdom.  One can find it, live it, be fortified by it, do wonders through it, but once cannot communicate and teach it.&#8221;
&#8211;Hermann Hesse, from Sidhartha&lt;/p&gt;

&lt;p&gt;My path in becoming a craftsman was not through conventional academics.  I did get a Bachelor degree in Computer Science.  During those years of learning, I was taught a lot about how to learn and how to communicate, but I learned nothing about how to practice my craft of software.  I learned how TCP/IP works, how registers are able to do math .  All of this is interesting and some of it is useful for a broader view of computer interactions as a whole.  None, however, taught me about developing software as a craft.  I did some programming, which is a prerequisite for any kind of software development.&lt;/p&gt;

&lt;p&gt;My real learning began after school.  Learning software as a craft was not done in books.  It took being around journeymen and master craftsmen to learn the way they think.  Observing their idiosyncrasies and approach to a problem is part of the learning.  Much of the wisdom is tacit.  For me it is watching the way my mentor approaches a story.  The way a craftsman sees a problem and digests it, without hurry, and finds a satisfactory solution.  Then they write code, introducing faults and fallacies the original solution could not have predicted. Finally, a meticulous approach to improve each fault in the code.  The whole time demanding perfection, without ever hitting it.  This is the good code I strive to write.  I can&#8217;t learn that by looking at the solution though.  &lt;/p&gt;

&lt;p&gt;These are observations of behavior and intent, not of actions.  For example, I have read about Test Driven Development, and it has made my job easier.  For awhile after I learned it, I wrote a lot of simple assertions, almost reverse engineering my production code in my head to figure out what the test code would look like.  However, the practice itself became ten times more valuable when I saw my mentor use the tests to design their API.  They would say things like &#8220;what do I want this to do&#8221; or &#8220;that doesn&#8217;t feel right, lets rename the method to this&#8221;.  Those insights into the thought process provide me with the experiential learning it takes to further improve my craft.  When I started thinking about TDD in a similar manner, it allows me to clean up my code and know it still works, refactor my code into easily extendable solutions, and it gives me the confidence to experiment with the aesthetics of my code.  I couldn&#8217;t fully learn that from books alone.  &lt;/p&gt;

&lt;p&gt;This is why it is so important to apprentice as a software developer.  There are many things about development that I only learned through watching the behaviors and actions of the craftsmen I admire.  To me, these are the things that open up the software world to gain wisdom.  For example, to be a better developer is not to learn a new language, but to have the wisdom to learn and understand any computer language, which requires you to learn new languages all the time.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-11-13:1214</id>
    <published>2008-11-13T19:21:00Z</published>
    <updated>2008-11-13T19:22:04Z</updated>
    <category term="Coding"/>
    <category term="Craftsmanship"/>
    <category term="Kata"/>
    <category term="Micah"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/11/13/kata-langston-s-ant-in-ruby" rel="alternate" type="text/html"/>
    <title>Kata: Langston's Ant in Ruby</title>
<content type="html">
            &lt;div&gt;
&lt;a href=&quot;http://www.vimeo.com/2234715&quot;&gt;
&lt;img src=&quot;http://blog.8thlight.com/assets/2008/11/13/langston_ant_sc.png&quot; /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;span&gt;Langston&#8217;s Ant in Ruby Kata Screencast&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;I&#8217;ve recorded my &lt;a href=&quot;http://www.vimeo.com/2234715&quot;&gt;Langston&#8217;s Ant kata&lt;/a&gt; for all to see.&lt;/p&gt;

&lt;p&gt;This particular kata, with slight variations, has been in front of an audience twice before.  Once at a &lt;a href=&quot;http://groups.softwarecraftsmanship.org/&quot;&gt;Software Craftsmanship group SCG&lt;/a&gt; meeting and again at &lt;a href=&quot;http://rubyconf.org/talks/32&quot;&gt;RubyConf2007&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On both occasions I asked the audience to evaluate my performance on a scale of 0-10, 0 being the worst kata you can imagine, and 10 being the best.  At the SCG, my performance was longer than the screencast because I didn&#8217;t use the &lt;code&gt;instance_eval&lt;/code&gt; trick and wrote multiple &lt;code&gt;case/when&lt;/code&gt; statements.  It resulted in much more code as well.  Honestly, I felt the kata dragged on a bit too long which is why I shortened in subsequent performances.  Despite this, the SCG audience gave me an average score of 8.  At RubyConf, the kata was almost exactly like the screencast and it earned me an average score of 7.  &lt;/p&gt;

&lt;p&gt;Now coming from an audience of dedicated Ruby developers, I&#8217;m quite pleased with my score.  Here&#8217;s some of the feedback I got&#8230;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use of &lt;code&gt;instance_eval&lt;/code&gt;: -1&lt;/li&gt;
&lt;li&gt;First test, going from compile error to passing tests: -1&lt;/li&gt;
&lt;li&gt;Refactoring on with red bar: -1 (not repeated in the screencast)&lt;/li&gt;
&lt;li&gt;Non-idiomatic &lt;code&gt;is_black?&lt;/code&gt;: -0.5 (fixed in screencast)&lt;/li&gt;
&lt;li&gt;Steps are too big in between tests: -1&lt;/li&gt;
&lt;li&gt;&#8230;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I find this feedback immensely valuable and thank those who took the time to provide me with it.  &lt;/p&gt;

&lt;p&gt;In martial arts, the techniques performed in kata are not always by the book.  There is an aspect of art, creativity, and entertainment.  At several points in my Langston&#8217;s Ant kata I intentionally decided to bend the rules to enhance artistic and entertainment values.  I leave it up to you whether I made the right compromise or not.&lt;/p&gt;

&lt;p&gt;After watching the kata, leave a comment with your rating and any feedback you have for me.  I thank you in advanced.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-11-10:1179</id>
    <published>2008-11-10T16:20:00Z</published>
    <updated>2008-11-10T16:24:44Z</updated>
    <category term="Coding"/>
    <category term="Fun"/>
    <category term="Limelight"/>
    <category term="Micah"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/11/10/simon" rel="alternate" type="text/html"/>
    <title>Simon</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;http://blog.8thlight.com/assets/2008/11/10/simon_game_w.jpg&quot; /&gt;
You remember the classic Simon game, right?  The one where the electronic devise will blink a color and make a sound that you have to replicate by pushing the colored buttons.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.8thlight.com/files/simon.llp&quot;&gt;&lt;img src=&quot;http://blog.8thlight.com/assets/2008/11/10/simon.png&quot; /&gt;&lt;/a&gt;
At RubyConf 2008, I cornered &lt;a href=&quot;http://onestepback.org/&quot;&gt;Jim Weirich&lt;/a&gt; and asked his opinion on Limelight.  He didn&#8217;t feel like he had seen enough of it to give a good opinion.  So we found an hour where we could both sit down and build a simple Limelight production.  We decided to build Simon.  &lt;/p&gt;

&lt;p&gt;The result is really quite simple.  It&#8217;s a couple hundred lines of code, UI, game logic, and all.  It&#8217;s also got a suite of unit tests.&lt;/p&gt;

&lt;p&gt;If &lt;a href=&quot;http://limelight.8thlight.com/main/download&quot;&gt;Limelight is installed&lt;/a&gt;, you can download the production file, and double click it, or enter the url in the Startup Limelight Production.
&lt;br /&gt;&lt;br /&gt;
Limelight Production file: http://blog.8thlight.com/files/simon.llp
&lt;br /&gt;
&lt;img src=&quot;http://blog.8thlight.com/assets/2008/11/10/simon_download.png&quot; /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://github.com/slagyr/simon&quot;&gt;Source Code&lt;/a&gt; can be found on github.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-11-08:1167</id>
    <published>2008-11-08T14:17:00Z</published>
    <updated>2008-11-08T14:22:01Z</updated>
    <category term="Coding"/>
    <category term="Craftsmanship"/>
    <category term="Fun"/>
    <category term="Micah"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/11/8/ruby-battleship-sparring-tournament" rel="alternate" type="text/html"/>
    <title>Ruby Battleship Sparring Tournament</title>
<content type="html">
            &lt;p&gt;Yesterday in &lt;a href=&quot;http://rubyconf.org/talks/32&quot;&gt;my talk at RubyConf2008&lt;/a&gt;, I announced the commencement of the &lt;a href=&quot;http://sparring.rubyforge.org/battleship/index.html&quot;&gt;Ruby Battleship Sparring Tournament&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://sparring.rubyforge.org/battleship/index.html&quot;&gt;
 &lt;img src=&quot;http://blog.8thlight.com/assets/2008/11/8/title_cover.png&quot; width=&quot;300&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an open tournament.  All are welcome to participate.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-11-05:1141</id>
    <published>2008-11-05T08:05:00Z</published>
    <updated>2008-11-05T08:23:41Z</updated>
    <category term="Micah"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/11/5/limelight-0-3-0-released" rel="alternate" type="text/html"/>
    <title>Limelight 0.3.0 Released</title>
<content type="html">
            &lt;p&gt;This release of limelight contains many new features and stability.  Perhaps most notably, Limelight will no longer eat 95% of your CPU (ouch)! It's proud to say it's becoming quite usable for real apps of considerable size. &lt;/p&gt;

&lt;div&gt;&lt;a href=&quot;http://limelight.8thlight.com&quot;&gt;&lt;img src=&quot;http://limelightwiki.8thlight.com/images/limelight_logo.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/52&quot;&gt;Default event implementation - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/63&quot;&gt;Image player - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/61&quot;&gt;Sending variables to partials - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/35&quot;&gt;CPU Hog - &lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/12&quot;&gt;Gems in productions - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/17&quot;&gt;Giving Floats to prop styles - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/47&quot;&gt;Scene's Default name - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/36&quot;&gt;Hand Cursor Stays - bug&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/46&quot;&gt;generate production templates - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/53&quot;&gt;Validate styles - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/51&quot;&gt;Auto resizing doesn't trigger update on parent. - bug&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/27&quot;&gt;Double click to open production - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/32&quot;&gt;Color as a hash - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/54&quot;&gt;Add more Known colors - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/50&quot;&gt;Need to relaunch when changing player. - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/48&quot;&gt;Shared Players - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/49&quot;&gt;Unique IDs - bug&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/41&quot;&gt;Building a Production - documentation&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/15&quot;&gt;Document Events - documentation&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/16&quot;&gt;Document Prop API - documentation&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/14&quot;&gt;Document Styles - documentation&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/37&quot;&gt;Variable size text areas - feature_request&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/39&quot;&gt;Editable TextArea size - bug&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/42&quot;&gt;Simple App screencast - documentation&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/40&quot;&gt;RDoc - documentation&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/43&quot;&gt;finish 0.2.0 release - release&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://limelight.lighthouseapp.com/projects/12073/tickets/45&quot;&gt;Reserved prop keywords - bug&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-10-29:885</id>
    <published>2008-10-29T21:23:00Z</published>
    <updated>2008-11-13T19:59:37Z</updated>
    <category term="Coding"/>
    <category term="Craftsmanship"/>
    <category term="Micah"/>
    <category term="Process"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/10/29/agile-in-buenos-aires" rel="alternate" type="text/html"/>
    <title>Agile in Buenos Aires</title>
<content type="html">
            Last week I attended &lt;a href=&quot;http://www.agiles2008.org/en/&quot;&gt;Agiles2008 in Buenos Aires, Argentina&lt;/a&gt;.  It was a fun, high energy conference.  The highlight was a heated panel discussion at the closing of the conference.  On the Panel was Matt Gelbwaks, myself, Tom and Marry Poppdieck, Dave Nicolette, and Tobias Mayer. Tobias has already &lt;a href=&quot;http://agilethinking.net/blog/2008/10/23/getting-trashed-by-the-lean-machine/&quot;&gt;posted a blog about the event&lt;/a&gt;.  So that my opinion is not misconstrued, I'll share it with you here.
&lt;br /&gt;&lt;br /&gt;
The future of Agile is &lt;a href=&quot;http://blog.8thlight.com/articles/2008/09/22/definition-of-software-craftsman&quot;&gt;Software Craftsmanship&lt;/a&gt;.  
&lt;br /&gt;&lt;br /&gt;
Software is a young industry and we're still discovering more about it every day. Yet, it has it's origins in electrical engineering.  So it's seems that, at it's inception, people assumed software was a form of engineering.  And to build software systems should be no different from engineering any other creation.  Take a bridge for example.  Before building a bridge, you have to analyze the bridge requirements.  How long will it be?  How much weight must it hold?  etc...  Once the requirements are understood, you design a solution.  Build to-scale models that you can push and stress to make sure the design hold up.  Then, once you have a solid design, can you begin construction of the bridge.
&lt;br /&gt;&lt;br /&gt;
It's waterfall.  Waterfall worked for engineering so waterfall was applied to software.  We know now that waterfall doesn't work.  Agile, is a realization that software is not a form of engineering.  Agile is a realization that software is a craft.  
&lt;br /&gt;&lt;br /&gt;
I have been to every North American Agile conference since the very first, and I have noticed a trend.  In the first conference in Charlotte NC, laptops were open on every table, around every corner, with someone or a pair of people writing code.  In many of the sessions, people were writing code or talking about it.  This is the conference where people were bragging about their Ward number (0 if you paired with Ward Cunningham.  n + 1 if you pared with someone with a Ward number of n.) and desperately trying to improve it.  It was truly a conference about software.  Over the years, less and less coding could be found at the conferences.  This last year, at the conference in Toronto, it was abysmal.  Although there was some good content, I felt like the conference had been taken over by Scrum Masters.  It was no longer a conference about software development.  It had become a conference about project management, people management, and Scrum.  This makes me sad.  
&lt;br /&gt;&lt;br /&gt;
&lt;img src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/NotreDameDeParis.jpg/300px-NotreDameDeParis.jpg&quot; width=&quot;200px&quot; /&gt;
In middle ages, if you were a lord and you wanted to build a cathedral, you found a master craftsman.  The master craftsman recruited other craftsmen and together they constructed amazing buildings that still stand today.  These craftsman were passionate about their work and cared about creating great buildings.  That is what made it work.  They didn't have scrum masters telling them what to do or cheering them on. The great work they did is a tribute to their craftsmanship.
&lt;br /&gt;&lt;br /&gt;
The future of Agile is Software Craftsmanship.  Developers out there need to realize that software is a craft.  As such, developers should strive to become craftsmen; strive to learn more about software; strive to write better code; strive to build the best software possible.  The software you get from a team of true craftsmen will be unrivaled.  It is the goal and quality within that drives a team of craftsmen.  They'll find a way to overcome any obstacles and adapt to any changes.
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-10-06:89</id>
    <published>2008-10-06T15:16:00Z</published>
    <updated>2008-11-13T20:21:22Z</updated>
    <category term="Fun"/>
    <category term="Jim"/>
    <category term="jim"/>
    <link href="http://blog.8thlight.com/articles/2008/10/6/how-jim-got-started-programming" rel="alternate" type="text/html"/>
    <title>How Jim got started programming</title>
<content type="html">
            Tagged by &lt;a href=&quot;http://blog.8thlight.com/articles/2008/07/02/tag-im-it&quot;&gt;Micah Martin&lt;/a&gt;, &lt;a href=&quot;http://blog.8thlight.com/articles/2008/08/13/how-paul-started-coding&quot;&gt;Paul Pagel&lt;/a&gt;, and &lt;a href=&quot;http://blog.8thlight.com/articles/2008/07/03/no-tag-backs&quot;&gt;Eric Smith&lt;/a&gt;.

&lt;h3&gt;How old were you when you started programming?&lt;/h3&gt;
I took an introduction to programming college class when I was a sophomore in college, so 18 years old.


&lt;h3&gt;How did you get started programming?&lt;/h3&gt;
I was looking for a new major after deciding chemistry (and lab work in particular) probably wasn't for me.  So I decided to try a few different classes, hoping to find something that interested me.  I took an accounting, an economics, and a programming class.  Luckily, I got hooked on programming instead of becoming an accountant.  


&lt;h3&gt;What was your first language?&lt;/h3&gt;
Java


&lt;h3&gt;What languages have you used since you started programming?&lt;/h3&gt;
Java, C++, Perl, JavaScript, Python, C#, ColdFusion, VB 6.0, VB.NET, VBA, PHP, Ruby, Objective-C


&lt;h3&gt;What was the first real program you wrote?&lt;/h3&gt;
Late in my sophomore year, I was fortunate and landed a job with the US Geological Survey (USGS) in Urbana, IL.  At this point, nearly all of the programming I had ever done were machine problems for my CS classes.  I was thrown into a whole new world of web programming, tasked with writing CGI scripts with this weird looking language called Perl.  My first project was to write an application to disseminate groundwater data to Illinois residents visiting this site.  This was all done using Perl to dynamically generate horrendous HTML.


&lt;h3&gt;What was your first professional programming gig?&lt;/h3&gt;
Web developer for USGS


&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;
You don't know as much as you think you do.  Even the best developers are constantly learning and working to improve their craft.  To do this, you need to read about technologies that are new to you and then practice, practice, practice.  You cannot limit your learning to between 9 and 5.


&lt;h3&gt;What’s the most fun you’ve ever had programming?&lt;/h3&gt;
It probably sounds passe by now, but the project that I and many of the 8th Lighters are currently working on has been the best professional experience I have ever had.  Never have I worked with a group of people so concerned about and cognizant of the quality of the work and the success of the project.  Software is a people business, and working with great people makes even the most mundane tasks bearable and the most difficult challenges surmountable.


Next up:
&lt;a href=&quot;http://blog.8thlight.com/articles/tag/ericm&quot;&gt;Eric Meyer&lt;a&gt; and Matt Segvich.
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-10-02:88</id>
    <published>2008-10-02T21:12:00Z</published>
    <updated>2008-11-13T20:09:40Z</updated>
    <category term="Coding"/>
    <category term="Micah"/>
    <category term="Process"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/10/2/fidelity-life-case-study" rel="alternate" type="text/html"/>
    <title>Fidelity Life Case Study</title>
<content type="html">
            As craftsmen, we're proud of our work.  Yet it's rare that we get the opportunity to show off what we do for clients.  Fortunately the kind folks at Fidelity Life have given us permission to do just that.  

Check out the case study summarizing several systems 8th Light built for Fidelity Life using mostly Ruby and Rails. This project is a whopper.

&lt;a href=&quot;http://8thlight.com/FidelityLifeCaseStudy.pdf&quot;&gt; Fidelity Life Case Study&lt;/a&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-10-02:87</id>
    <published>2008-10-02T14:11:00Z</published>
    <updated>2008-11-13T20:09:40Z</updated>
    <category term="Craftsmanship"/>
    <category term="Micah"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/10/2/software-craftsmanship-group" rel="alternate" type="text/html"/>
    <title>Software Craftsmanship Group</title>
<content type="html">
            I'm pleased to announce the inception of the Software Craftsmanship Group.

&lt;a href=&quot;http://groups.softwarecraftsmanship.org&quot;&gt;http://groups.softwarecraftsmanship.org&lt;/a&gt;

The first meeting is October 13th at 7pm in 8th Light's office.

Hope to see you there.
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-09-30:86</id>
    <published>2008-09-30T02:27:00Z</published>
    <updated>2008-11-13T20:22:10Z</updated>
    <category term="Coding"/>
    <category term="Paul"/>
    <category term="Testing"/>
    <category term="limelight"/>
    <category term="paul"/>
    <link href="http://blog.8thlight.com/articles/2008/9/30/limelight-tutorial-tic-tac-toe-excample" rel="alternate" type="text/html"/>
    <title>Limelight Tutorial: Tic Tac Toe Example</title>
<content type="html">
            &lt;p&gt;Welcome to a Limelight production.  I am going to go through a step by step introduction to limelight development using a tic tac toe game as an example.  So, lets get started.  I am going to create the directory structure and open it up in a text editor.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$ mkdir tictactoe
$ cd tictactoe
$ mate .
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;Now I need to set up Limelight.  You can just download the gem.&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
$ jruby -S gem install limelight
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
We can start by creating the props.rb file in the tictactoe directory.  The props.rb file defines the structure of your application.  A prop is named after the theater metaphor.  We are going to use them to define what our scene's physical structure look like.  We can start with a simple screen with an empty board with the nine cells we need for a tic tac toe game.  Lets create a spec directory to write a test for the props we are going to create.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$ mkdir spec
$ mkdir spec/props
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Now for the spec.  In the spec directory, we can name our spec props_spec.rb.  We want to check that there is a cell on the scene.  Here is the first test.  NOTE: To be able to run the test, you will need the spec_helper.rb in your spec directory (not the props directory).  You can copy it from the &lt;a href=&quot;http://blog.8thlight.com/files/tictac.zip&quot;&gt;sample application&lt;/a&gt;.
&lt;/p&gt;
&lt;code&gt;
&lt;pre&gt;
require File.expand_path(File.dirname(__FILE__) + &quot;/../spec_helper&quot;)

describe &quot;Props&quot; do
  include PropSpecHelper
  before(:each) do 
    setup_prop_test
  end
  
  it &quot;should have cell_0_0&quot; do
    @scene.find(&quot;cell_0_0&quot;).should_not be(nil)
  end
end
&lt;/pre&gt;
&lt;/code&gt;
&lt;p&gt;
and when we run it (You can copy the Rakefile from the sample application as well, if you want to have a specs task), 
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$ jruby -S rake spec
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
we get the failure 
&lt;/p&gt;
&lt;pre&gt;
&lt;p&gt;
1)
Errno::ENOENT in 'Props should have cell_0_0'
No such file or directory - File not found - /Users/paulwpagel/Desktop/tictactoe/props.rb
/Users/paulwpagel/Desktop/tictactoe/spec/spec_helper.rb:18:in `initialize'
/Users/paulwpagel/Desktop/tictactoe/spec/spec_helper.rb:18:in `setup_prop_test'
/Users/paulwpagel/Desktop/tictactoe/./spec/props/props_spec.rb:6:

Finished in 0.063 seconds

1 example, 1 failure
&lt;/p&gt;
&lt;/pre&gt;

&lt;p&gt;
So, lets create the props.rb file in the project root.  Now we should get the error.
&lt;/p&gt;

&lt;pre&gt;
&lt;p&gt;
1)
'Props should have cell_0_0' FAILED
expected not nil, got nil
/Users/paulwpagel/Projects/tictac/./spec/props/prop_spec.rb:12:

Finished in 0.089 seconds

1 example, 1 failure
&lt;/p&gt;
&lt;/pre&gt;

&lt;p&gt;
Each of the props accepts a block of code your can give options/structure to.  We can open the props.rb file and add a cell with the id of &quot;cell_0_0&quot; to make this test pass. 
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
main do
	board do
		cell :id =&gt; &quot;cell_0_0&quot;
	end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
And the test passes.  Lets make sure we have the rest of the id's while we are at it.  Here is a more exhaustive spec.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
it &quot;should have cells&quot; do
  @scene.find(&quot;cell_0_0&quot;).should_not be(nil)
  @scene.find(&quot;cell_0_1&quot;).should_not be(nil)
  @scene.find(&quot;cell_0_2&quot;).should_not be(nil)
  @scene.find(&quot;cell_1_0&quot;).should_not be(nil)
  @scene.find(&quot;cell_1_1&quot;).should_not be(nil)
  @scene.find(&quot;cell_1_2&quot;).should_not be(nil)
  @scene.find(&quot;cell_2_0&quot;).should_not be(nil)
  @scene.find(&quot;cell_2_1&quot;).should_not be(nil)
  @scene.find(&quot;cell_2_2&quot;).should_not be(nil)
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
And it fails in a similar manner.  Lets expand our props.rb file to make the test pass.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
main do
  board do
    cell :id =&gt; &quot;cell_0_0&quot;
    cell :id =&gt; &quot;cell_0_1&quot;
    cell :id =&gt; &quot;cell_0_2&quot;
    cell :id =&gt; &quot;cell_1_0&quot;
    cell :id =&gt; &quot;cell_1_1&quot;
    cell :id =&gt; &quot;cell_1_2&quot;
    cell :id =&gt; &quot;cell_2_0&quot;
    cell :id =&gt; &quot;cell_2_1&quot;
    cell :id =&gt; &quot;cell_2_2&quot;
  end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
And it passes. However, it is all ruby code, so I can leverage ruby functions to help me out.  Lets remove the duplication.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
main do
	board do
		3.times do |row|
		  3.times do |col|
		    cell :id =&gt; &quot;cell_#{row}_#{col}&quot;
		  end
		end
	end
end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
Much better.  Lets now move on to the styles.  Nothing will show up without a few styles.  I create a styles.rb  file in the project root and filled it with some simple content.  In Limelight, styles refer to how a prop is aesthetically displayed on the screen.  Here is an example which defines the size and gives a border to the board and the cells.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
board {
  width 152
  height 152
  border_width 1
  border_color &quot;black&quot;
}
cell {
  width 50
  height 50
  border_width 1
  border_color &quot;black&quot;
}
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
We should be able to start up Limelight and see the board.  We start Limelight like: (From the tictacctoe directory)
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$ jruby -S limelight open .
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
and there is your first Limelight screen.  Pretty easy, and all ruby code.  Lets make it more interesting.  Let us make it such that if you click on one of the squares, the square shows the 'X' mark denoting the first move.
&lt;/p&gt;
&lt;p&gt;
First we create a directory called players.  Inside go the players, which contain the actions and behavior of the props for a Limelight scene (the controllers).
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
$ mkdir players
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
We want to now make a player for the cell prop.  We create a file inside of the players directory called cell.rb.  The file will start with a definition by looking like:
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
module Cell

end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
We define all players in modules of the same name as the file and prop, by convention.  This allows Limelight to include this behavior when it needs it.  You can specify specific mappings between the props and its players, but we don't need to do that here.  So, let's make the cell more interesting.  When we click on the cell, we want it to make a large 'X' mark.  Lets start by creating a spec for the behavior.
&lt;/p&gt;

&lt;p&gt;
I created a new directory for the players spec
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
$ mkdir spec/players
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
We have to add the players directory to the ruby search path, so I added the following line to the spec_helper.
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
$: &amp;lt;&amp;lt; File.expand_path(File.dirname(__FILE__) + &quot;/../players&quot;)
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
My spec is going to find the prop that was clicked on and make that prop display an 'X', denoting the first move.  Here is what my first spec looks like (I call it cell_spec.rb):
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
require File.expand_path(File.dirname(__FILE__) + &quot;/../spec_helper&quot;)
require 'cell'

describe Cell do
  include Cell
  attr_accessor :id
  
  it &quot;should make first move an X&quot; do
    @id = &quot;cell_0_0&quot;
    @cell_one = Limelight::Prop.new
    @scene = MockScene.new
    @scene.register(&quot;cell_0_0&quot;, @cell_one)
    self.stub!(:scene).and_return(@scene)
    mouse_clicked(nil)
    @cell_one.text.should == &quot;X&quot;
  end
end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
Which provides the feedback when run:
&lt;/p&gt;

&lt;pre&gt;&lt;p&gt;
F

1)
NoMethodError in 'Cell should make first move an X'
undefined method `mouse_clicked' for #&amp;lt;spec::example::examplegroup::subclass_1:0x616750&gt;
/Users/paulwpagel/Projects/tictac/spec/players/cell_spec.rb:14:

Finished in 0.007423 seconds

1 example, 1 failure
&lt;/p&gt;
&lt;/pre&gt;
&lt;p&gt;
If you have seen a rSpec specification before, this should look syntactically familiar.  Before we move on to making the test pass, let us take closer look at a few aspects.  
&lt;/p&gt;

&lt;p&gt;
@id = &quot;cell_1_1&quot; - This line is setting the id of the imaginary prop that the players behavior will be executed against.
@scene = MockScene.new - This creates a scene to mock out.  The scene will be explained later, but for this test we are going to use the find method on scene to find our props.
@cell_one = MockProp.new - Create a mock prop that will turn to 'X' when clicked
@scene.register(&quot;cell_1_1&quot;, @cell_one) - We are giving the scene the mock prop, so the find method will find it by its id.
mouse_clicked(nil) - Simulates a mouse_click on the cell.  It takes an event, but we don't care about that yet, so lets just pass in nil.
&lt;/p&gt;
&lt;p&gt;
All right, time to make this test pass.  Lets open up the cell.rb player and see what we need done to make the test pass.  
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
module Cell
  def mouse_clicked(event)
    cell_prop = scene.find(id)
    cell_prop.text = &quot;X&quot;
  end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Run the test again, no failures. We needed to find the prop on the screen which we are concerned about.  We do this by calling find on a method scene, which will give us any prop by its unique identifier.  We are looking for the id of the element we clicked, and then we set the text of that element to 'X', which makes the test satisfied.
&lt;/p&gt;
&lt;p&gt;
Now, we can run the application from the root directory.
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
$ jruby -S limelight open . 
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
If we click on the box that is displayed, a small 'X' should appear in the upper right corner.  
&lt;/p&gt;
&lt;p&gt;
Congratulations, that is your first piece of Limelight behavior.  However, this is not very interesting yet.  Lets take it the next step and make the tic tac toe game work.  I am going to create a lib directory to hold the game model.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$ mkdir lib
$ mkdir spec/lib
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
And before I write my first spec, I am going to add the new lib directory to the ruby search path by adding the following line to the spec_helper (It is already in the example spec_helper.rb, you don't need to add it).
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$: &amp;lt;&amp;lt; File.expand_path(File.dirname(__FILE__) + &quot;/../lib&quot;)
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
So, here is what my first spec looks like:
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;

require File.expand_path(File.dirname(__FILE__) + &quot;/../spec_helper&quot;)

require 'game'

describe Game do
  it &quot;make a move in the middle square&quot; do
    game = Game.new
    game.move(1, 1)
    game.mark_at(1, 1).should == &quot;X&quot;
  end
end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
To make it pass, we need to create a game class in the lib directory and give it this code.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
class Game
  def move(row, column)
  end
    
  def mark_at(row, column)
    return &quot;X&quot;
  end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
And we can follow the test driving of the model to make the game class.  I have already done this, and you can download the models in the &lt;a href=&quot;http://blog.8thlight.com/files/tictac.zip&quot;&gt;sample application&lt;/a&gt;.  Lets move past that back to the players and hook up the game.
&lt;/p&gt;

&lt;p&gt;
I am going to create a file init.rb in the root directory.  The init.rb class gets loaded up by Limelight when you start the application.  We want to create a new game and have a way to keep it in memory for the other classes to use.  Here is what the spec looks like in a init_spec.rb in the spec directory:
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
require File.expand_path(File.dirname(__FILE__) + &quot;/spec_helper&quot;)
require &quot;game&quot;

describe &quot;init&quot; do
  it &quot;should create new game on initialization&quot; do
    game = mock('game')
    Game.should_receive(:new).and_return(game)
    Game.should_receive(:current=).with(game)
    
    require File.expand_path(File.dirname(__FILE__) + &quot;/../init&quot;)
    
  end
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
The simplest way to start that is to have a current_game class variable.  Here is the code for the init.rb.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
$: &amp;lt;&amp;lt; File.expand_path(File.dirname(__FILE__) + &quot;/lib&quot;)

require &quot;game&quot;
Game.current = Game.new
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
I add the lib directory to the ruby search path so the Limelight application would know what a game is when I require it.
&lt;/p&gt;
&lt;p&gt;
Now we need to plug the game model into the cell player.  Lets change the spec we made earlier to make the first move depending on the game model.  Here is the new version.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
it &quot;should make first move in a game&quot; do
  @id = &quot;cell_0_0&quot;
  @cell_one = Limelight::Prop.new
  @scene = MockScene.new
  @scene.register(&quot;cell_0_0&quot;, @cell_one)
  self.stub!(:scene).and_return(@scene)
  
  game = mock('game')
  Game.should_receive(:current).and_return(game)
  game.should_receive(:move).with(0, 0)
  game.should_receive(:mark).and_return(&quot;X&quot;)
  
  mouse_clicked(nil)
  
  @cell_one.text.should == &quot;X&quot;
end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;
I am mocking out the game model and passing the values from the id into the game's move method.  Here is the code that makes this pass.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
module Cell  
  def mouse_clicked( event)

    game = Game.current
    x, y = get_coordinates
    game.move(x, y)
    cell_prop = scene.find(id)
    cell_prop.text = game.mark
  end

  private ################################
  
  def get_coordinates()
    x = id[(id.length - 1)..(id.length - 1)].to_i
    y = id[(id.length - 3)..(id.length - 3)].to_i
    return x, y
  end 
  
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Minus the ugly string manipulation, it is a pretty straight forward approach.  Now we should be able to start up the application and click on any of the squares and make some moves.  There are 2 things left to do for this demo.  We need to make sure that a player can not move on a square that is already occupied, and we need to display a winner.  So for the first task, we need to write a spec to have some kind of feedback to the players that the move is invalid.  Let's add this spec to the props_spec file.
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
it &quot;should have message center for feedback to the user&quot; do
  @scene.find(&quot;message_center&quot;).should_not be(nil)
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Nice and simple.  Here is the new props.rb file.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
main do
  board do
    3.times do |row|
      3.times do |col|
        cell :id =&gt; &quot;cell_#{row}_#{col}&quot;
      end
    end
  end  
end

message_center :id =&gt; &quot;message_center&quot;
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Now lets write a spec for the cell_spec to make sure that the move is valid, else we display a message in the message center to the user they must move somewhere else.  Here is the spec.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
it &quot;should display in the message center if the space is occupied.&quot; do
  @id = &quot;cell_0_0&quot;
  @cell_one = Limelight::Prop.new
  @message_center = Limelight::Prop.new
  @scene = MockScene.new
  @scene.register(&quot;cell_0_0&quot;, @cell_one)
  @scene.register(&quot;message_center&quot;, @message_center)
  self.stub!(:scene).and_return(@scene)
  
  game = mock('game')
  Game.should_receive(:occupied?).with(0, 0).and_return(true)
  
  mouse_clicked(nil)
  
  @message_center.text.should == &quot;This space is occupied, please move in an unoccupied square&quot;
end

&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;

Same as before, with a new prop added. Here is the new cell.rb file.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
module Cell
  
  def mouse_clicked( event)
    game = Game.current
    x, y = get_coordinates
    if game.occupied?(x, y)
      message_center = scene.find(&quot;message_center&quot;)
      message_center.text = &quot;This space is occupied, please move in an unoccupied square&quot;
    else 
      game.move(x, y)
      cell_prop = scene.find(id)
      cell_prop.text = game.mark
    end
  end

  private ################################
  
  def get_coordinates()
    x = id[(id.length - 1)..(id.length - 1)].to_i
    y = id[(id.length - 3)..(id.length - 3)].to_i
    return x, y
  end 
  
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Simple if, makes it all work.  Lets remove the duplication in the specs.  Here is the new spec file.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
require File.expand_path(File.dirname(__FILE__) + &quot;/../spec_helper&quot;)
require 'cell'

describe Cell do
  include Cell
  attr_accessor :id
  
  before(:each) do
    @id = &quot;cell_0_0&quot;
    @cell_one = Limelight::Prop.new
    @scene = MockScene.new
    @message_center = Limelight::Prop.new
    @scene.register(&quot;message_center&quot;, @message_center)
    @scene.register(&quot;cell_0_0&quot;, @cell_one)
    
    self.stub!(:scene).and_return(@scene)
    @game = mock('game', :occupied? =&gt; false) 
    Game.should_receive(:current).and_return(@game)
  end
  
  it &quot;should make first move in a game&quot; do
    @game.should_receive(:move).with(0, 0)
    @game.should_receive(:mark).and_return(&quot;X&quot;)
    
    mouse_clicked(nil)
    
    @cell_one.text.should == &quot;X&quot;
  end
  
  it &quot;should display in the message center if the space is occupied.&quot; do
    @game.should_receive(:occupied?).with(0, 0).and_return(true)
    
    mouse_clicked(nil)
    
    @message_center.text.should == &quot;This space is occupied, please move in an unoccupied square&quot;
  end
    
end

&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Much better.  Now lets do the case of a winner.  Here is the spec for the cell.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
it &quot;should display there was a winner in the message center&quot; do
  @game.should_receive(:move).with(0, 0)
  @game.should_receive(:is_winner?).and_return(true)
      
  mouse_clicked(nil)
  
  @message_center.text.should == &quot;Player X has won the game, congratulations&quot;
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
And here is the new cell.rb
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
module Cell
  
  def mouse_clicked( event)
    game = Game.current
    x, y = get_coordinates
    if game.occupied?(x, y)
      message_center.text = &quot;This space is occupied, please move in an unoccupied square&quot;
    else 
      game.move(x, y)
      cell_prop = scene.find(id)
      cell_prop.text = game.mark
      message_center.text = &quot;Player #{game.mark} has won the game, congratulations&quot; if game.is_winner?

    end
  end

  private ################################
  
  def get_coordinates()
    x = id[(id.length - 1)..(id.length - 1)].to_i
    y = id[(id.length - 3)..(id.length - 3)].to_i
    return x, y
  end 
  
  def message_center
    return scene.find(&quot;message_center&quot;)
  end
  
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Now we can finish off the application by adding new game functionality, or even a computer player that can not be beaten!  However, before I let you go, we have to add some styles to the message center and pretty up the board to make it look better.  To find a comprehensive list of the styles supported in Limelight, go here(http://limelightwiki.8thlight.com/index.php/Style_Attributes).  Here is a new version of the styles.rb.
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
main {
  width &quot;100%&quot;
  horizontal_alignment &quot;center&quot;
}
board {

  width 152
  height 152
  border_width 1
	border_color &quot;black&quot;
}
cell {
  width 50
  height 50
  border_width 1
	border_color &quot;black&quot;
}
message_center_container{
  top_margin 100
  width &quot;100%&quot;
  horizontal_alignment &quot;center&quot;
}
message_center {
  width 300
  height 100
  rounded_corner_radius &quot;10&quot;
  border_color &quot;black&quot;  
  border_width 2
  padding 5
  
}
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
There was one change to the props.rb file, to wrap the message_center in a prop called message_center_container.  Also, notice the pretty rounded corners.  Easy to do.
&lt;/p&gt;
&lt;p&gt;
Here is the props.rb
&lt;/p&gt;
&lt;code&gt;&lt;pre&gt;
main do
  
  board do
    3.times do |row|
      3.times do |col|
        cell :id =&gt; &quot;cell_#{row}_#{col}&quot;
      end
    end
  end
end

message_center_container do
  message_center :id =&gt; &quot;message_center&quot;
end
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;
Happy Limelight coding!

&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-09-23:85</id>
    <published>2008-09-23T14:28:00Z</published>
    <updated>2008-10-28T03:52:10Z</updated>
    <category term="Craftsmanship"/>
    <category term="Eric Meyer"/>
    <category term="ericm"/>
    <link href="http://blog.8thlight.com/articles/2008/9/23/customer-interaction" rel="alternate" type="text/html"/>
    <title>Customer Interaction</title>
<content type="html">
            &lt;p&gt;
At 8th Light, they follow a practice of training people through an apprenticeship period.  As it is nearing the end of my apprenticeship, my mentor has asked me to write a blog talking about one thing I have learned during the course of my apprenticeship.  For me, the one skill that I learned the most about was the one skill that needed the most work in the first place.  The main thing I learned was that I was writing software for others.  Similar to that idea came the need for increased customer interaction and learning how to interact with people in general.
&lt;/p&gt;
&lt;p&gt;
Prior to working at 8th Light, almost all the programming I had ever done was either for myself, or for school projects.  In the first case, I was my own user, so there was never any issue in communication there.  And for the second case, the requirements were almost always very clearly drawn out(and not likely to change).  Again, not much room for error.  Once I came to 8th Light, I was forced to write code both specified and to be used by someone that was not myself.  This was something new to deal with.  For at least the first month or so, my thought process was for myself.  It wasn't until I came to that realization that I was able to change my thought process.  There was not one single event that made me learn this, but it was something learned over time.  When starting a story, once the requirements have been approved, I don't try to change the story.  Even if I don't agree with the desired functionality, it is what the customer wanted, and that's all that matters.  And now, when I finish a story, I take the time review the requirements and make sure it completes all the requirements that the customer specified.
&lt;/p&gt;
&lt;p&gt;
In order to provide a high quality product for another person, you must maintain a high level of collaboration with them. Without talking to them, you will never be able to guess what they want.  So, in going along with the first lesson, I also learned that a lot of customer interaction is important and any issues that arise should be addressed quickly.  One event in particular occurred that helped me realize this was the week leading up to one of our releases.  It was around this point that the customer decided to begin some testing of the system and uncovered a number of bugs.  There was some concern as to whether or not all the bugs were being kept track of in some way, and this added stress to both the development team and the customer.  It wasn't the bugs that taught me anything, but the manner in which Micah handled them.  After our iteration meeting, he called attention to the problem.  He didn't blame anybody, but just said that something needed to be done to fix the problem and even proposed some possible solutions.  It was the high level of communication between the development team and the customers that was valuable to me.  This made me realize that you have to address problems quickly, and it helps to offer multiple solutions to a problem.  The customer also seemed to appreciate that we brought the issue up, and partly because of this week of bugs, we introduced a new bug tracking tool to our process.
&lt;/p&gt;
&lt;p&gt;
I also began to learn that if you have a question about how something is supposed to work, sometimes the best solution is to just ask the customer.  At one of our recent iteration meetings, the customer mentioned functionality that they expected to be in a completed story that had never been discussed.  We realized that there was not enough feedback gained from the requirements, so we altered our process to account for that.  Now, after determining the requirements, we bring them to the customer and discuss them in person.  This is something we just began, but it already has shown signs of success.  The customer has actually come to us to discuss the requirements for some of the stories.  It is because our team values communication that we were able to improve our process.
&lt;/p&gt;
&lt;p&gt;
Learning these things has already helped me work more productively.  If I have a question, instead of trying to spend too much time reasoning it out my own, it can be much faster to either go to the requirements or directly to the customer.  During the course of my apprenticeship, I also learned a lot about coding but nothing was as important as what I learned about human interaction. This is a lesson that has definitely changed my mentality towards coding and will hopefully improve my skills as a professional software craftsman.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.8thlight.com/">
    <id>tag:blog.8thlight.com,2008-09-22:84</id>
    <published>2008-09-22T03:13:00Z</published>
    <updated>2008-11-13T20:09:40Z</updated>
    <category term="Craftsmanship"/>
    <category term="Micah"/>
    <category term="micah"/>
    <link href="http://blog.8thlight.com/articles/2008/9/22/definition-of-software-craftsman" rel="alternate" type="text/html"/>
    <title>Definition of Software Craftsman</title>
<content type="html">
            &lt;p&gt;Craftsman Clarification&lt;/p&gt;

&lt;p&gt;There has been some discrepancy in the use of the term &#8220;software craftsman&#8221;.  Rather than going into details about various uses of the term, I&#8217;ll just clarify what I believe it means.  &lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;software craftsman n. A man who practices the software craft.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are a few points to make about this definition.  &lt;/p&gt;

&lt;h2&gt;1. &#8220;software craft&#8221;&lt;/h2&gt;

&lt;p&gt;A craftsman believes that software is a craft.  This is important because not everyone believes this.  A craftsman takes pride in his work an strives to do the best job he can.  He believes that writing good software requires skill and careful attention.  That software is not something that can be manufactured nor can it be delivered faster by merely adding more bodies.&lt;/p&gt;

&lt;h2&gt;2. &#8220;practices&#8221;&lt;/h2&gt;

&lt;p&gt;A craftsman practices his craft, always striving to become more skillful, to produce better software.  &lt;/p&gt;

&lt;p&gt;There are traditionally 3 stages of craftsmanship:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apprentice&lt;/li&gt;
&lt;li&gt;Journeyman&lt;/li&gt;
&lt;li&gt;Master&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No matter which stage one may be in, as long as he practices software as a craft, he is a craftsman.&lt;/p&gt;

&lt;h2&gt;3. &#8220;A man&#8221;&lt;/h2&gt;

&lt;p&gt;Technically the term &#8220;craftsman&#8221; is gender specific.  Women are just as capable of software craftsmanship.  Indeed, I&#8217;d like to see more software craftswomen out there.  In an effort not to alienate anyone we should use the term &#8220;software craftsperson&#8221; more liberally.  &lt;/p&gt;

&lt;p&gt;&lt;b&gt;&lt;i&gt;Update:  There&#8217;s a movement afoot to make the term &#8220;software craftsman&#8221; gender neutral.  Feel free to comment below.&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;I&#8217;ve checked with the book &#8220;Software Craftsmanship&#8221; by Pete McBreen to see if it conflicts with my definition.  Although, he uses the term &#8220;software craftsman&#8221; ambiguously at times, he is careful to use the term &#8220;master craftsman&#8221; when referring to craftsmen at the height of his craft.  This is in line with my definition.&lt;/p&gt;

&lt;p&gt;I hope this serves as a reference for my use of the term.  People should not think me presumptuous when I call myself or my colleagues craftsmen.  I mean only what I describe above.&lt;/p&gt;
          </content>  </entry>
</feed>
