Ruby Code Quality Tools

This is the third post in my series of Ruby tools articles. This time I look at Ruby code quality tools. Rubyists like Ruby because the code can look so nice, simple, and sometimes beautiful. Unfortunately not all code is so great, in fact often the code I write doesn’t look good. Fortunately while a great language can help you to write great code, great tools can help as well. As code grows it is easy for code bloat, dead code, or confusing complexities to slip in. The tools I review below can help with all of these problems. I recommend finding the one or two code quality tools you like best and starting to integrate them more into your development process.

Roodi


Roodi gives you a bunch of interesting warnings about your Ruby code. We are about to release some code, so I took the opportunity to fix up anything Roodi complained about. It helped identify refactoring opportunities, both with long methods, and overly complex methods. The code and tests became cleaner and more granular after breaking some of the methods down. I even found and fixed one silly performance issue that was easy to see after refactoring, which improved the speed of our code. Spending some time with Roodi looks like it could easily improve the quality and readability of most Ruby projects with very little effort. I didn’t solve every problem because in one case I just didn’t think the method could be simplified anymore, but the majority of the suggestions were right on. Below is an example session with Roodi


dmayer$ sudo gem install roodi
dmayer$ roodi lib/client/syncer.rb
lib/client/syncer.rb:136 - Block cyclomatic complexity is 5. It should be 4 or less.
lib/client/syncer.rb:61 - Method name "excluded" has a cyclomatic complexity is 10. It should be 8 or less.
lib/client/syncer.rb:101 - Method name "should_be_excluded?" has a cyclomatic complexity is 9. It should be 8 or less.
lib/client/syncer.rb:132 - Method name "find_changed_files" has a cyclomatic complexity is 10. It should be 8 or less.
lib/client/syncer.rb:68 - Rescue block should not be empty.
lib/client/syncer.rb:61 - Method name "excluded" has 25 lines. It should have 20 or less.
lib/client/syncer.rb:132 - Method name "find_changed_files" has 27 lines. It should have 20 or less.
Found 7 errors.

After Refactoring:

~/projects/gridtest/trunk dmayer$ roodi lib/client/syncer.rb
lib/client/syncer.rb:148 - Block cyclomatic complexity is 5. It should be 4 or less.
lib/client/syncer.rb:82 - Rescue block should not be empty.
Found 2 errors.

I did have one problem with Roodi - the errors about rescue blocks just seemed to be incorrect. For code like the little example below it kept throwing the error even though I obviously am doing some work in the rescue code.

Roodi output: lib/client/syncer.rb:68 - Rescue block should not be empty.
begin
  socket = TCPSocket.new(server_ip,server_port)
  socket.close
  return true
rescue Errno::ECONNREFUSED
  return false
end

Dust


Dust detects unused code like unused variables,branches, and blocks. I look forward to see how the project progresses. Right now there doesn’t seem to be much out there on the web, and the README is pretty bare bones. Once you can pass it some files to scan, I think this will be something really useful. For now I didn’t think there wasn’t much I could actually do besides check it out. Kevin, who also helped create the very cool Heckle, does claim that code scanning is coming soon, so I look forward to doing a more detailed write up eventually.

Flog


Flog gives feedback about the quality of your code by scoring code using the ABC metric. Using Flog to help guide refactoring, code cleanup, and testing efforts can be highly effective. It is a little easier to understand the reports after reading how Flog scores your code, and what is a good Flog score. Once you get used to working with Flog you will likely want to run it often against your whole project after making any significant changes. There are two easy ways to do this a handy Flog Rake task or MetricFu which works with both Flog and Saikuro.

Running Flog against any subset of a project is easy, here I am running it against our client libraries
find ./lib/client/ -name \*.rb | xargs flog -n -m > flog.log

Here some example Flog output when run against our client code.

Total score = 1364.52395469781

Client#send_tests: (64.3)
    14.3: assignment
    13.9: puts
    10.7: branch
    10.5: send
     4.7: send_quit
     3.4: message
     3.4: now
     2.0: create_queue_test_msg
     1.9: create_run_msg
     1.9: test_files
     1.8: dump
     1.7: each
     1.7: report_start
     1.7: length
     1.7: get_tests
     1.7: -
     1.7: open
     1.7: load_file
     1.6: empty?
     1.6: nil?
     1.6: use_cache
     1.6: exists?
ModClient#send_file: (32.0)
    12.4: branch
     5.4: +
     4.3: assignment
     3.9: send
     3.1: puts
     2.9: ==
     2.9: exists?
     2.9: directory?
     1.9: strftime
     1.8: to_s
     1.5: read
     1.5: create_file_msg
     1.4: info
Syncer#sync: (30.8)
    13.2: assignment
     8.6: branch
     3.6: inspect
     3.2: info
     3.0: puts
     2.8: +
     2.6: empty?
     1.7: map
     1.5: now
     1.5: length
     1.4: send_files
     1.3: max
     1.3: >
     1.3: find_changed_files
     1.3: write_sync_time
Syncer#find_changed_files: (26.2)
    15.6: assignment
     8.7: branch
     3.5: <<
     1.8: to_s
     1.7: get_relative_path
     1.7: >
     1.7: mtime
     1.6: exists?
     1.6: ==
     1.5: prune
     1.4: should_be_excluded?
     1.3: get_removed_files
     1.3: find
... and so on ...

Saikuro


Saikuro is another code complexity tool. It seems to give a little less information than some of the others. It does generate nice HTML reports. Like other code complexity tools it can be helpful to discover the most complex parts of your projects for refactoring and to help focus your testing. I liked the way Flog broke things down for me into a bit more detail, but either is a useful tool and I am sure it is a matter of preference depending on what you are looking for.

saikuro screenshot
Saikuro Screenshot

Ruby Test Quality Tools

This is the second post in my series of Ruby tools articles. This time I am focused on Ruby test quality tools. Devver is always really interested in testing, and obviously the quality of a project’s tests is important. We are always looking at ways to add even more value to the investment teams put in with testing. Simply knowing that you are writing higher quality tests helps increase the value returned on the time invested in testing. I haven’t found many tools to help with test quality, but these tools are a great help to any Ruby tester.

Heckle


Heckle is an interesting tool to do mutation testing of your tests. Heckle currently supports Test:Unit and RSpec, but does have a number of issues. I had to run it on a few different files and methods before I got some useful output that helped me improve my testing. The first problem was it crashing when I passed it entire files (crashing the majority of the time). I then began passing it single methods I was curious about, which still occasionally caused Heckle to get into an infinite loop case. This is a noted problem in Heckle, but -T and providing a timeout should solve that issue. In my case it was actually not an infinite loop timing error, but an error when attempting to rewrite the code, which lead to a continual failure loop that wouldn’t time out. When I found a class and method that Heckle could test I got some good results. I found one badly written test case, and one case that was never tested. Lets run through a simple Heckle example.

#install heckle
dmayer$ sudo gem install heckle

#example of the infinite loop Error Heckle run
heckle Syncer should_be_excluded? --tests test/unit/client/syncer_test.rb -v
Setting timeout at 5 seconds.
Initial tests pass. Let's rumble.

**********************************************************************
***  Syncer#should_be_excluded? loaded with 13 possible mutations
**********************************************************************
...
2 mutations remaining...
Replacing Syncer#should_be_excluded? with:

2 mutations remaining...
Replacing Syncer#should_be_excluded? with:
... loops forever ...

#Heckle run against our Client class and the process method
dmayer$ heckle Client process --tests test/unit/client/client_test.rb
Initial tests pass. Let's rumble.

**********************************************************************
***  Client#process loaded with 9 possible mutations
**********************************************************************

9 mutations remaining...
8 mutations remaining...
7 mutations remaining...
6 mutations remaining...
5 mutations remaining...
4 mutations remaining...
3 mutations remaining...
2 mutations remaining...
1 mutations remaining...

The following mutations didn't cause test failures:

--- original
+++ mutation

 def process(command)

   case command
   when @buffer.Ready then
     process_ready
-  when @buffer.SetID then
+  when nil then
     process_set_id(command)
   when @buffer.InitProject then
     process_init_project
   when @buffer.Result then
     process_result(command)
   when @buffer.Goodbye then
     kill_event_loop
   when @buffer.Done then
     process_done
   when @buffer.Error then
     process_error(command)
   else
     @log.error("client ignoring invalid command #{command}") if @log
   end
 end

--- original
+++ mutation
 def process(command)
   case command
   when @buffer.Ready then
     process_ready
   when @buffer.SetID then
     process_set_id(command)
   when @buffer.InitProject then
     process_init_project
   when @buffer.Result then
     process_result(command)
   when @buffer.Goodbye then
     kill_event_loop
   when @buffer.Done then
     process_done
   when @buffer.Error then
     process_error(command)
   else
-    @log.error("client ignoring invalid command #{command}") if @log
+    nil if @log
   end
 end

Heckle Results:

Passed    :   0
Failed    :   1
Thick Skin:   0

Improve the tests and try again.

#Tests added / changed to improve Heckle results
  def test_process_process_loop__random_result
    Client.any_instance.expects(:start_tls).returns(true)
    client = Client.new({})
    client.stubs(:send_data)
    client.log = stub_everything
    client.log.expects(:error).with("client ignoring invalid command this is random")
    client.process("this is random")
  end

  def test_process_process_loop__set_id
    Client.any_instance.expects(:start_tls).returns(true)
    client = Client.new({})
    client.stubs(:send_data)
    client.log = stub_everything
    cmd = DataBuffer.new.create_set_ids_msg("4")
    client.expects(:process_set_id).with(cmd)
    client.process(cmd)
  end

#A final Heckle run, showing successful results
dmayer$ heckle Client process –tests test/unit/client/client_test.rb
Initial tests pass. Let’s rumble.

**********************************************************************
*** Client#process loaded with 9 possible mutations
**********************************************************************

9 mutations remaining…
8 mutations remaining…
7 mutations remaining…
6 mutations remaining…
5 mutations remaining…
4 mutations remaining…
3 mutations remaining…
2 mutations remaining…
1 mutations remaining…
No mutants survived. Cool!

Heckle Results:

Passed : 1
Failed : 0
Thick Skin: 0

All heckling was thwarted! YAY!!!

rcov


rcov is a code coverage tool for Ruby. If you are doing testing you should probably be monitoring your coverage with a code coverage tool. I don’t know of a better tool for code coverage than rcov. It is simple to use and generates beautiful, easy-to-read HTML charts showing the current coverage broken down by file. An easy way to make you project more stable is to occasionally spend some time increasing the coverage you have on your project. I have always found it a great way to get back into a project if you have been off of it for awhile. You just need to find some weak coverage points and get to work.
Rcov Screenshot
rcov screenshot

Ruby Performance Tools

I have been interested in all of the tools that exist for Ruby developers. I give you the first of a series of posts where I will be looking at some of the more interesting Ruby tools.

Recently a few different Rail performance tools / web services have been released. They are leaps and bounds better than just watching your developer log and trying to fix performance issues, or just tracking down slow MySQL queries. I went ahead and installed and worked with a few of these tools and wrote a bit about my thoughts and experience with each of them.

ruby-prof


ruby-prof does what every other profiler does, but it is much faster than the one built in to Ruby. It also makes it easy to output the information you are seeking to HTML pages, such as call graphs. If you are just looking for a simple write up to get started with ruby-prof I recommend the previous link. I will talk a little more about the kinds of problems I find and how I have solved them with ruby-prof.

I have used ruby-prof a number of times to isolate the ways to speed up my code. I haven’t used it to identify why an entire Rails application is slow (there are better tools I discuss later for that), but if you have a small but highly important piece of code ruby-prof is often the best way to isolate the problem. I used ruby-prof to identified the two slowest lines of code of a spellchecker, which was rewritten to become twice as fast.

Most recently I used it to identify where the code was spending all of its time in a loop for a file syncer. It turns out that for thousands of files each time through the loop we were continually calling Pathname.new(path).relative_path_from(@dir_path) over and over. Putting a small cache around that call essentially eliminated all delays in our file synchronization. Below is a simple example of how a few lines of code can make all the difference in performance and how easily ruby-prof can help you isolate the problem areas and where to spend your time. I think seeing the code that ruby-prof helped isolate, and the changes made to the code might be useful if you are new to profiling and performance work.

changes in our spellchecker / recommender

 #OLD Way
 alteration = []
    n.times {|i| LETTERS.each_byte {
        |l| alteration << word[0...i].strip+l.chr+word[i+1..-1].strip } }
 insertion = []
     (n+1).times {|i| LETTERS.each_byte {
        |l| insertion << word[0...i].strip+l.chr+word[i..-1].strip } }
 #NEW Way
    #pre-calculate the word breakups
    word_starts = []
    word_missing_ends = []
    word_ends = []
    (n+1).times do |i|
      word_starts << word[0...i]
      word_missing_ends << word[i+1..-1]
      word_ends << word[i..-1]
    end

 alteration = []
    n.times {|i|
      alteration = alteration.concat LETTERS.collect { |l|
        word_starts[i]+l+word_missing_ends[i] } }
 insertion = []
    (n+1).times {|i|
      insertion = insertion.concat LETTERS.collect { |l|

        word_starts[i]+l+word_ends[i] } }

Changes in our file syncer

#OLD
 path_name = Pathname.new(path).relative_path_from(@dir_path).to_s
 #NEW
 path_name = get_relative_path(path)

  def get_relative_path(path)
    return @path_cache[path] if @path_cache.member?(path)
    retval = Pathname.new(path).relative_path_from(@dir_path).to_s
    @path_cache[path] = retval
    return retval
  end

New Relic


New Relic is a performance monitoring tool for Rails apps. It has a great development mode that will help you track down performance issues before they even become a problem, and live monitoring so that you can find any hiccups that are slowing down the production application. The entire performance monitoring space for Ruby/Rails seems to be heating up. I guess it is easy to see why, when scaling has been such an issue for some Rails apps. Just playing around with New Relic was exciting and fun. I could quickly track down the slowest pages, and our most problematic SQL calls, in this case I was testing New Relic on Seekler (an old project of ours) since I didn’t think I would find much interesting on our current Devver site. Seekler had some glaring performance issues and I think if we had New Relic from the beginning we could have avoided many of them. Sounds like I might have a day project involving New Relic and giving Seekler as much of a performance boost as possible. New Relic turned out to be my favorite of the performance monitoring tools. For a much more detailed writeup check out RailsTips New Relic Review.

newrelic screenshot
New Relic screenshot

TuneUp


TuneUp another easy-to-install and use Rails performance monitoring solution. The problem I had with TuneUp was I couldn’t get it working on test app for these sorts of things. I tried running Seekler with TuneUp, but had no luck. I found that many people on the message boards seemed to be having various compatibility issues. I looked at the TuneUp screencast and the kind of information that they give you and I feel like this would be equal to New Relic if it works for you. I am emailing back and forth with FiveRuns support who have been very attentive and helpful, so if I get it working I will update this section.

Ruby Run


RubyRun provides live performance monitoring and debugging tools. I hadn’t ever heard of this product before I started doing some research while writing this blog article. I am sorry to say but this was the hardest to set up, and gave back less valuable information. I think they need a simple screencast on how to get set up and get useful information back. After getting setup and running I could only get ugly CSV reports that didn’t tell me much more than the regular Rails log files. I started reading the RubyRun Manual but it was about as long as Moby Dick and all I wanted was how to view simple easy-to-read reports which is a snap in New Relic and TuneUp. Since the site didn’t mention RubyRun providing better data than New Relic or TuneUp which were much more user friendly, I don’t think I would recommend RubyRun.


UPDATE: After reading about my difficulties with RubyRun the great folks from Rubysophic got in touch with me. They offered to help me get the tool working and posted a RubyRun quick start guide to their site. I got it working in a snap thanks to an email from their dev and the amazingly simple quick start guide. I still didn’t get the same depth of information that I got with New Relic, although RubyRun has a ton of settings so it is likely you can get more depth to the reports. Something worth pointing out is that RubyRun is working on Seekler, which I haven’t been able to get TuneUp running on. So if you have been having problems with TuneUp or New Relic, definitely give RubyRun a look. In the end I think the other offerings are slightly more user friendly (less complex settings), and easier to explore the data (link in the feed to both reports, at least when in developer mode). That being said RubyRun offers some great information and options that the others don’t and with a bit more UI tuning RubyRun would be at the top of the pack. Thanks to the helpful devs at Rubysophic for helping me to get the most out of RubyRun.


RubyRun screenshot
RubyRun screenshot
RubyRun second screen shot
screenshot of a different RubyRun report

If there are any other Ruby performance tools worth checking out let me know. Obviously, if you have experience with any of these tools I would love to hear your thoughts on them.

Boulder.Me: An interesting way to get employees

Boulder has a lot going on in terms of tech startups. A bunch of Boulder startups got together for a pretty interesting plan. A group of startups will be flying 100 interviewees out to Boulder to interview potential employees and let them get a feel for the city. There has already been some pretty good coverage of the plan on TechCrunch and elsewhere.

So if you are interested in getting a great job with some of the awesome startups in Boulder, I highly recommend checking out and applying to Boulder.Me.

Devver has Launched!

We’re happy to announce that on Thursday we officially launched with our first alpha customer!

Dan and I were both pretty nervous, but we also knew that this was an important step forward for Devver. I won’t say it went off without a hitch (we ran into a few bugs in the morning, which was pretty stressful). I don’t think we’ve ever watched log files with such interest and anticipation.

Thankfully, our alpha customers were awesome - patient, forgiving, and funny all at once. We got tons of great feedback from them in just in the first few hours alone. And, by the afternoon, Devver was up and running on their code base - in fact, we brought a test suite that was taking around forty minutes to complete on one machine down to two minutes on Devver.

All in all, it was a successful launch. It was a huge thrill to see a customer using Devver. I’ll leave you with a few real IM quotes from our customers:

“hurray! tests are zipping along.”

“I’m actually really excited to work with this.  I think it will really improve the process around here.”

And my personal favorite: “dots a’flowin’ “

Why Side Projects?

I just read a great post at Ekinoderm that nicely tied together two things Dan and I have been thinking and blogging about recently - the joys of side projects and why you should own your own IP. Check it out.

One Day of TDD

I am am a big believer in software testing. I normally have created tests after writing my code and mostly to ensure that regressions of functionality don’t occur when the code is changed. As I have become more comfortable with testing, and the changes it requires such as writing testable code, I have found even more benefits of testing. Better automated testing, and better understanding of testing has changed my development practices.

I haven’t practiced TDD, but I do follow Test Driven Corrections (TDC) which I might be coining right now. Following TDC means that when you find a bug, you should try to write a test that fails on that bug, then fix bug and make the test pass. I have become a fan of fixing bugs this way because bugs often first appear in code that for one reason or another is brittle or has some unseen dependency. If you just fix the bug even if it was a simple mistake it is still far more likely that there will be another bug with that piece of code than other areas. If you know a section of code is error prone wouldn’t you want to catch the error as fast as possible?

A new tool in my toolbox is exploratory testing. If I was learning a new library or object in the past I would often write simple programs that would print out the state, manipulate that state, and print the result. I would then continue to learn ways to work with the objects and verify that the printed state matched my expectations. Hmmm that seems error prone, and not necessarily repeatable. Now when I am learning something new I tend to write tests against my expectations of how things should work. A great recent example of this was when I was learning to use the RightScale AWS gem so I could access Amazon’s SimpleDB (SDB). I ended up writing tests to create, save, update, and delete objects. After that it was easy to write a real DB layer for some of our objects and write additional tests for that as well.

The more I learned about testing the more useful I have found it in many situations. The issue is that I have still never bought into the idea of TDD for most development. Even though many smart people have written about the benefits of TDD (Adam@Heroku Jay Fields), it just hasn’t ever seemed worth it to me. I decided that I really couldn’t knock it if I really hadn’t ever tried it for any significant amount of time. So I decided to spend one full day completely following TDD.

I was going to be adding some new features to Devver, and thought it would be a good chance to try my TDD challenge. The features I was adding were some small actions on the server that would be triggered remotely by the client. This broke down into a few separate pieces of functionality.

1. The client would send one of three new requests based on user input and existing client state
2. The server would receive and parse these new messages
3. The server would call 3 new handlers with the encoded project data and carry out tasks

Breaking this into tests was very natural and led to nearly no debugging time as almost the first time the client and server connected the interactions all behaved exactly as expected. I didn’t waste any time looking into where a message or a response got lost or wasn’t properly acknowledged in the code. The tests had already simulated the message creation, parsing, routing as well as the event handling and completion. It is nice when you put all the pieces together and it just works, and you know it is very solid from the beginning.

To break down the tasks I wrote the tests in this order.

1. Tested creating messages to store the expected project information
2. Tested parsing messages to get the expect project information
3. Tested client inputs would call my event handlers
4. Tested that client event handlers would send the proper message
5. Tested that the server would receive and parse the expected messages
6. Tested that the server would call my event handlers
7. Tested that event handler would complete the task expected off them

After spending a day and completing all the pieces of functionality I had expected to complete I was happy with my TDD experiment. I came away with a new respect for TDD an while I still don’t think it would be well suited to all programming tasks, I can certainly see a place for it and plan on using TDD more in the future. I do think that it took me slightly longer to complete the features than it normally would have. I freely admit that the more often you do TDD development the better you would get and that likely less time would be wasted trying to think up the proper test cases. I felt that the code I wrote under TDD was of a higher quality than the code I normally write. It forced me to refactor and rework my code as I went as well as break it into small enough pieces that I could write simple tests to verify the next piece of the project. I think that the code I ended up writing will be less brittle and easier to work with in the future. As a developer, I was happier and more sure of the stability of the features I just added to the system.

I think TDD is especially well suited to situations with small communications between systems, as each independent system can be completely tested and have it’s behavior verified while isolated from the other pieces. I was surprised that working in a way that demanded more upfront costs before I wrote anything functional didn’t slow me down more. I was expecting that it would make my development process slower by a factor of two, but the truth is that a single nasty bug halting your forward progress can take up more time than you would have needed to spend initially if working with a TDD approach.

I don’t plan on trying to move over to an entirely TDD approach but by challenging myself to work in a way that seemed unintuitive to me, I ended up learning a lot and likely will use the approach in the future for myself.

My Day Project: IMShoes

Inspired by two posts _Why’s ’so create’ and GitHub’s Start a Side Project I decided that I needed to do a quick side project. After our demo day we were taking the weekend easy and I had some extra time on Sunday. I decided that I should find a really quick project something I could really just do in one day. Since I was partly inspired by _why, I decided to take some time to learn Shoes.

“Shoes is a very informal graphics and windowing toolkit. It’s for making regular old apps that run on Windows, Mac OS X and Linux. It’s a blend of my favorite things from the Web, some Ruby style, and a sprinkling of cross-platform widgets.”

I tried to think of a simple Shoes app that I could contribute to The Shoebox (a collection of Ruby Shoes apps). I saw a couple Shoe’s Twitter apps, but didn’t see any Shoes AIM apps. Since I knew a good AIM protocol library for Ruby existed (Net-Toc), I thought it would be a nice simple app.

I ran into a few problems with Shoes (getting it to work with Gems) and it seemed to have problems loading YAML files. Besides the mentioned problems it was a breeze to work with. I looked at a few different example apps from the Shoebox. I ended up using Gentle Reminder as a template of sorts for my app. So basically in couple hours on Sunday I read a bunch about Shoes, read the source code of a couple Shoes apps, and I created a very small but functional GUI for AIM. It was a great little side project that reminded me how much fun it can be to code little things once in awhile.

If you have a day off go try to write some code and contribute to one of your favorite projects. Or finally go learn a new library or framework that looks really cool and try to give something back to that community. Then write up a post and share your experience with others. The best way to learn is to go do something, quoting _why, “so create.”

So I proudly present my tiny day project IMShoes.

# A small gui for basic AIM messaging

# Author::    Dan Mayer (mailto:dan<@t>devver.net)
# Site:: http://devver.net/blog
# Copyright:: Copyright (c) 2008 Dan Mayer
# License::   revised BSD license
# (http://www.opensource.org/licenses/bsd-license.php)
# Version::   0.0.1 (AKA a "alpha it sucks" version)
# Thanks::
# Ian Henderson for creating TOC, _why for Shoes, and
# Oliver for Gentle Reminder which I used to learn (as my template).

#You need to install net-toc with gem install net-toc
#then copy toc.rb into shoes/contents/ruby/lib/net for this to work in shoes
require 'net/toc'

Shoes.app :title => "Shoes AIM",
  :width => 370, :height => 560, :resizable => false do

  #ADD your own user and password here, should allow you to do this via GUI
  @user = 'urUser'
  @password = 'urPass'

  background green, :height => 40

  caption "IM Shoes", :margin => 8, :stroke => white

  stack :margin => 10, :margin_top => 10 do
    para "Buddies", :stroke => red, :fill => yellow

    stack :margin_left => 5, :width => 1.0, :height => 200 do
      background white
      border white, :strokewidth => 3
      @gui_buddies = para
    end

     flow :margin_top => 10 do
       para "To"
       @send_to = edit_line(:margin_left => 10, :width => 180)
     end

     flow :margin_top => 10 do
       para "Message"
       @add = edit_line(:margin_left => 10, :width => 180)
       button("Send", :margin_left => 5)  do
         send_msg(@send_to.text, @add.text);
         @send_to.text = '';
         @add.text = '';
       end
     end
   end

  stack :margin_top => 10 do
    background darkgray
    para strong('Messages'), :stroke => white
  end

  @gui_messages = stack :width => 1.0, :height => 207

  def refresh_buddies
     @buddies = []
     @client.buddy_list.each_group { |g, b| @buddies = @buddies + b }

     @gui_buddies.replace *(
                         @buddies.map { |buddy|
                           [ buddy.screen_name, '  ' ] +
                           [ link('Message') { set_to buddy.screen_name } ] +
                           [ '  ' ] + [ "\n" ]
                         }.flatten
                         )
  end

  def refresh
    refresh_buddies
    refresh_msgs
  end

  def refresh_msgs
    @gui_messages.clear

    @gui_messages.append do
      background white

      @messages.keys.sort.reverse.each { |day|
        stack do
          background lightgrey
          para strong(day.strftime('%B %d, %Y')), :stroke => white
        end

        stack do
          inscription *(
                        ([@messages[day][0].to_s]+
                         [" "]+
                         [@messages[day][1].to_s]+
                         [" "]+
                         [link('Reply') { set_to(@messages[day][0].to_s) }]).flatten
                        )
        end    

      }

    end
  end

  def set_to(screen_name)
    @send_to.text = screen_name;

    refresh
  end

  def send_msg(to_name, msg)
    msg = msg.strip
    to_name = to_name.strip

    return if msg == ''
    return if to_name == ''

    to_buddy = @client.buddy_list.buddy_named(to_name )

    if to_buddy.available?
      to_buddy.send_im(msg)
      @messages[Time.now]=[to_name,msg]
    end

    refresh_msgs
  end

  def load
    @client = Net::TOC.new(@user, @password)
    @client.connect
    sleep 3
    @messages = {}

    @buddies = []
    @client.buddy_list.each_group { |g, b| @buddies = @buddies + b }

    @client.on_im() do |message, buddy, auto_response|
      @messages[Time.now]=[buddy.screen_name, message.gsub(/<\/?[^>]*>/, "")]
      #buddy.send_im("#{message} responce")
      refresh_msgs
    end

    refresh
  end

  load

end



Screenshot:

IM Shoes Screenshot

Yeah, that’s my cofounder

Behold my favorite picture of this awesome TechStars summer

Dan\'s backflip

Considering you can clearly see the Devver logo on Dan’s shirt, I think this needs to be in all our future marketing material. Nothing says “developers love Devver” like a developer doing a backflip in excitement. Awesome stuff.

TechStars Completed

TechStars has been an amazing group to be a part of. We have frequently been asked about the program and “what is the best part of the TechStars program?” It is really hard to break it down to any single point, but all the benefits come back to being all about the people.

We have received a ton of help from everyone in the program. We want to thank all of the mentors and sponsors involved with the program. TechStars really brings an amazing group of people together. We of course want to thank the original founders of TechStars - you have helped to build a really unique and engaged tech community in Boulder.

We want to give mad props to all of the other TechStars 08 teams. Some of the best advice we got came from the other teams. So thanks goes out to Occipital, Gyminee, App-X, TravelFli, Ignighter, People’s Software Company, Foodzie, BuyPlayWin, and of course The Highway Girl.

We also got some great advice and feedback from some of last year’s teams. Thank you to Ari from Filtrbox, Rob and Josh from EventVue, and the entire team with Socialthing!.

Last, but not least, we wanted to give a final thanks to some of the mentors that we spent additional time with. We really appreciate the advice, feedback, and laughs… thanks to David Cohen, Tom Higley, and Seth Levine.

Congrats to everyone for making TechStars such an amazing ride. We know that even though the program is over we will still be getting advice from many of you and still be working with the kind of determination that TechStars helps foster.