![]() |
Articles Feed |
Categories
Archives
- July 2010 (5)
- June 2010 (4)
- April 2010 (3)
- March 2010 (2)
- February 2010 (2)
- January 2010 (1)
- December 2009 (1)
- October 2009 (2)
- September 2009 (2)
- August 2009 (1)
- July 2009 (5)
- June 2009 (2)
- May 2009 (2)
- April 2009 (8)
- March 2009 (7)
- January 2009 (2)
- December 2008 (3)
- November 2008 (5)
- October 2008 (4)
- September 2008 (6)
- August 2008 (4)
- July 2008 (5)
- June 2008 (5)
- May 2008 (4)
- April 2008 (2)
- February 2008 (4)
- January 2008 (2)
- December 2007 (2)
- November 2007 (2)
- October 2007 (2)
- September 2007 (1)
- August 2007 (3)
- July 2007 (1)
- June 2007 (4)
- May 2007 (7)
- April 2007 (2)
- February 2007 (3)
- January 2007 (3)
- November 2006 (3)
- October 2006 (3)
- September 2006 (17)
- November 2004 (1)
Craftsman Swap at Relevance - Day 4
by: colin | July 9th, 2010 | 0 comments »
Today was my last day at Relevance, pairing again with Stuart Sierra. Along with Alan Dipert, we arrived at a solution for our data woes from yesterday, and deployed it. The approach we chose exposed a problem with data interpretation when a Clojure-precondition-thrown AssertionError came back to bite us later in the day. Note to self: AssertionError, which preconditions throw, is a java.lang.Error, not a java.lang.Exception. Catch it accordingly, especially if you're running these preconditions in a thread pool!
Today may have been the most fast-paced of my time here. In the morning after the project standup, Alan did some whiteboarding with Stuart and me to explain the architecture and requirements of a spike that we spent the rest of the day on. It's going to be a pretty cool system that integrates with the rest of the client system. The interesting bits include writing to Redis (potentially with a C application) and a web service (in Clojure) that reads from Redis server to provide data to end users.
So Stuart and I started from scratch on a new Compojure app with Clojure 1.2, Leiningen, and redis-clojure. We got set up relatively quickly, and implemented a tiny web service that parses a request to find what to read from Redis, does all the proper error handling, and returns a reasonable result. We had ideas about providing several types of web services (HTML, JSON, XML, perhaps even plain text), but for the purposes of the spike, we just used the browser.
I had fully expected Stuart's knowledge of Clojure to be impressive, and I wasn't disappointed. I didn't see too many things I hadn't seen before, but having seen things is different than knowing just when to use them. There was a new macro, condp, that I hadn't seen before, and it seems like a great substitute for cond in situations where all the predicates look very similar. And if you've ever been frustrated by needing to restart a Clojure process in order to add a jar to the classpath, you'll be excited to know that Stuart is working on an interesting solution involving Nailgun.
It's also been cool to hear a couple of questions Stuart Halloway asked us about Clojure idioms (he kindly included me in the questions, which were really for Stuart Sierra). It's sometimes easy to forget that everybody's human, and the smartest people will often ask for help rather than forge ahead as a lone warrior, and they're better off for it - even when it's just rubber ducking.
On that note, my experience here has been that almost everyone seems to be pairing all the time, and those who aren't pairing are either working on project management or QA-type tasks, or have their code reviewed by someone else later on. My own experience at 8th Light has always been that two heads are better than one, so this was cool to see. Additionally, as I've said before, the developers all seem to be very good at client-relations issues, and I discovered today that, as I suspected, Relevance uses its own developers as project managers for all projects. This seems very noteworthy to me - it's been rare that I've seen a developer as project manager, but it seems to be the rule here. This is also often the case for the QA role. Certainly there is a lot of testing going on here at both the unit and acceptance test level, but there is often a developer doing QA on other developers' work.
My experience this week was great. I would highly recommend anyone considering doing something like a craftsman swap / journeyman pairing tour to just do it. This has been a wonderful experience, and it's easy to see why people like Corey Haines have been such proponents of this sort of thing. Relevance would be an excellent choice for a visit if you can make it happen - I've learned a lot, and I look forward to bringing more of that back to the team at 8th Light when I get back to Chicagoland.
Many thanks to 8th Light and Relevance for the opportunity to do this!
Craftsman Swap at Relevance - Day 3
by: colin | July 8th, 2010 | 0 comments »
Day 3 at Relevance began, as the previous days, with the company standup. Stuart Sierra, of clojure.test and Practical Clojure fame, was my pair for the day. Yep, there are two Stuarts at Relevance with Clojure books! If you're interested in Clojure, and you haven't already purchased the Apress book, electronic or print, you should do that.
We started off with some Bash scripting for a cron job. Mostly pretty straightforward stuff, though I did really like the way the structure and logging behavior in the script turned out. I won't go so far as to say that this (or any) Bash script is a thing of beauty, but it's very clear, concise, and is going to do the job very well. One cool thing I hadn't realized was possible (and Stuart mentioned that a decent amount configuration is necessary for this) is that we used using sendmail to, well, send mail - but directly from the command line. So we had something along these lines:
message=`cat email_file_contents.txt` sendmail -t $message
Our needs weren't very complex with regard to things like email headers, so it really was dirt simple to use, which was a very pleasant surprise.
We worked in Emacs, which was a bit of a struggle for me, but a reminder that I ought to be able to get around a bit better in that editor, as I'm interested in Clojure and many people in the community are gung-ho about it. org-mode was one notable takeaway there - we used the tables there to structure our table-based tests, and it can do some pretty cool formatting. I'll also say in Emacs' favor that users and authors sure are serious about documentation (just look at the previous link or the GNU Emacs Manuals), which I love to see. However, it can be a bit intimidating when you feel like you have to read a few books to get to know the editor.
At the project standup with Stuart, Alan Dipert, and Shay Frendt, the client reported a problem with a story that's still in progress, so Stuart and I spent the remainder of the day chasing this bug. There were several bright spots, however: we added several higher-level tests around some data-translation layers of the system (which includes JRuby on Rails and Clojure applications). Our tests were on the Clojure side of things, which was great to get a chance to see. Stuart had this great idea to write table-based tests a la Cucumber or Fitnesse, and we wrote a quick and dirty parser for a syntax similar to Cucumber's, plumbed a few tests in, and found one of our problems after a bit of data correction. We found the other, more mysterious problem soon afterward, and spent most of the rest of the day trying to track down the exact reason for it. It's interesting that neither of these problems had much to do with code - they were both problems with data. In one case, we received data in a format we didn't expect, and in the other, a subset of data suddenly went missing. I generally feel like good practices like TDD and pair programming can save you from many unexpected errors, but I don't know that there's a good solution for cases where data is mucked up, besides deploying, seeing what real data looks like, and adapting based on those results. I would suggest something like Haskell's QuickCheck (and similar ideas elsewhere), to try out more possibilities in the tests, but even if we used something like that here, I have a feeling we would have still ended up with an incorrect constraint, so wouldn't have caught these problems.
These problems make me wonder if, as external data drives more and more of a given application, it becomes more and more important for the data itself to be tested. That is, it would be ideal to be able to write tests that make assertions against the structure and contents of the external data. I'm not sure whether that would have been possible in this case, due to privacy concerns, but it's an idea that I'd love to hear feedback on anyway. And now that I imagine such a test system more carefully, maybe that's just design by contract in a different light?
Looking forward to tomorrow!
Craftsman Swap at Relevance - Day 2
by: colin | July 7th, 2010 | 4 comments »
Today was my second at Relevance for our craftmanship swap (see my first post for the goods on Day 1). Chris and I continued work on the project from yesterday. I was glad to have a chance to continue the story work we'd started, and see it through to completion by this afternoon, eliminating a few timezone bugs along the way (I'll get back to that).
We started the morning off with the company-wide stand-up meeting again, followed by a retrospective for the project I was pairing on. Chris explained that every iteration on a given project, Relevance does either a retrospective or a risk assessment meeting. After some scheduling and telephone difficulties on the client's side were (mostly) sorted out, Jason kicked us off as the retrospective facilitator. I haven't been on a project that held retrospectives on a regular basis before (though we've certainly done them at times), so it was interesting to see the very structured approach Relevance takes. As a brief outline, the team (and customers) began by outlining their expectations and hopes for the retrospective, followed by ratings of how several areas of the project (communication, ROI, building the right thing, etc.) were going, and finally a review and a set of action items with due dates attached. The team members - Chris, Jason, Don Mullen, and Michael Parenteau - were all excellent at interacting with the customers. I like to think that I'm pretty good at that kind of interaction, but there's a lot I picked up in a short time on that conference call. I heard a lot of rephrasing the customer's concerns to verify that the team always had the correct interpretation, and I'm sure the customer came away feeling like their needs were really being addressed, especially with the clear action items to address any issues that came up. Michael's design work on this project, incidentally, is pretty killer and got rave reviews from both of the client representatives.
In yesterday's installment, I neglected to mention the project management tool the teams use, Mingle. It's a very nice tool, which looks to have a ton of features, but (unlike some other many-featured products I've used) manages to keep the interface very clean and simple. I'm not sure in what situations I'd feel compelled to switch to it over something nice (and free) like Pivotal Tracker or Agile Zen, but it is an impressive piece of software that I'm glad to have had a chance to take a look at.
So... time zones. Every time I deal with them it's a mind-bending struggle to keep all the concerns in their proper place, and today was no exception. We had our Time.zone in Rails set to UTC, but were still getting some EST times. Well, it turns out things like Date.today.beginning_of_day don't respect that setting and use whatever the default system time zone is. After about an hour of investigations and pondering, we eventually decided to replace most uses of Date with the Rails TimeWithZone object, allowing some mildly unsavory naming with the understanding that the decision is going to need to be revisited to account for various user time zones anyway. It seems to me that this is a universal problem for apps that might be used in different time zones. Chris suggested that this might add to the often-quoted-but-rarely-sourced list of hard problems in computer science: cache invalidation and naming* (and off-by-one errors?). So henceforth, time zones are in there too. That's right, you heard it here first: it's three (or four, depending on if you're telling the off-by-one joke) hard problems: cache invalidation, naming, and time zones.
After work Aaron Bedra, Alex Warr, Stuart Halloway, and Stuart Sierra introduced me to my first draft-style game of Magic the Gathering. Yes, that's right, I spent the evening with three of the Clojure/core guys and learned a ton... about Magic. It was fun - I got a TON of help from everybody, especially Alex, and with a lot of help, I actually won a few rounds. We played duels, best-of-3, and I went 2-2 overall in games. And by "I", I mostly mean "the people who told me what I should put down." I heard a rumor on one end of the table that Relevance prefers to hire Magic players over non-players as programmers**, so potential applicants should take note. I don't know that I'll run out and buy a deck, but it's always fun to learn a new game, especially when the cards are named things like "Lord of Shatterskull Pass".
Sounds like I'll be sitting in with Alan Dipert's team tomorrow on some Clojure work, which I'm very much looking forward to.
* Some people on the Internet say the credit belongs to Phil Karlton, so it must be true.
** This sounds made up, and may be.
[UPDATE: fixed retrospective timing description based on Jason's comments below]
Craftsman Swap at Relevance - Day 1
by: colin | July 7th, 2010 | 2 comments »
I'm both honored and humbled to represent 8th Light on the latest Craftsmanship Swap, with Relevance in Durham, NC. I'd first heard about Relevance through Stuart Halloway's excellent book Programming Clojure, and their reputation precedes them in the Clojure community, as well as in the Ruby/Rails world. Jason Rudolph had me come in a few minutes early this morning to give me a quick introduction to the company before their company-wide standup, where the whole company gathered and very efficiently went through the interesting goings-on of the day. The plan for now is for me to spend a couple days working in Ruby/Rails, and a couple on Clojure - I'm excited about both.
![]()
I paired up with Chris Redinger to work on a Rails project that's just a few weeks old, but already doing some pretty cool stuff. There's a pretty slick graphing library on the project called Highcharts, which apparently even works on IE6 (gasp!). We did some refactoring, which was a pleasure - Chris has a great eye (nose?) for code smells and writing excellent code (as well as customer relationships), and I often felt like we were on the same wavelength as we made improvements. We ran into a strange issue with the RSpec version we were on: models seem to be loaded twice during our spec runs, which gave us annoying errors about redefining constants (when we were most definitely only defining them once). It turned out the right place for the (non-ActiveRecord) models was actually under lib/ in this case, and that cleared up our problem. Chris thought this may have already been fixed in the latest RSpec 2 beta, but unfortunately we can't upgrade because newer versions are only compatible with Rails 3, which we're not using on this project.
We also got some feature work done, of course. The code is a pleasure to work in - clean, plenty of tests, and several Thundercats references, which is perhaps most important of all. In all seriousness, it was pretty easy to jump in and contribute, and that's been due in large part to the high quality of the code. Bundler, by the way, seems awesome. I've heard mixed reviews, but my experience installing gems today was such a breeze that I'm definitely going to try to use it on my next Rails project. I also sometimes forget how freeing it is to work on a project using Git - all of our greenfield projects use it, but I've gotten used to being on Subversion projects, where making a branch is a big production. Chris uses feature branches regularly, and they seem to work pretty well.
The environment at Relevance is really nice - a big open space with lots of pairing stations, drinks and snacks, and even a keg of Aaron Bedra's delicious home-brewed Belgian-style wheat beer on tap. We had a great lunch of Thai food and very techy conversation - Node.js, Clojure, and EventMachine all got some playing time, and everyone agreed that Aquamacs was very pretty. Wait, maybe that last part went differently... After work, Aaron, his fiancee, Stuart Sierra, Jared Pace and I grabbed some Mexican food (after what was apparently a second failed attempt to eat at a place that serves something called a "Defibralator" - don't blame me, that's how they spell it on the online menu).
Chris and I ended the day working on tracking down a data issue, which we hadn't completely solved by the end of the day, but we narrowed the possible culprits down significantly, and I'm sure it'll be obvious to us in the morning. Looking forward to tomorrow's adventures!
JavaScriptness.prototype = new Class(); From Classical to Prototypal
by: justin | July 6th, 2010 | 0 comments »
It has gotten a bad rap because most people that use it don't look for its brighter side. Instead they will often look online for some code to copy paste, or they will hack something together using tiny snippets and in-lines to get a drop down menu.
It is also a very conflicted language. By nature, JavaScript is a Prototypal language where nearly everything is an Object and there are no classes. It is also somewhat Functional since all the functions are First Class Functions. They are just more objects that can be passed into and returned from other functions.
The Classical Form
Lets take a look at a basic Classical implementation of a Square using JavaScript:function Square (side) { this.side = side; } Square.prototype.area = function () { return this.side * this.side; }; Square.prototype.perimeter = function () { return this.side * 4; }; var mySquare = new Square (5);You will notice that JavaScript even has a new key word in an attempt to match a Classical implementation. The function Square () defines a class with a side attribute. It also has two instance methods, area and perimeter. We can then create mySquare in almost the same way we might do it in Java. This is JavaScript though, and the new works differently in JS. It creates a new, empty object and then calls the Square() function (or the constructor) passing the empty object into this . The constructor then populates that object with the specified behavior before returning it. This is particularly scary, because if you forget to put new in front of the constructor, this will refer to the Global Object, as will mySquare (meaning any further changes made to mySquare would also be on the Square 'class'). This is why, if you want to use JS in the Classical way, you should always capitalize the first letter of a constructor.
Ok, so we have our Square, but say we want to create a square that holds a X or an O. Well, we would want to inherit the properties of our current Square 'Class' and then add to them. We might do something like this:
function ContainerSquare (side, contents) { this.superclass(side); this.contents = contents; } ContainerSquare.prototype = new Square(); ContainerSquare.prototype.superclass = Square; ContainerSquare.prototype.constructor = ContainerSquare; ContainerSquare.prototype.getContents = function () { return this.contents; }; var myContainer = new ContainerSquare(6, "X");We create a new 'Class' for the ContainerSquare which uses the Square's constructor to define the side attribute, along with the two instance methods. We then define our new contents attribute, along with an accessor method to go with it.
The ContainerSquare .prototype = new Square(); line sets up a Prototypal inheritance structure so that a ContainerSquare object will be linked to the proper prototype chain.
The prototype chain is the hierarchy of objects that a method or attribute call will traverse until it finds what it is looking for. In other words, when I call myContainer.size(), JavaScript will first check to see if the myContainer object has that function. If not, it will proceed to check the object's prototype, which is the ContainerSquare. Since ContainerSquare doesn't have the function, next in line is ContainerSquare's prototype, which is just Square. Square does in fact have a size() function, and since javascript will use the first function it finds, it will use Square's size() function.
Thus, by setting ContainerSquare's prototype to Square, we inherit any of the attributes or methods of Square.
Although this all works, and we have successfully mashed a Prototypal language into a Classical scheme, we should try this in the way JavaScript wants to be used.
The Prototypal Form
We can start with the Square. There are few pretty simple ways to achieve the same functionality using regular objects and their prototypes, and we will look at two of them. The first will create a square object that we can use. Then if we need more squares, we can make a copy of that object using its prototype. The second will create a squareMaker function, which can then be used to pop out new squares.var firstSquare = { side: 5, area: function () { return this.side * this.side; }, perimeter: function () { return this.side * 4; } };Here, we already have a new and usable square at our disposal. We don't need to call a constructor and define any types. We can just take an object and mold it into the form we want.
Say we want another square though. We can't just write something like var secondSquare = firstSquare; because JS passes objects by reference, and thus the second square would just point to the first square. What we can do, and this is a technique developed by Douglas Crockford, is make a copy of our object by calling a new constructor with a prototype that points to our object. This new contructor creates a new empty object and assigns the values of our old object to the new empty object. You can do this yourself, or you can use Crockford's technique as follows:
if (typeof Object.beget !== 'function') { Object.beget = function (o) { var F = function () {}; F.prototype = o; return new F(); } } var secondSquare = Object.beget(firstSquare); secondSquare.side = 6;You can see that we are actually defining an on the fly constructor F, using our object 'o' to define F's prototype (where 'o' is firstSquare). Then we create a new object using that constructor. This will give us a new copy of our object, with all its attributes and functions. If we now called secondSquare.area(); we would get 36.
If you wanted to then make a ContainerSquare, you could simply add a contents attribute to the second square, and then make copies of the secondSquare if you need more Containers. Keep in mind that since firstSquare is the prototype of secondSquare, if you were to add a contents attribute to firstSquare, you would then have that attribute on secondSquare; however, adding attributes to the secondSquare does not place them on the firstSquare.
Spawn More Protolords
The other way to get squares would be to make a squareMaker function. This function will return a new object with whatever attributes you define. I am also going to show you some closure so that the attributes are private, and only accessible through accessor methods.var squareMaker = function(side) { return { getSide: function() { return side; }, area: function () { return side * side; }, perimeter: function () { return side * 4; } }; }; var anotherSquare = squareMaker(5);You will notice that the return value of the squareMaker is almost exactly like how we defined our firstSquare object. We are just returning the definition of a square, and thats quite awesome. Another thing you will notice is the bit of closure. We pass a value into the squareMaker, but it isn't stored anywhere. It is held in the scope of the squareMaker function, allowing those internal methods to use it, but hiding it from the outside (unlike the side attribute defined in the firstSquare). This sort of closure is another wicked awesome tool you can use in JS. In a way, this use of closure is like defining private variables to a class.
To get the Container functionality we create a containerMaker using the squareMaker, and some more closure, to make a new square object. We then dynamically add a getContents method to provide access to our private contents attribute.
var containerMaker = function(side, contents) { var container = squareMaker(side); container.getContents = function () { return contents; }; return container; }; var anotherContainer = containerMaker(6, "O");
Conclusion
So we have now seen two ways to use some of the better parts of JavaScript to get the same functionality that we could get using the Classical scheme. We can also see some advantages in using JS in its natural form like: getting some closure (which can be exceedingly powerful), very dynamic objects ready to change in anyway you can think of, quickly defined objects which can be used and multiplied, and no need to predefine types. Pretty sweet right?I will admit one slight inefficiency with the two solutions I showed you (although there are ways around this). Using the squareMaker, or making copies of the objects will make full copies, including the function objects defined inside. If you use the Classical scheme I showed, you are defining functions on the prototype rather than the object itself, thus there will only be one copy of the function. You can, of course, do something similar in the JS scheme, but the optimization doesn't count for all that much in most cases (unless you are doing mobile development where you want to save everything you can!).
JavaScript isn't a Classical language, but instead a Prototypal language that is powerful enough to mimic a Classical language without breaking a sweat. There is much to be gained by recognizing this fact and changing your mindset to work with it. Trying to fit a square into a circular hole will just get you stuck. All languages are unique with a variety of their own advantages, and as good developers we should recognize these differences and reap all the benefits they have to offer.
Craftsman Swap Day 4 - Oh how fast a week goes, especially when it's short.
by: eric | June 24th, 2010 | 1 comments »
Did you know that Midsummer is arguably the biggest holiday in Sweden? And did you know it’s celebrated tomorrow? And that there’s no work tomorrow? Neither did I, and neither did CJ otherwise he probably would have tried to schedule this for a different week. Originally it was scheduled for the middle of July, when I am unavailable because of the imminent birth of my son. In fact I’m not really able to do a craftsman swap from oh..now…until the end of this year when the new baby might be old enough that I could leave my incredibly understanding wife at home alone with 5 children with a clean conscience. So really I have to thank CJ for forgetting a national holiday so that I could have this fantastic experience.
In celebration of midsummers we had what we Americans call a Pot Luck and what the Swedes call a “llAHHRdcdfagageeees”. I really don’t have the language down, but I’m sure that’s pretty close. We got to eat out on the veranda and I ate some pickled herring! Despite being warned I actually quite liked it and the view of the “lipstick” building is fantastic. Plus the eLabs folk (and @keavy - in yellow) are great people so you’d be pressed to beat the company. I’ll have a full post-mortem tomorrow ( as well as a special bonus post I’ve been sitting on for a few weeks) so let me just take this opportunity to thank 8th Light and Elabls for a great week. I’m honored to have been chosen for such a trip, and I hope I was able to give back a little of what I was given.
Now hopefully tomorrow I survive the insane bicyclists.
International Craftsman Swap Day 3
by: eric | June 23rd, 2010 | 0 comments »
Got Ruby?
After attending tonights got:ruby I became obsessed with and started installing rvm. It worked swimmingly, and I’m looking forward to getting my development machine off of the embarrassingly low version of Ruby and experimenting on the latest versions without (unintentionally) screwing up my production environment. Indeed after this week I’ve got a lot to google, lookup, and research. I’ve decided I have got to get good at JQuery - probably using it on a small Rails 3 project in the near future - and learned that Jasmine has it all over ScrewUnit. This may mess up my Haskell plans - not that I’ve ever messed that up before. After that we played a lot of ping-pong, then I decided to clean up my hard drive, because it was really time. Then I realized if I’m gonna do this project as Rails3, I better make sure I can deploy it on dreamhost with bundler.
If this sounds like procrastinating it’s cause it is. I also checked email, read Anders’ blog on the elabs.se site, and watched some of Germany beating Ghana. None of this is writing the blog post and that’s because today’s blog post is going to be hard. Let’s get this out of the way first. Today was another great day at ELabs. With my Jet Lag finally kicked I really was able to contribute, using a couple ideas we’ve had before on 8th Light projects to get some cool work done on the project I’ve been working on this week. I even wrestled for the keyboard a bit (although they have two keyboards - so it was lonely, I wrestled with Pixie) then we topped it all off a cool Ruby user group meeting. The meeting was last minute, so they had lightning talks where CJ talked about Bundler and rvm, Jonas talked about a Javascript testing plugin he’s working on, we puzzled over a problem one of the other developers was having and even looked at Omni Graffle. Now that I’m awake the ELabs guys had to suffer my jokes like the 8th Light guys do all the time. Now they know why they sent me out of the country.
What’s been really nagging at me has to do with the way that the ELabs boys work. See they are what Brian Marick would call “classicist” TDDers - they essentially never use mocks. I on the other hand generally mock out a lot. What Jonas said to me was, and I’m going from memory here, “I’d rather the tests run slow than be right.” Of course taken as stated, this is a truism. Nobody is voting for slow tests, although I might argue that the tests that verify correctness are often different than unit tests, and that unit tests are verifying a different thing. Aside from speed mocks provide value in designing apis by letting you design it with a client using it, before the object itself exists, and in thinking of systems as objects passing around messages you can really focus on their interactions instead of the implementation details. Mocks lead to a cleaner design all told….except….
Except I usually stub out things for speed. Objects I’m stubbing are webservices, database objects, file access, etc. And in the best cases the benefit I get is speed, and in the worst cases I get a tangled mess of mocks where my code and tests are coupled, but nothing necessarily works. I’ve completely traded speed for correctness. Why is that? Why am I not getting all the purported benefits of mocking.
In a related note on the way here I started reading “growing object oriented software, guided by tests” by Steve Freeman and Nat Pryce. In a throw away comment they say, “Never mock out third party API’s, write thin classes that wrap those with integration tests, and mock out your objects interaction with those classes.” Now maybe you think you haven’t done this, but let me give you some typical examples of mocks:
- IO.stub!(:read).and_return(mock_file)
- ActiveRecord.should_receive(:find).with(1)
Well look at that - those are two third party API’s aren’t they? And they are often mocked out everywhere! Trading speed for correctness again. “Okay fancy boy”, you’re saying - and really why are you calling me that, “Then we shouldn’t use mocks. Problem solved.” Not so fast. Have you ever had the problem where you are testing that an object gets saved and you do this:
object.should_receive(:update_attributes).with({:my => value})
but then you think, “Gosh I really don’t care how they save the values, I just care that it gets saved.” Right now you have to call update_attributes to make this pass, but you could call update_attribute, or set the object and save!, or hell use SQL although you shouldn’t. This makes for a crappy test - one you’re likely to break then fix later instead of changing in the deliberate process of TDD. What if instead you did this:
object.should_receive(:update_my_value_to).with(value)
Of course the other things are still true - assuming it’s an active record object, but maybe it’s not. Maybe it’s a wrapper around it, or maybe it’s datamapper object, I don’t really don’t care. I’ve gone ahead and mocked this call because that’s the call I really want to see - and somewhere else I’ve test driven that call against the database. Now let’s imagine you’ve got more complicated scenarios. Ever done this?
object.should_receive(:get_this).and_return(object2)
object2.should_receive(:is_true?).and_return(false)
This is a simple example - but I’m sure you’ve seen worse. The problem is again that you really need one method, maybe two, but you probably figured out in your head the algorithm beforehand, then test drove it. Maybe you know if object2 was true you needed to set unrelated object3’s flag - so you started writing those tests. Let’s look at that rule again though - don’t mock a third party API. Well what defines a third party API? Is it a third party if another company wrote it? How about the same company - but on a different project? Or the same project but a long time ago? Or YOU six weeks ago and you forgot it. Isn’t it a third party API again? What’s the difference? Should you then mock out objectnew - and test drive it with real objects? Because it’s pretty clear the API you want doesn’t exist yet, and that’s the crux of my long wrambling argument that I’ll probably better express and codify when it’s not late and I’m not tired:
Stop mocking the API you already have - mock the API you need
And then if by chance it matches the API you already have - by all means just substitute the real object in. But write the implementation with mocks first - without using any real API unless it matches coincidentally. Pretend the object doesn’t exist yet, and then mock. And maybe then you’ll get what you’re looking for.
Eh - or maybe I should go write some Javascript.
International Craftsman Swap Day 2
by: eric | June 22nd, 2010 | 2 comments »
CJ on his way to work
Before I get into some of the details of day #2 at eLabs, let me dispell a few myths about Sweden that my American readers may still believe.
Swedes buy all their furniture at IKEA
This is of course a silly idea, caused by the prominence of the IKEA brand in the United States. In fact IKEA accounts for a mere 83% of the furniture market here in Sweden, with the rest of the furniture being bought at independent specialty stores such as Wal-Mart.
Ski jumping is the primary form of transportation
Swedes have a wide variety of commuting options available to them. By far the most popular is to bike to work at speeds of upwards of 300 miles an hour, using the bodies of pedestrians to slow your bike down when you arrive at your office. The speed is necessary to outrun the second most popular form of transportation, the electric trams. The trams take a convenient route to your office, assuming they don’t fly off the tracks. Which they do, often. Ski jumping is naturally third, keeping the commuter safely above the trams and bikes, until they crash down on the brick sidewalks. Finally I believe two gentleman own cars, but they rarely drive them because they are afraid.
The Swedish Chef is President
Don’t be an idiot. Sweden has a Prime Minister, not a President.
With that out of the way, we can properly concentrate on my time at eLabs. I promised yesterday I’d document stand-ups the eLabs way, and I’m glad I did because today I got to see first-hand day 2. Standups at eLabs go something like this - everybody stands up from all projects. There’s about 8 employees, so it’s sizeable but not gigantic. On Mondays everybody gives an update for the project they are on. The rest of the week everybody just pipes up if they have a problem. What I find interesting is there is no customer involvement - these stand ups are for team members to team members - and the multiple project nature of the meetings doesn’t seem to slow them down at all.
From there they retire to pairing stations and it’s a lot quieter than the 8th Light office - especially since I’m not at the 8th Light office making noise. They have offices where the pairs work, which I find both good and bad. At 8th Light on fridays we have frequent problems where one pair is on a conference call and another is animatedly discussing a problem, so that would be helpful, on the other hand there’s definitely an energy to everybody in the same room that isn’t there when offices have doors. It’s an interesting hybrid approach, and I could get used to it.
On a personal level I wasn’t 100% today. I woke up at 4:45, apparently Jet Lagged, and learned that Gothenburg doesn’t have early morning coffee shops for iPhone hacking. After walking around the rather cold town for over an hour I finally found one at 7:30, and thought I was fine. At two I crashed, and was completely losing concentration, practically falling asleep in my chair. Fortunately they have ping pong and after a couple quick games I was back to my normal self, and really wrote some code. I really want to get better at JQuery and ScrewUnit, because right now I’m still coding too much Javascript by luck.
Afterwards Jonas was kind enough to join me for dinner and we had a lively conversation about mocks and when (or when to not) use them, as well as the way eLabs does their Rails testing. I’m too tired to properly write my thoughts now, but it’s definitely gonna be a blog post tomorrow. It was a very nice dinner and I’m glad Jonas joined me. Now if you’ll excuse me I have to dodge the death trams on my way back to Andres Apartment.
International Craftsman Swap Day 1
by: eric | June 21st, 2010 | 0 comments »
Today was day one of my Craftsmanswap with eLabs developer Anders Tornqvist, and so far they have treated me with the hospitality and graciousness I expected. Largely they’ve been led by my pair, pictured at right. This is Pixie, who’s been working in the same room as me all day, and when she hasn’t been barking at me she’s been growling. It’s been a tad….terrifying? Especially when the blood is dripping from her teeth, and she can leap so high!
Actually poor Pixie had a rough time of it last night, and it apparently led to her being out of sorts. She eventually got along with me just fine, and I was able to have a productive day pairing with Ingemar. I hope I was helpful, as I’m trying to spend most of my time listening. I hate being the guy who shows up on a project and immediately tells people how to do stuff, plus Ingemar had a grumpy boxer/pit-bull mix next to him so I wasn’t gonna ruffle feathers. The problem with that approach is that you can end up failing to contribute by being too passive, but I think I did okay today. Tomorrow I’ll probably be a little more vocal, and moreso the next day. You know, just in time for me to leave.
The highlight of our day, for me anyway, was implementing drag and drop in JQuery. I’ve never done it before - I think I’ve done it in Prototype but it’s been a while - and it’s amazing what a breeze it was. I’m going to have to find an excuse to use JQuery more, and I’ll probably try and find out some info on ScrewUnit. Of course on the plane I started reading “Growing Object Oriented Software, Guided by Tests” and a new iPhone book, so I’m nothing if not capable of overbooking myself. Speaking of which GOOS looks like a real winner, if you didn’t already know.
In addition to some JQuery at one point or another Ingemar touched on a gem or idiom I wasn’t familiar with, often with me hurriedly scribbling notes probably without him realizing it. The list of gems from today alone was:
- formtastic
- hitch
- machinist
- launchy
- carrierwave
Hitch was seriously cool, allowing us to push git changes as a pair. Formtastic is an interesting form builder, and although we had some struggles with it today Ingemar assures me it’s awesome. It did have a nice DSL syntax. We used machinist’s blueprint feature for building factory objects, kinda like factory girl. I admit I like the concise syntax, but I wonder if we should be making it easier to create lots of objects in setup for a test. Launchy cleanly launched the browser when testing at a given point, and finally I’m excited to use carrierwave for file uploads tomorrow.
I have more notes, particularly regarding the different way that eLabs does standups, but I fear this blog post has become disjointed and a tad dull, so I shall leave you until tomorrow.
MMEmail: My First Clojure Open Source Contribution
by: micah | April 21st, 2010 | 0 comments »
While working on website for my sister, I was perturbed that there were no libraries on Clojars for sending email. I was using Leiningen which will download and include all your dependancies for you (so sweet!). Yet, with the library I found, I had to manually download all the required jars. Call me lazy but being forced to manually download dependancies seems like cruel and unusual punishment these days.
So I solved the problem:
MMEmail
Simple Clojure library for sending email, with just one jar!
Installation
Leiningan:
- (defproject your-project "0.0.0"
- :dependencies [[mmemail "1.0.0"]]
Jar File
…can be downloaded at http://clojars.org/repo/mmemail/mmemail/1.0.0/mmemail-1.0.0.jar
Usage:
Include the library
- (use 'mmemail.core)
The Easy Way
mmemail.core is the only include you need. It contains only 2 methods, the fist being send-email.
It takes a map that includes all the configuration and email parameters. That’s it.
- (send-email {:host "smtp.gmail.com"
- :port 465
- :ssl true
- :user "road@gmail.com"
- :password "runner"
- :to "joe@acme.com"
- :subject "Greetings"
- :body "Meep Meep!"})
Most of the parameters are required, but based on your server configuration you might get away without these:
- :ssl
- :password
- :subject
It also accepts the following optional parameters:
- :from (defaults to :user)
- :cc
- :bcc
The recipient parameters (:to, :cc, :bcc) may be a string, for one recipient, or a sequence of strings, for multiple recipients.
The Convenient Way
It can be annoying to pass such a big map into the function, and typically you’ll want to get all the server configuration
out of the way. This is where the second function of mmemail.core (create-mailer) comes into play.
- (def my_mailer (create-mailer {:host "smtp.gmail.com"
- :port 465
- :ssl true
- :user "road@gmail.com"
- :password "runner"}))
create-mailer will return a new function with all the configuration baked in. So in the future, you can send email
like so:
- (my_mailer {:to "joe@acme.com"
- :subject "Greetings"
- :body "Meep Meep!"})
The create-mailer accepts email parameters that will be used as defaults when the generated function is called.
- (def my_mailer (create-mailer {:subject "Greetings"
- :body "Meep Meep!"
- :host "smtp.gmail.com"
- :port 465
- :ssl true
- :user "road@gmail.com"
- :password "runner"}))
- (my_mailer {:to "joe@acme.com"})
License
Copyright 2010 Micah Martin. All Rights Reserved. MMEmail and all included source files are distributed under terms of the GNU LGPL.
TDD in education, they're doing it wrong
by: eric | April 9th, 2010 | 4 comments »
This blog post originally appeared on a blog I maintain for my current game development class. Generally speaking my posts over there are pretty specific to the classes I’m taking, and aren’t appropriate for this blog. Recently however my instructor, who is an extremely smart and accomplished developer in the game development industry, described a common misconception about TDD that prompted me to rant on that blog. Since the subject is TDD I’m placing it here, edited to make more sense.
Recently in class our professor said something like this, “TDD says you should only write the simplest code that can possibly pass the test, and that leads to spaghetti code with a lof conditional logic.” Sadly this left me shaking my head. I’ve been doing TDD every single day for the last 3 years professionally, and intermittently for 2 years before that, and I can say for certain that TDD never caused me to write spaghetti code. Of course I’ve written spaghetti code, including some of the code I TDD’d for the previous class (I’m not real happy with my memory system) but that wasn’t caused by TDD. The crux of the professor’s argument seems to come from a mistaken understanding of TDD. He seems to have TDD as a three step process:
- Write the test
- Write the smallest amount of code to make the test pass
- Repeat
Unfortunately it’s missing a crucial step – refactor! Yes we initially write the simplest code that can possibly pass, but we don’t leave it that way. We write that simple code so we can refactor with a green bar, something that unfortunately my professor doesn’t understand.
When I write the minimal amount of code refactoring becomes easier, because I have a suite of passing tests. In school students and teachers throw around the term refactoring a lot, but are usually unaware that when Martin Fowler wrote the book on Refactoring, defining it for the software development community, he required unit tests. You can’t guarantee your behavior did not change unless you have tests around the behavior, which is why I hear so many students say things like “I’m almost done refactoring but the code doesn’t build yet.” Refactoring is meant to be small steps, in a definite process, so that at the end of each refactoring (such as extract method) I have the same behavior as before, but better code. Most people who refactor don’t have tests, take huge steps and eventually end up hacking and slashing something back together that is close to (but not the same) as their original behavior. That’s not refactoring, that’s hacking - and most students clearly don’t know the difference.
At this point the blog went into a description of how you’re supposed to do TDD, but if you’re reading this blog you probably already know how to do that. The point of moving this here is to point out that TDD is making inroads at the university level, but it has a long way to go. Those doing TDD are a distinct minority, those that are are doing it wrong, and they’re getting bad information. Furthermore let’s remember these are smart people. The professor for my class is frakking brilliant, and the students are amongst the best in the university, and yet in spite of that when they start their first job they’ll do so without writing unit tests. The good news is that smart people are trying out TDD, in an industry (games) that is notoriously slow to adopt software development methodologies, so we are winning. It’s just taking longer than we thought.
JRuby Helps Us Craft Quality Software
by: doug | April 6th, 2010 | 0 comments »
"It's kind of a Frankenstein." We've used this phrase more than a few times to describe the architecture and technology used to design a product that was recently released after almost a year of development by the software craftsmen of 8th Light. The product is a multi-platform, PC management application for library computer labs written primarily in Ruby, run on the JVM with JRuby. The user interface is written in erb-templated HTML and Javascript, and is displayed in an embedded web browser. JNA (Java Native Access) is used to call operating system specific functions that enable an insane amount of control over the desktop. The various JRuby components communicate with each other over DRb.
But the most amazing thing about this project is that we are using JRuby to deliver a portable, rich desktop app using the best of web technologies. We chose JRuby because it increased portability and performance and reduced development time.
At 8th Light we had tried before to build products for our clients using Ruby, but we always hit a dead end when it came to deployment. For our clients who provide software products instead of software services, the applications must install easily and completely on the end customers machines while still protecting the intellectual property of our client. We tried very hard to make technologies like RubyScript2exe work, but in the end a packing and unpacking solution was too slow and still left our client's source code open for the reading on the installed computer.
As we began the project about a year ago, we discovered that JRuby had reached the point where it could be a viable platform for us to be able to build products that our client's customers could easily deploy in their own environments. Our solution was to bundle all of our JRuby code into jars after it had been encrypted. By patching into the JRuby load service we were able to decrypt the source on the fly and leave the code bundled and encrypted on the disk at all times.
JRuby allows us dirt simple access to Java's huge collection of libraries, along with plenty of custom Java libraries our client had already written. We also go back the other way, implementing Java interfaces in JRuby and using those objects in Java code. This fluidity allows us to always pick the best tool for the job. Early in the project, this also helped to sell the technology to our client. They were wary of a new language that none of their in-house developers knew, but we were able to reassure them that they could easily drop back into Java at any time.
At one point in the project, the client's development team jumped on the project to add a new configuration interface to the server side of the application. The team wanted to use a set of Java tools that they were already familiar with, but needed to make calls into the JRuby side of the application to get and set the configuration values. We built a new Java interface for them and implemented it in JRuby—then from our Ruby initialization code, called a static Java function back on the Main class, passing in the configuration object. This allowed the client's team to initialize their java objects with the instance of our JRuby class that we had provided.
- //The Java Interface
- public interface ConfigurationStore
- {
- void put(Map<string> pairs);
- void put(String key, String value);
- String get(String name);
- }
- #The Ruby Implementation
- class ConfigurationStore
- include Java::package.ConfigurationStore
- def get(key)
- .....
- end
- # Notice how we were able to implement the function
- # overloading present in the interface by
- # using a variable arguments in one ruby method.
- def put(*args)
- if args.size == 2
- ....
- elsif args.size == 1
- .....
- else
- raise ArgumentError.new("put() takes a Hash
- (or a Java Map) or a key and value pair")
- end
- end
- end
We wanted to be extra sure that the class we were writting in Ruby would work from Java before we handed it over, so in addition to the rspecs we wrote to test the Ruby class, we also wanted to write a JUnit Test. Normally, we inject a JRuby object into Java by calling a Java function from a JRuby method and passing along the JRuby object that is to be used. In this case we wanted to actually instantiate the Ruby object in the setup of a JUnit test. We dug around in the JRuby APIs and were able to leverage the fact that the RubyRuntimeAdapter returns the last thing evaluated. We were able to use the toJava() method on the IRubyObject returned from eval and cast the result into the interface class. Then we were free to write JUnit tests exercising the functionality of the JRuby class.
- // instantiating a Ruby object in Java
- RubyInstanceConfig config = new RubyInstanceConfig();
- Ruby runtime = JavaEmbedUtils.initialize(new ArrayList(), config);
- RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
- IRubyObject result = evaler.eval(runtime, "require 'configuration_store';" +
- "config_store = ConfigurationStore.new");
- store = (ConfigurationStore) result.toJava(ConfigurationStore.class);
We do a lot of things at 8th Light to ensure that we can deliver very high quality code to our clients as fast as is responsible. One of the most important things we do is work in highly productive languages. JRuby enables us to write most of the complicated business logic of our application in the highly productive Ruby language and still provide a viable deployment scheme that allows our clients to successfully sell their product to their customers.
This article appears in the April 6th, 2010 Engine Yard Newsletter
Makin' somthin'
by: doug | March 15th, 2010 | 4 comments »

Today (March 15th, 2010) is my Grandfather's 90th birthday. We celebrated with him this weekend in Pike County, IL.
I spent quite a bit a time growing up with Grandpa. On many weekends and for entire weeks of the summer, I'd join him on his farm in Perry, IL. By the time I came a long, grandpa had mostly retired. He rented out his farmland, but still kept some cows around, mostly so that he'd have something to feed every morning.
Grandpa dedicated his retirement to a variety of woodworking pursuits. He made scale models of local buildings, wooden carousels, clocks, toys, banks, and even the occasional joke piece. One of my favorites was a small base with a US quarter mounted to it. A tiny dowel rod mallet slid into a hole in the base. Hand stenciled on the base was the title of the piece: "Quarter Pounder." He refinished furniture, built us an elevated playhouse, and built a scale model of our house. He'd see plans for something in a magazine or pick something up on a trip, and go to work on it in his workshop. I would tag along for much of this activity.
When I was 7 or so, Grandpa did something that I think more than anything, shaped what I was to become and do in the future. He built me my own workbench. It was kid height with kid sized tools. I know that now you can buy playschool workbenches and tools for kids. But the tools on my workbench were no plastic toys from China. They were real: a real saw that was really sharp, a vise that could crush things, a hammer that could actually drive nails. He set it up in his workshop down at the end of the big workbench.
So the story goes like this: (This is how grandpa tells it anyway.) He had lost track of me in the workshop. He had gotten involved in something and I had gone quiet. When he found me, I was hunch over the blue workbench furiously working. Grandpa asked me what I was doing, and I responded "makin' somthin'" I guess grandpa got a real kick out of my response because it's one of those family stories that has been told over and over. Here is what I remember. I really didn't know what I was making. I just knew that I was consumed by the desire to make something. So I was cutting pieces of wood and nailing them together all because I wanted to make. It was part emulation. I admired Grandpa and wanted to be like him. But it was more that he had infected me with this bug. I had caught it. I wanted to be a maker.
I studied engineering in college, but ended up gravitating towards software. Fairly recently I've discovered just why it is that software appeals so much to me. It is because software is making. In engineering, we'd design something and send it out somewhere to be made, but in software, everyday I get to step into a the world of the maker and just build stuff. Every time I open my laptop, I'm 7 years old again and hunched over my workbench consumed by the desire to make. The tools are different, the raw materials are different, the end product is different, but that feeling and that drive to make is just the same.
Thank you, Grandpa, for putting tools in my hands and showing me how to use them, and letting me make something. Happy 90th!
The Hammock
by: doug | March 12th, 2010 | 0 comments »
The Hammock

Our secret is out. A recently published photo revealed it hanging lazily in the corner of our office: a hammock.
Why would an office of software development professionals have a hammock in it?
Well the short answer is that it's always been a dream of 8th Light co-founder Micah Martin to have a hammock in the office. For me, it's an indispensable part of my daily rhythm.
The Reboot
I remember when I started my first internship while in college just how hard it was to stay alert for an 8 hour day. I was reminded of this this summer when I watched the head of one of our interns start to bob and shake at around 2:00 every afternoon. My solution early in my career was caffeine. That sweet green bubbly nectar of the awake dropped out of the vending machine into my hand each afternoon.
I've since given up caffeine, and have learned to get adequate sleep. But there are still some afternoons when everything catches up with me and I just stop making progress. Maybe a particular problem just won't budge, or I have to read some dry documentation. Whatever it is, my brain just shuts down. I sometimes describe it as a fog. It's like that feeling just before getting a headache.
Enter the hammock. Instead of just pushing through and making no progress for an hour or more, I go lie down in the hammock. I lie there and focus on my breathing until I just barely fall asleep. When that first dream sequence starts to roll, I get up, shake out the weariness and start back to work more focused and more alert. I like to call it my personal reboot. Like a sluggish Windows box, I'll I need is to shut all the way down and then turn back on again.
I've heard a story about how Thomas Edison would do a similar thing to refocus himself when he was working. He didn't have a hammock, but he would sit in a comfortable chair with a pile of ball bearings in his hand. When he would reach that just barley asleep state, his hand would drop, the bearings would fall and wake him back up.
Step Back, Go Around
The hammock to me is also a reminder to slow down. As Bob Martin's popular mantra goes "The only way to go fast is to go well." It is also an aid in stepping back from a problem to find that area of minimum resistance. Richard Sennett talks about this idea in "The Craftsman." He says that one of the qualities of a craftsmen is finding the most forgiving approach to a problem. That skill requires stepping into and out of detail on a problem. That is, focussing on the point of tension, but them zooming out to see if going around might be better than going through. A little bit of time in the hammock is great for that. Many times, I've gone to the hammock frustrated with a problem, only to emerge with a completely tangential solution.
It's a Team Thing
Here is what some of the other craftsmen at 8th Light have to say about the hammock.
Short cat naps help reset my brain to keep me thinking clearer throughout a long day.
-- Paul Pagel
I often head there at around 3 (which is coffee time at the client office). In addition when I'm stuck on something I'll try and clear my head in the hammock, when juggling doesn't work.
-- Eric Smith
After a lunch that was a little too big. A 10 minute hammock-nap gets me back on my feet. In moments of coding frustration, a quick trip to the hammock helps me relax and clear my mind.
-- Micah Martin
These guys echo my feelings about the hammock and affirm how giving ourselves the permission to lie down in the middle of the day is beneficial not only to our own health, but also the health or our projects. It's one of our practices that helps to keep us delivering great code day after day, week after week, month after month.

Walk and Code
by: doug | February 25th, 2010 | 43 comments »

The Motivation
A few years ago when we were buying furniture for the first 8th Light office I came across a piece called the WalkStation. It was an adjustable height desk with a treadmill underneath. I had just started to get myself into better physical shape, and thought this would be a unique way to change a sedentary job into an active one. The price tag turned out to be way to high ($4500+).
Fast forward to January 30th, 2010. At ORDCamp, Zach Kaplan, founder of Inventables, gave a presentation about Dr. James Levine and the research he's done creating active computer workstations. It turns out that Dr. Levine is the guy behind the WalkStation that I had seen earlier. Zach had thrown together a treadmill and a laptop desk to try out the concept and was raving about the benefits. It was the motivation that I needed to finally get to building my own treadmill desk.
Acquisition
Using Craigslist, I found a treadmill just blocks from my house. It is a ProForm 830QT. Sears sells this brand, and I think this one retailed for around $900. I paid my neighbor $140 for this one.
My next stop was Ikea. Somewhere in the back of my brain I remembered seeing a desk at Ikea that was adjustable on-the-fly. I went searching, but found nothing that could be adjusted without tools and without unloading the desk first. I had done a bit of a web search earlier for adjustable surfaces, but hadn't come across anything in a reasonable price range. I headed downstairs to the "as-is" section of Ikea and snatched a Gallant table, frame, and T-Leg combo for $60. The legs alone cost that much new. The combo had been a display model and we a little bit dinged up, but the price was right.
Construction
My first concept was to build a free standing table that would sit over the top the treadmill. The table I picked up was wide enough, but the Gallant legs maxed out at around 36" and I knew that wouldn't be enough. I began envisioning ways to make the legs longer.
In the meantime I started to take apart the treadmill. I just started unscrewing and unplugging everything I found until I was left with just the touch-panel unit and circuit board in my hand. There was one cable running through a leg of the treadmill that was pretty obviously the main control cable back down to the motor below. There was also an audio cable, a cable running to the hand-grip heart rate monitor, and an extra heart rate cable leading to nothing. After a look at the manual, I discovered that this cable can be connected to an optional sensor for heart rate chest straps. The whole idea of this setup is to walk slowly and keep the heart rate down, so I just yanked out all the heart rate cables and sensors.
With all of the electronics off of the treadmill, it was back to figuring out how to mount the desk. This treadmill has hand grips on either side. I yanked furiously on these for several minutes trying to pull them off to see what was underneath. After consulting the assembly manual, I saw there was nothing holding them on, so I got out a pry bar and went to town. They eventually gave way and revealed the horizontal supports that were to become the foundation of the table mount.
A 2x4 set across the hand grip post put the work surface at just about the right height, so I drilled a hole through the posts and bolted on the 2x4. The Gallant table frame has lots of mounting holes, so after removing the frame from the desktop, I chose two holes and bolted the frame on top of the 2x4.
Things were looking good, but for the two post that would prevent the table top from being installed. At first I thought that I could cut the uprights off. But my dremel cutting wheel and hack saw were no match for the thick posts. Without the right tools or know-how to deal with metal, I resigned myself to notching out the table top to fit around the posts. This operation was a measure twice, start over, measure twice again kind of affair. But with some care, I was able to cut the notches with a drill and a jigsaw. A quick tip here. When you cut through a laminated surface like most Ikea stuff, masking or packing tape on your cut line will prevent the laminate from chipping.
Amazingly, I had measured and cut the notches right and the table top slid in place and the old holes to the frame lined up nicely.
With the table top mounted, it was time to get control of the treadmill back. First the touch-panel and circuit boards needed to be contained. I didn't want to spend more money on a project box, so I started hacking away at the plastic enclosure that I had disassembled earlier. I was able to cut away everything but a box the just enclosed all the pieces and was even left with two screw holes for mounting. The problem was where to mount it. I wanted the controls accessible, but out of the way most of the time. They couldn't interfere with walking or typing.
I settled on a keyboard tray that would mount underneath the desktop. It could slide under most of the time, and then pull out easily to start and stop the treadmill or change the speed. Ikea has a tray for just under $10, so it was back to Ikea for the Summera Pull-out keyboard shelf. With the touch-panel mounted on the keyboard tray, there was just not quite enough slack in the control line to be able to pull the controls out far enough to see the entire display. I took the cover off on the base of the treadmill to investigate the control cable and see if I could create any slack. I was able to free up enough cable so that the tray could come out far enough, but it came at the cost of the treadmill's incline feature. The cable will bind now because of the re-routing when the incline it pushed up.
Results
So it's been about 3 weeks with the treadmill desk. Here are some of the question I've received:
Q: Don't you get tired?
A: Sure, then I sit down for a while.
Q: Isn't it distracting to your work?
A: I'll admit it took a little while to get over the novelty of walking and coding. Once the meta-conversation in my head stopped ("Look at me, I'm on a treadmill, and I'm writing code!") then I think that low level physical activity has actually helped to keep me focused. Walking engages a completely different part of my brain. I compare it to how some people will pace when they are making a decision.
Q: What about pair-programming?
A: Colin and I have been experimenting with pairing on the treadmill. We've integrated it into our normal ping-pong rhythm. The one coding is the one walking. One green-red cycle, and then we switch. It's a little bit hard to stand and look over the walkers shoulder, so we've been using a second laptop sharing the screen of the first. With both laptops on the same network, the point-to-point screen sharing is pretty responsive. We've had the best luck with Skype. A second screen also allows the pair to sit for a while. I'm still imagining how two treadmills could come together for a fully-walking pair station.
Q: How fast do you walk?
A: 1 MPH for the most part. We've done okay at 1.3 - 1.5 too. I can stay pretty stable even up to 2.0, but I start to get overheated at that speed.
Q: What effect has it had on you?
A: My knee hurts a bit after being on all day. Colin and I have both noticed that we get hungry sooner when walking. I think that mean that our metabolisms are running faster. So I make sure to eat a good breakfast everyday, and we are really ready for lunch at noon now.
References:
Dr. James Levine talk about treadmill desks
The Mayo Clinic's Non-Exercise Activity Thermogenesis Lab
Jay Buster's Treadmill Desk
Treadmill Sensei - Good reviews and info and treadmills
Photos
From the Side:

The touch panel mounted beneath the work surface:

From the Front:

Underneath / Mounting detail:

Update 2/28/2010: Here is some video footage.
#