Tuesday, April 08, 2008

Frankie Goes To Facebook

UPDATED 4/12/2008: Now compatible with Sinatra 0.2.0
So you want to create a small Facebook application... seems like it should be a small thing, right? But creating an entire Ruby on Rails application just for a tiny little Facebook application is, at the very least, a bit wasteful. In the case of a overly popular Facebook app you could end up with, as Marc Andreessen put it, a "self-inflicted denial of service attack", unless you have both a pretty serious infrastructure to support it, as well as lots of cash to keep that data center running.

Wouldn't you rather be able to create a highly scalable "hello, world" Facebook application in around 13 lines of Ruby code? Say hello to Frankie:

require 'rubygems'
require 'frankie'

configure do
set_option :sessions, true
load_facebook_config "./config/facebooker.yml", Sinatra.env
end

## facebooker helpers
before do
ensure_authenticated_to_facebook
ensure_application_is_installed_by_facebook_user
end

## the site
get '/' do
body "<h1>Hello #{session['facebook_session'].user.name} and welcome to frankie!</h1>"
end


Frankie is a plugin for the minimalist and very fast Sinatra web framework that allows you to easily create a Facebook application by using the Facebooker gem. Why would you want to use it? If your Facebook application needs to be highly scalable, is fairly small, or is really a mashup of other web-available resources, than Frankie could be a good solution.

Frankie is available now for your enjoyment. Here is how to get started:

- Install the Frankie gem, which will install the Sinatra and Facebooker gems if you do not already have them.
sudo gem install frankie


- Create the application directories for your new app:
mkdir myapp
cd myapp
mkdir config


- Put your facebooker.yml file into the /myapp/config directory, and set the values to your information. Here is a simple example of the file:

-------
development:
api_key: apikeyhere
secret_key: secretkeyhere
canvas_page_name: yourcanvashere
callback_url: http://localhost:4567
test:
api_key: apikeyhere
secret_key: secretkeyhere
canvas_page_name: yourcanvashere
callback_url: http://localhost:4567
production:
api_key: apikeyhere
secret_key: secretkeyhere
canvas_page_name: yourcanvashere
callback_url: http://yourrealserver.com


- Make sure you have setup your facebook application on the facebook site. Google "setup new facebook application" if you are unsure how to do this. I recommend starting with an IFrame application, so that you can point a development version of your Facebook application to your local machine. This, like our example here, would use "http://localhost:4567" as the callback URL when configuring the Facebook app.

- Create your application, based on the sample above, and run it:
ruby sample.rb


This will start the Sinatra Ruby web server running:
== Sinatra has taken the stage on port 4567!


- Test it by pointing your browser to http://apps.facebook.com/yourappname. If you have things setup correctly then you should see your application appear inside of Facebook's site.

Facebook is now your playground... have fun with Frankie!

Thursday, March 13, 2008

Excuse Me, While I Kiss The Sky

The demo that Microsoft showed at TED of Robert Scoble crying, ahem, I mean their future Microsoft Worldwide Telescope or whatever, looks really neat. In the meantime, those provocateurs over at Google have just put live Google Sky, a fully browser based version of their Google Earth software that started this whole "star wars" virtual astronomy competition thing in the first place.

I suppose since so many people cannot see the stars anymore, that we need virtual astronomy more than ever. In the meantime, it is pretty incredible to have such an educated introduction to the heavens. I could easily spend hours just like, playing with the universe, man.

The U.S. Navy Goes Open Source

That unwitting center of global innovation known as the United States Navy has made a bold announcement: from now on, they are only going to accept open source.

I just read about this on CNET, where they were linking to a recent story in Federal Computer Week. When I read this, I just about fell out of my seat. According to Vice Adm. Mark Edwards, deputy chief of naval operations for communications:

“The days of proprietary technology must come to an end,” he said. “We will no longer accept systems that couple hardware, software and data.”


Really. I am not making this up. Here is some more juicy stuff:


“We can’t accept the increasing costs of maintaining our present-day capabilities,” Edwards said. “In the civilian marketplace, it’s just the opposite. Some private-sector concerns are cutting their costs by 90 percent while expanding their performance.”

Edwards noted that the Navy has cut the number of databases and applications it maintains and has reduced its networks by 40 percent. “But it is not enough,” he added. “We would have to double our IT budget over the next several years just to run in place.”

By using an open network architecture, the Navy could rapidly upgrade its capabilities and handle increases for demand, Edwards said.


So what will be next? The U.S. Navy vs. The US Patent and Trademark Office? Wow, talk about getting bogged down in a conflict! Still, my money is on the Navy... I played on a soccer team with a Navy SEAL and a couple of Marines (also not kidding) and those guys really ARE tough!

The Telepathy Machine Demo

I just saw an amazing demo of communication without speaking. No, not instant messaging, or sign language. Instead, scientists at Ambient Corporation have succeeded in tapping into the nervous system that control speech, and translate that into digitized speech. Michael Callahan showed off their demo at the Texas Instruments developer conference. Wow, this is a long way from my TI-99/4!

Applications for secret agents, people who suffer from ALS, and people who cannot shut up when on the subway will be forthcoming. The quality is "at the same level of recognition as the early days of speech to text", so it will be a little while till all those people staring off into space at cafes are actually talking to someone else.

In the meantime, I would like to scan all of you in this room one at a time...

Wednesday, March 05, 2008

Merb On The Virge

Merb, the mighty challenger to the current Rails domination of the Ruby web framework conversation, races towards "getting very close to being stable api wise". That sounds like a 1.0 release to me!

Ezra says that the 0.9.1 developer release is ready to take thru its paces. One area where Merb really differs from Ruby on Rails is how Merb is based off of RubyGems. The refactored Merb architecture takes the Merb modularity to a massive 16 gems. You can really pick and choose what you want to include in your application.

Luckily for the very lazy, or the undecided, there is a Merb gem that will install everything for you. All you have to do is:


sudo gem install merb -y --source http://merbivore.com


And away you go! Unfortunately, "you should uninstall all of your old Merb gems before you install the new version" but that is not so bad. If you have been Merbing for while, you are not afraid to get your hands a little dirty. And if not, Merb 1.0 (dare I say it?) is right around the corner.

Saturday, March 01, 2008

Thanks For Paying Attention

This last week has brought some very nice and favorable attention to the Dead Programmer Society.

The ever-popular "I'd Rather be A Jazz Programmer" post popped up again, this time in the stodgy old school publication Computerworld. They ran an article on the "Rock Star Programmer" meme, and decided that my little post was part of the "Kill Rock Stars" contrarian perspective they were looking for. Thanks for making me look so good, guys!

Actually it really is pretty amazing to make an article that also mentions Linus Torvalds, Joel Spolsky, Paul Graham, Obie Fernandez, Zed Shaw, and "why the lucky" (sic). Hey, I told you Computerworld was stodgy. Sorry they mangled your handle, why!

On to more recent work. Ari Lerner and I have been getting some good attention to our introduction of the EC2 ProcessorPool gem. We managed to get covered in both Rails Envy and Ruby Inside this last week. Thank you to the editors for helping us let people know about this quite useful tool.

Anyhow, that is about enough self-congratulation for one post. Next time, back to our irregularly scheduled programming.

Wednesday, February 20, 2008

Rush The Shell

I just read the latest posting from Adam Wiggins, very cool dude, hard-core Rubyist, and friend. He has a new project called Rush, the Ruby shell. Adam is one of the guys behind Heroku, which is a pretty amazing pure web browser-based IDE/deployment/hosting solution for Ruby on Rails, if you haven't seen that yet.

Anyhow, like many of us, Adam seems like he just wants to use Ruby for everything. And when I say everything, I mean EVERYTHING. Writing bash scripts.... sucks. Destroying the sanctity of your Ruby code with
`bash-shell-command /ugly /madness`
is not hardly any better. My man is trying to help us do away with all that, by applying a friendly familiar Rubyness, not just caging the ugliness away.

Here is a little taste of Rush, from the Rush site:

How about killing those pesky stray mongrels? Before:

kill `ps aux | grep mongrel_rails | grep -v grep | cut -c 10-20`

After:

processes.each { |p| p.kill if p.command == "mongrel_rails" }

But rush is more than just an interactive shell and a library: it can also control any number of remote machines from a single location. Copy files or directories between servers as seamlessly as if it was all local. bash and ssh, we love you, but your era is past.

Example of remote access:

local = Rush::Box.new('localhost')
remote = Rush::Box.new('my.remote.server.com')
local_dir = local['/Users/adam/myproj/']
remote_dir = remote['/home/myproj/app/']
local_dir.copy_to remote_dir
remote_dir['**/.svn/'].each { |d| d.destroy }


I have not had a chance to play with Rush yet, but I'm sure I will be. Unix shell scripting is not syntactical sugar, that is for sure, and Rush looks pretty sweet.

Everybody Into The Pool

A few weeks back, I indulged my current obsession with grid computing, and Amazon's EC2 and S3 services in particular, with a lengthy post. I mentioned how friend Ari Lerner and I had built a really neat solution, and were going to put all of our processing farm goodness into a nice neat gemified package. Well, mostly thanks to Ari, we now have a new Ruby gem called ProcessorPool that uses EC2 and S3 to do all the hard work for you.

Based on Sinatra, with a bunch of S3 goodness mixed in, the ProcessorPool gem makes it staggeringly easy to exploit the power of the EC2 grid. More info about it is available at the Blog @ CitrusByte, and you can also check it out on RubyForge here.

All kinds of fun applications await you in the pool... image processing, video/audio transcoding, heavy computational stuff, long crawls of content... and it is fun to delegate to a pool of worker machines in the EC2 cloud.

Come on in... the pool is fine.

Tuesday, February 19, 2008

Getting To Usable

I read a great posting last night from Matt Rogers, founder of startup Aroxo, on a strategy for usability testing. Suddenly, I was flashing back a few years to the early salad days of web usability...

When I first read Steve Krug's tiny masterwork "Don't Make Me Think", I was very excited; at last, a nice practical approach! After the pedantic and overly academic work of guys like Jakob Neilson, Krug's book hit me like Dr. Seuss taking out Dick, Jane, and Spot.

Somehow, Rogers' post reminded me of that sudden flash of clarity in the fog. Yes, we can DO this! Gentlemen and ladies, start your testing...

Tuesday, February 05, 2008

You Got Your DS In My Robot

The French press may be reeling in financial scandal, but the cool kids there are still concentrating on what is really important: drinking wine and controlling an open source robot with a heavily modded Nintendo DS.

The Pekee Mobile Robot and a whole bunch of DS hacking. That in itself just sounds like hours of fun. But then can you just imagine real-world robotic battles in your living room, fought remote controlled by DS. Can I preorder now?

C'est Manifique!

Ruby.NET, We Hardly Knew Ye

It comes as not entirely surprising that the Wayne Kelly of the Ruby.NET project from down under has finally given up the ship. Microsoft had already grabbed the spotlight with IronRuby and the DLR. Despite some early gains, it seemed that development momentum had peaked, until Ruby.NET finally made its way up onto Google Code and a "real" open source project.

How, how will John Lam and team proceed without Ruby.NET around? I seem to recall a conversation I had with John when we were at RailsConf, and he was telling me since his M$ cannot look at open-source source code due to patent issues, they were unable to look at the MRI code in order to implement IronRuby. He said they WERE able to look at the Ruby.NET code due to some weird licensing thing. Does this mean they have now had their way with Ruby.NET, and they are done with it?

The DLR is a very cool concept, but it seems like is a lot more than many developers want, particularly polyglot ALT.NET folks who just want to add some capabilities most easily implemented in the Ruby-language, more than they want to switch over to pure Ruby.

Reading further in the mailing list thread, it seems like others in the Ruby.NET project are not quite ready to throw in the towel quite yet... but is it already too late for them?

Friday, February 01, 2008

Recaptcha On Rails

UPDATED Oct. 15, 2009 with most current info

I hate implementing captchas. You know, those annoying things that your users think are deciphering hieroglyphics. I have hated them because I do not want to install a whole massive assemblage of software like ImageMagick/RMagick just to provide some basic protection from spam and bots.

To avoid this, I had hacked together a simple implementation using some free public captcha. However, a client recently turned on SSL on their signup page, and my free public captcha gave a nasty error cause of the domain name in the SSL certificate not matching the domain of their site. How cheap!

I needed a new solution. I waded thru pages of search results with the dreaded RMagick sotuions. But then, lo and behold, I discovered there is a fantastic simple plugin for Ruby on Rails from Ambethia that supports the marvelous Recaptcha.

Recaptcha is a really neat project that uses crowdsourcing to implement a form of human OCR on old books that defy machine OCR. They need human scanners, and we need proof that the people signing up on the site are human. Perfect match!

Less than 10 minutes later I had the plugin installed, implemented, and deployed in production. It is that easy. Here is a four step process that will have you up in moments:

Step 1 - Install the Recaptcha plugin

script/plugin install git://github.com/ambethia/recaptcha.git

'Nuff said.

Step 2 - Set Your Recaptcha Account Data in Rails
OK, so I lied. You need to tell the plugin what your account info is, and if you do not yet have a free Recaptcha account, you will need to sign up for one. Once you do, save your keys into config/initializers/recaptcha.rb

ENV['RECAPTCHA_PUBLIC_KEY'] = 'youractualpublickey'
ENV['RECAPTCHA_PRIVATE_KEY'] = 'youractualprivatekey'


Step 3 - Display The Recaptcha Widget In Your View
You will need to display the Recaptcha widget somewhere. In my case, it was the signup page for the site. Just put this view helper where you want the widget to appear:

<%= recaptcha_tags %>

If you are using SSL, use this instead:

<%= recaptcha_tags :ssl => true %>


Step 4 - Validate The Recaptcha
You need to make sure that the user entered the proper values for the Recaptcha. Just add this to the controller action that the view submits to:


If you want to display any Recaptcha errors right along with any model errors of the model you are trying to control adding using the Recaptcha, you could do this instead:



You may have guessed by now that it took me longer to write this posting than to implement Recaptcha using the Ambethia plugin. Hey, that is just the kind of guy I am. It was just so cool, and such a quick solution to a common problem, that I couldn't help myself.

Let the digitizing begin!

Tuesday, January 29, 2008

RailsConf 2008 Registration Is Open

Get ready, get set, go!! The annual frenzy of registration for RailsConf 2008 has begun.

Yes, I have already received my registration confirmation. No, I have not received my speaker confirmation...yet? Oh well, looks like RejectConf again!

See you all there... ahem, not all of you, unless you register right now!

The Patent Apocalypse Begins?

Software patents... as, Obi-Wan warned, "You will never find a more wretched hive of scum and villainy. We must be cautious." Well, the dark side has struck back, people. A massive salvo has been launched, this time aimed directly at the open source community in the form of Trend Micro vs. Barracuda Networks.

I was thinking about a cute little pictograph that would describe the public awareness and attitudes about software patents. Yes, this is highly unscientific. Also, I was too lazy to do it, so I settled for pie charts instead:




75% - Huh? Pass the beer...
24% - I know ALL about software patents... shoes, right?
1% - Programmers & Patent Lawyers



Within the programmers and patent lawyers, we could break it down this way:
75% - I don't mess with them, they don't mess with me... please don't hurt me...
24% - Ban the patent!
1% - Sue me? Sue you!

Is that last group now large enough to start the patent apocalypse? Just like any conflagration, some small sparks can result in a firestorm with devastating consequences.

Just ask yourself... really... are the ideas of free open source software and software patents compatible in any way? Are these two not overdue for a showdown? And what if we lose?

Be afraid... be very afraid...

Monday, January 28, 2008

I Want My API

I just ran into a really great resource for open source API documentation. Called gotAPI, it links in a delightfully searchable way all of the APIs we love, but turn out to not actually know. Well, we know them, just not well enough to have their numbers setup for speed dial on our cell phones. Or our code able to call them directly without looking up a reference first.

Here is a small sample of ones I will actually use regularly:

  • HTML

  • CSS

  • JavaScript

  • Prototype

  • jQuery

  • Ruby Standard Library

  • Ruby on Rails

  • Erlang

  • MySQL

  • PostgreSQL

  • Selenium


Plus gotAPI is a domain name I can probably remember. That should keep me from several pointless button mashing Google searches per hour just to end up back on the same sites that gotAPI is already linking to.

Monday, January 14, 2008

Beware Of The Merb

Apparently the Merb team was not yet satisfied with just having created a better Rails than Rails itself. Now, they are going after even more conceptual high ground, and creating an even more flexible web development paradigm that incorporates many of the great ideas percolating around the mongrel community.

According to Yahuda Katz, the next version of Merb will completely revise the existing Merb framework, in order to provide for many more ways to utilize it. He has an excellent writeup about what they are up to, and it sounds really cool.

The upcoming Merb 0.9 will break Merb into two parts: merb-core, and merb-more. merb-core will be a separate gem based on Rack, and as such will be able to plug into any web server like mongrel, evented_mogrel, thin, or even the venerable WebBrick. With this stripped down merb-core, you could create mini one file applications like those that you might been thinking of doing with Sinatra or Camping. Back to the Merb roots, if you will.

The other part of the new Merb, is the merb-more gem, which supports a more complete application structure like Rails or the current Merb. Combine this with a bunch of plugins, and the new Merb sounds to be an excellent way to really recombine elements to create an application.

I will be checking it out as soon as practical... stay tuned for more Merb.

Saturday, January 12, 2008

On The Grid With EC2

Lately, I have had a chance to get seriously into Amazon's Elastic Compute Cloud (EC2) service. I doubt any reader of this blog is unfamiliar with the existence of EC2, but many of you have probably not even gotten to the tire kicking stage, like I had been until recently.

Even after attending several sessions about Amazon's EC2 at RailsConf 2007, I still had only a very general idea about the service. However, it is true that there is no substitute for experience, and now that I have finally been getting hands-on, I am pretty excited about what you can do with it.

A client with a pretty complex Ruby on Rails application needed to create a processing farm for doing video conversion, as well as serving up the resulting video files. Sounds like the perfect application for Amazon's utility computing services. I dug in to the myriad of online sources of information available...

I decided to base my Amazon Machine Image (AMI) on Ubuntu 7.1. Oh, Ubuntu, such a modern operating system you are! That turned out to be a very good decision, and apt-get was quite co-operative getting the myriad of prerequisites my open source video processing farm would require.

I also decided to base my upload processor on Sinatra. My application's entrypoint is a single stateless call, but there are lots of these calls, and each requires a bunch of intensive back-end processing. Something nice and multithreaded, like some kind of mongrel handler, was called for. In this case, even Merb seemed like it was too heavyweight!

Luckily, I had colleague Ari Lerner available to help me strap Sinatra into my processing farm, who proved to be indispensable. We ran into some issues with Rack, which I am sure Ari will be blogging about. Thanks, Ari, you are the man.


Some lessons learned about working with EC2 and S3:

  • When you can launch a new instance whenever you want, you can really work on your machine configurations in an iterative way. Treat your AMI like source code, and don't be afraid to bundle and upload iterations of the AMI as you go along. If you mess up something, you will be glad you did. And there is no bandwidth charge between EC2 and S3 so go ahead, pile it into S3! At $0.15 per GB-Month of storage used, you cannot afford not to.


  • Amazon provides very complete instructions on how to create an image. When you are "developing" an AMI, by iteratively modifying a running instance, and re-bundling and re-uploading, you can skip the step of uploading your keys. However, you will need to delete /mnt/image before you can re-run the "ec2-bundle-vol" utility, or else you get an "the specified image file /mnt/image already exists" error.


  • You can get DRY with your AMIs. You can use a single AMI, and pass in launch parameters to set various configuration settings. For example, when I launch a processor instance, I use my main AMI and just pass in the required launch parameters to tell it if is staging or production, and which pool of processors to join itself to. And how do you retrieve this individual instance data at runtime? You use a REST call to get it. Neat!


  • At some point, I did something wrong with the code that generated keys for each file I was saving to S3, which in S3 corresponds to the path and file name. For whatever reason, it messed up, and I could not even delete the S3 objects using the S3 Firefox Organizer! Fortunately, the somewhat ugly, but much more functional Bucket Explorer was able to get rid of the offending files.


  • To really take advantage of the distributed nature of the solution, I decided to use a client-side load balancing scheme like that described by Lei Zhu in this article.

    The solution described does load balancing without a separate load balancer. It accomplishes this as follows: when a new processing node comes online, it registers itself by saving its name into a special bucket. Any server listed in this special bucket is available to serve requests. Add in regular peer to peer checking to verify that a node has not gone offline, and the peer removes it from the bucket. If that node, or a replacement, comes online, it will register itself. And so on... Zhu's solution is both effective and minimalist.

    As I said, the solution proposed at the end of the article was really cool, but no actual code was provided, since it is part of what appears to be the codebase for the author's startup company. So, I decided to implement it myself, which proved to be really fun and easy. A fully Ruby-based client side load balancer for EC2 is a pretty useful thing to have around. If anyone else is interested, I will publish as a gem or something.



We are not quite finished with our video processing farm, but it is almost there, and the results are a surprisingly small amount of code. I am been extremely impressed by the relative ease with which we have put together a pretty sophisticated solution.

Grid computing... it's not just the future, it's the present.

Friday, January 11, 2008

Making S3 Folders In Ruby

Amazon's S3 storage service is a really cool way to store and serve up massive quantities of data. Interestingly, it is more like a database than like a file system. Despite the convenience of referring to an object like "/path/to/thing.jpg" S3 really does not have any separate objects for "/path" or "/path/to". In fact, neither "/path" nor "/path/to" even exist.

This is why, when you store an S3 object, the name it is given is called "key" instead of "filename". It functions like a database key, returning a file. However, as very "ultra hipster Web 2.0" as this may be, it is still convenient to browse a large collection of files by using a familiar directory/sub-directory/etc.

In fact, all of the S3 utilities that I use allow you to create a folder inside of a bucket, and sub-folders inside of that etc. But I did not see any programmatic facility for creating a folder independent of any object inside of S3. If you have been paying attention, you remember that in S3 there is no such thing as a directory! So how do these nice GUI browsers do it?

I did some Googling, but no luck, beyond "it couldn't be done". Since I had two different programs that already did it, I knew THAT wasn't the case. It took a little old-fashioned investigation... I looked directly at the output from a query to a bucket that had the little folders in them already.

Lo and behold, it turns out, they cheat, by creating a specially named object for each "directory". For a directory named "/path", you would create an object with the key "path_$folder$", and for a directory named "/path/to", you create an object with the key "path/to_$folder$". Then to get a directory listing for "/path" you just do a query on S3 for all object whose key starts with "/path". Ignore any objects that end with "_$folder$" and there you have it: S3 folders.

I decided that it would be nice if the aws/s3 gem would support this foldering the same way that copying a file within a file system does: if the enclosing directories do not exist, they are created before the file copy.

Thanks to the beauty of modern dynamic languages, I was easily able to put together a little monkeypatch for aws/S3 to the S3Object class, that handles this.

# This is an extension to S3Object that supports the emerging 'standard' for virtual folders on S3.
# For example:
# S3Object.store('/folder/to/greeting.txt', 'hello world!', 'ron', :use_virtual_directories => true)
#
# This will create an object in S3 that mimics a folder, as far as the S3 GUI browsers like
# the S3 Firefox Extension or Bucket Explorer are concerned.
module AWS
module S3
class S3Object
class << self

alias :original_store :store
def store(key, data, bucket = nil, options = {})
store_folders(key, bucket, options) if options[:use_virtual_directories]
original_store(key, data, bucket, options)
end

def store_folders(key, bucket = nil, options = {})
folders = key.split("/")
folders.slice!(0)
folders.pop
current_folder = "/"
folders.each {|folder|
current_folder += folder
store_folder(current_folder, bucket, options)
current_folder += "/"
}
end

def store_folder(key, bucket = nil, options = {})
original_store(key + "_$folder$", "", bucket, options) # store the magic entry that emulates a folder
end
end
end
end
end


Sure, you can have the best of both worlds: massive virtual storage, and a convenient directory-like structure. And now you can have it with your favorite Ruby S3 library.

Happy storage!

And Here Comes The Money...

I read with great excitement that Engine Yard, my favorite of the Ruby-centric hosting companies, was taking in a round of $3.5 million from Benchmark Capital. I am a big fan of Ezra, and the rest of the crew, and the whole waiting list thing for getting a new slice setup has been a big inhibitor of their growth.

Funny, however, the press coverage has called EY a "Ruby on Rails hosting company". Yeah, sure, they are expert in RoR, no question. But the REAL stories there are Merb and Rubinius, and the press has not even caught a clue yet. Obviously Benchmark got it.

Congratulations, guys!

Thursday, January 03, 2008

Money In The Ghetto

I keep thinking about Zed Shaw's vitriolic (and newly updated) posting, and one particular aspect about it that seems to bother me. One way of looking at a ghetto is that is keeps people in. Another, is that is keeps outsiders away. In either case, it is an economy, like most any other. And like any economy, there are winners and losers.

What exactly is Zed complaining about? That the overall level of technical competence is very low, even among many self-proclaimed developers? That the industry has lots of hustlers and scammers? That the MAN is keeping us down and holding back our progress? I am just curious, what was the ideal environment that Zed was waxing sentimentally about? Oh yeah, developing software for the NYC Department of Corrections. Hmmm, time for a gratuitous link about the prison-industrial complex.

Ahem, back to whatever point I was trying to make. Some people look at the folks who are collecting recyclables out of the trash as disgusting. Myself, I see them as micro-entrepreneurs. It is a desirable occupation? Of course not. But it is an alternative to the corporate/governmental control structures.

I can certainly understand Zed's frustration with the relatively small amount of influence developers have in most development projects, and how many shysters are looking to exploit someone. But this is not something unique to any particular industry. It has to do with human nature, and let's not think for a minute that anyone is immune.

The "ghetto startup" mentality has certain advantages than the entrenched corporate interests, because in the creative chaos there is opportunity for the individual entrepreneur to do something independently from the established control systems. Is the Ruby on Rails community a ghetto? A shantytown? Or is it a successfully growing colony of ingenious social anarchists, and the inevitable hangers-on, sycophants, and moochers that follow success?

So, let me complete this metaphor. I, for one, am not going to complain too much about the stupid A & R execs and greedy managers that are hanging around the clubs signing anyone in sight. Nor am I going to complain about how so many artists are stealing my sound. Instead, I am going to sell mix tapes out of the trunk of my car, and just try to get paid.

Tuesday, January 01, 2008

Zed Is Mad

Zed Shaw has always been a rather curmudgeonly figure. I find him smart and hilarious, but of course many are rather insulted by his "tell it like he $%#@! well sees it" style. To me, Zed is like the Hunter S. Thompson of our community. The more your believe your own BS, the more he pisses you off.

Like Hunter S., Zed is a put up or shut up kind of person. Admit it, if you are reading this blog, you probably are running your vast empire on top of his code, while gleefully taking all credit yourself. But hey, Zed is just that kind of guy.

He also reminds me of a guy I used to work with long ago, who among other things had a masterfully inventive style of invective that could, like Zed, "blister the paint off of a bulkhead". They both have sharp minds, with a very low tolerance for mental laxity. They also both play guitar.

But one would be greatly mistaken to ignore the rant of such a mind, too easy to dismiss it as mere ravings. Zed chose to end his year with a wide-ranging assault against the "Rails Ghetto". It is a pretty interesting read... Are you afraid now to look? Perhaps you should be. But look anyhow. Then decide what you think.

Wednesday, December 05, 2007

Rubinius Maximus

I got a little excited when I read of the team assembled right now working on Rubinius up at Engine Yard in San Francisco.

After following the Ruby VM coopitition for while, and then seeing the Rubinius crew in full effect at RubyConf 2007, I am more convinced than ever that we are going to see some SERIOUS code coming out of these guys.... and assembling them all in one place is the best way to do it. Props to Engine Yard for making it happen. Get the throne ready, because the inheritors of the Ruby Imperium cometh.

Hail, Rubinius!

Wednesday, November 21, 2007

The Eyes Have It

Software usability has really benefited from the latest and greatest digital technology for eye tracking. If you are not familiar with eye tracking, it is exactly what it sounds like: a camera watching where the user's eyes are focused, and matching that to the screen to identify what the user is REALLY looking at, for how long, and in what order.

Here is a really great summary called "Scientific Web Design: 23 Actionable Lessons from Eye-Tracking Studies" that collects information from several different studies, and packages it up into something pretty, dare I say it, usable.

It is really worth it to read the whole thing, and it is pretty short. Here are a few highlights that got my attention:


  • Text attracts attention before graphics

  • Fancy formatting and fonts are ignored

  • Type size influences viewing behavior

  • One-column formats perform better in eye-fixation than multi-column formats

  • Lists hold reader attention longer

  • Navigation tools work better when placed at the top of the page



There is so much more to UI than drawing a pretty picture. Applying some science to the art of user interface design can result in something truly beautiful.

Monday, November 19, 2007

Werewolf vs. Vampyre

I had read with mild amusement the minor dustup over the craze of Werewolf players at RubyConf 2007. If you don't know what it is, you can read about it here.

Some people just really enjoy playing social games. Let's call them the Werewolves... you know who you are, even if the rest of us do not.

Other people, however, view RubyConf as a place to get together with the other commiters on their beloved project, stay up all night, and crank out a new release before their presentation the next day. Let's call these people the Vampyres... subsisting on mysterious red liquids, and notable for the pallor of their skin.

So what is the problem? Can't we all just get along? Not really, cause these two sub-species have very different priorities and modus operandi. Werewolves come out in droves when the time is right (full moon). They operate as a pack, sniffing out things and then chasing after them collectively.

The Vampyre is by nature a bit more cliquish. You simply cannot have a pack of wild creatures committing patches without *some* kind of arcane ritual involved. You can call it merging branches if you want. There is usually a coven of Vampyres, with a charismatic leader surrounded by younger creatures.

I go to a conference to hang out, drink a few beers, and then go to bed to rest from the inevitable time zone changes. If I want to get into a big social hoopla, I just go to soccer practice. On the other hand, if I want to stay up all night programming in a group, I can certainly go do that whenever I want. Personally, I do not find group programming at all efficient, but if someone else does, go for it.

I feel like a covert human thinking he is hidden among these undead creatures. If the Werewolves and Vampyres want to get together in order to get down, by all means they should. Just don't get stuck in the middle!

Sunday, November 18, 2007

RubyConf 2007 - Day 3

As day 3 of RubyConf 2007 began, the breakfast buffet had to remind us of its presence. This time, it was the main sound system that was taken out by the ultra-powerful toasters. When Dr. Nic was asked if he wanted to get started anyhow, he had to give two of his charmingly nasal "No" rhymes with "Pow" before MC David Black caught his meaning. This gave some of us a moment to try to catch up on the flurry of RubyConf blogging. Not that you could tell that from the extreme lateness of this post. But enough of my feeble excuses.

Finally, Dr. Nic took the stage, and gave an entertaining if kitschy presentation of his new RubiGen generator to make generators. The whole "A-team" gimmick was over the top enough that Dr. Nic himself admitted by the end how he looked forward to retiring it. All I can say is "curse you for planting that theme song in my head for over an hour". On a better note (ouch!) this is for sure some useful stuff, and I will no doubt be doing some "generatin'" of my own coming up soon.

Next up was "Behavior Driven Development in Ruby with RSpec". Although the presentation was not as flashy as the first, it was full of great information presented by smart guys who really know their stuff. I did not know Dave Astels, and although I have spent some time hanging out with David Chelimsky, I don't know him half as well as I would like to. Watching their live demo of ping-pong programming on stage made me wish that I had someone really, really good to pair with these days. It looked fun!

For a former Fitnesse junkie like myself, the syntactical sugar applied to testing of requirements that is Behavior Driven Development using RSpec is really appealing. I really don't know why some really smart people like Chad Fowler and Ryan Davis are not into it. I suppose that I have spent a lot of time with trying to sync up a customer's need with some custom software that was being written, and so the merger of domain specific languages and executable specifications is just particularly compelling.

The last of the three main sessions was Jay Phillips presenting "Adhearsion - Sane VoIP Development". Way back when, I did some telephony stuff on ancient evil AT&T System V boxes, so I have followed from afar the wild and craziness of VoIP with the jaundiced eye of one who has gone there before, and came back having lost half of the party. Poor Vonage... ahem. That said, the Adhearsion project taking a Rails-like approach to the stinking morass that is anything related to telephony is rather ingenious. I think much of the crowd will never use any of this stuff, but it was really neat. I wish Jay luck in his quest!

After the main presentations, I decided to keep close to the cutting edge, and see what the Google Summer of Code hath wrought. Amusingly, I must not have been the only one to lack major interest in the other sessions, cause the Goog room was full up on the "everyone who is anyone in Ruby" crowd. Can you say "time to catch up on feeds"?

Of the Google SOC projects, I cannot remember much. I was most impressed by one student's charming honesty. It would seem that the project hadn't really gone all that well, and the work produced didn't seem like anything usable. But he had learned quite a lot. I think we often forget the value in so-called "failure", cause we of course only extol the virtues of success. But Edison's remarks on failure are instructive, and I took from this kid that he was going to be a lot more ready for real-life programming challenges as a result of his experience. I was a lot more impressed by that than some well-crafted but uninteresting code library that I will probably never use.

The last session of the day for me was Aaron Bedra's extremely cool "Sploitin' With Ruby". It you do not know about Metasploit, it is a security research nee hacking tool, that is written almost entirely in Ruby. Taking an open-source, very plugin-oriented approach allows security professionals and outgunned system administrators to try to keep up with the R & D budgets of black hats, who these days have major economic incentives to hack your systems. Anyone who knows anything about security knows that these is no such thing as a secure operating system. That said, it was pitiful how easily you could probe for these exploits using Metasploit, without even knowing a fraction of what would be required before the invention of such tools.

I just hope a bunch of the people who were making dumb comments in the room understand that breaking into your own computers to test them is smart, and a great way to harden your defenses against various nasty people. Breaking into OTHER people's computers is a recipe for a stay in federal prison.

After the fun and games, I had to join the throng of taxi-seekers and head for the airport. RubyConf 2007 had been great, but now it was time to get back to the enormous piles of work that had only grown in my absence. RubyConf is a fantastic fun time, and a real inspiration to many of us. I will most certainly be back again next year, assuming that my finger is quick enough on the mouse to grab a seat.

Tuesday, November 06, 2007

RubyConf 2007 - Day 2 - "The Ruby VM Smackdown Begins"

As the sun rose over the hills of North Carolina, the quiet betrayed a seething fire blazing in the hearts of three development teams. "Three teams enter, one team leaves!" Yes, I am talking about the main event, people, the one, the only, Ruby VM Smackdown! The room was jam packed, the anticipation was high.

As good fortune would have it, I was sitting right next to the head of the team who was my personal favorite to win the day. Yes, I am referring to Evan Phoenix, leader of Team Rubinius along with co-conspirator Ryan Davis. You should have seen the look at their faces when the JRuby team showed the Rubinius RSpec test suite as part of their demo! But I am getting ahead of myself...

I like the underdog in a fight, when the underdog is tough, and under-estimated by their opponents. On one side, the resources of Microsoft, on the other, the full power of Sun. And then, THE LADS. If you don't want to see that one go down, you have no passion for the cutting edge of innovation. And if you do not know about the history of innovation in the software industry, you might miscalculate the odds. Gentlemen, to your corners... I want a clean fight!

MC Chad Fowler got up, and gave a brief intro to the show. "We are about to see what Matz called 'wonderous' last night," he said. And it was true.

First up, was John Lam of Microsoft with IronRuby armed with "State of IronRuby".

Next, Charles Nutter and Thomas Enebo of Sun with JRuby using "Ruby for the JVM" style.

Last, the challenger, Evan Phoenix with Rubinius wielding "Rubinius 1.0".

Wow. Bread and circuses, indeed!

I will be posting individually about each of the Ruby VM contestants, and will update the above links when I am done...

After all that excitement, the crowd was starved. We shuffled out to eat our lunches, and converse on all we had seen. From everyone I spoke with, the mood in the crowd was firmly in the Rubinius corner, with a close second to JRuby, with third place probably going to YARV. Hardly anyone I spoke with at RubyConf had any interest in using IronRuby at all!

That is to be expected from a conference like RubyConf, well known for its strong ABM (Anything But Microsoft) attitude, which is pretty unfair. That said, I think the uptake in the .NET community will be the measure of the success of IronRuby, not whether they can get the typical RubyConf attendee to switch back to Windows.

In the afternoon, I got to see some great sessions, from:

"Refactotum: Ruby" - Stuart Halloway
"Maximizing Productivity" - Eric Hodel
"Mac OS X Loves Ruby" - Laurent Sansonetti

I will be posting individually for each session when I get a chance, and will update the links here.

Once the afternoon's sessions had wrapped up, a large group of us overran a local BBQ joint named Mac's, with tasty BBQ, a great beer selection, and a bunch of Harleys in the parking lot. Despite our somewhat atypical appearance (nerd chic) for NC, we were welcomed warmly by the locals. There must've been 30+ people from RubyConf there, it was great!

We then returned at the perfect moment to hear Matz's keynote speech. And it was good. Really good. Matz is charming, and quite funny. His wit was so much better able to emerge in a forum where he was simply presenting, rather than the somewhat less successful "town hall" format that had been attempted the evening before. I have a separate posting with his remarks which will be up later:

RubyConf 2007 - Keynote by Matz

Once the keynote had ended, I just had to go up and shake the man's hand. I know it may be corny, but I really did suddenly appreciate what he really does, which is to inspire the community. People keep looking to Matz for all the answers, but the answers are up to us, my friends. No superheros, remember?

Afterwards, I want to the legendary RejectConf, held right next door. Don't ask me how I wedged my way in, but I did it. To everyone who's toes I stepped on: sorry! There was a fun series of lightning talk (5-10 min) presentations of pretty much brand-new stuff. The beauty of RejectConf is its appeal to the ADD'd-out techno-junkie: every few minutes something else. I will be posting a rundown of RejectConf when I get a chance here:

RubyConf 2007 - RejectConf

RejectConf was really a great highlight of RubyConf. Once they kicked us out, the entire crowd immediately migrated directly next door to the hotel bar where we drank beers and chatted loudly about techno-babble to our great enjoyment. I staggered up to my room, to rest up and prepare myself for Day 3.

Monday, November 05, 2007

RubyConf 2007 - Day 1 - "Advanced Ruby Class Design" - Jim Weirich

Jim Weirich is a very smart guy. So smart that his presentation was not about complicated classes, but about Ruby itself and how to take advantage of it to simplify things. Jim's background in computing is long and varied, something like a history lesson in programming languages. Here is the abbreviated list:

FORTRAN > C > Modula 2 > C++ > Eiffel > Java
and in parallel to this:
LISP > FORTH > TCL > Perl

Jim got started programming taking an introduction to FORTRAN class that just so happenened to be taught by Daniel Friedman, author of "The Little LISPer". As such, they studied LISP for the first half of the semester. They did finally get around to FORTRAN, where Jim learned firsthand the adage:

"A real programmer can write FORTRAN (Java) in any language"

Jim took us thru three examples that illustrate some very cool techniques to use as part of elegant class design in Ruby.

Box 1. Rake::FileList
Everyone knows and loves Rake, right? Rake::FileList is like an array but:
- can init with GLOB (an array of filenames, created using a pattern match expression)
- has a specialized to_s
- has extra methods
- uses lazy evaluation

In his first cut, Jim derived from Array:

class FileList > Array
...
end

Here is the first implementation for FileList:

class FileList > Array
def initialize(pattern)
super
@pattern = pattern
@resolve = false
end

def resolve
self.clear
Dir[@pattern].each do |file|
...
end
end
end

The problem is this:

f1 = FileList.new("*.c")

won't work, cause we never call "resolve". What we need to do is to do some lazy loading to "auto resolve", like this:

def [](index)
resolve if ! @resolve
end

Lots of methods need to call resolve in this manner... which is a problem that Jim solves later using a little metaprogramming.

But there is a another problem with the current implementation. This is OK:

f1 = FileList.new('*.rb')
f1 + ['thing.rb']

But this is NOT:

f1 = FileList.new('*.rb')
['thing.rb'] + f1

Why? Because the + method requires passing a literal array to it as an argument, not an object of class Array. If only there was a way for an arbitrary object could indicate that it wants to be treated like an array... ah, but there is! The "to_ary" method was designed to do exactly this. The problem is you cannot call the to_ary method on an Array. The solution is not to derive the FileList class from Array, but instead to use the "to_ary" method to access an Array that is encapsulated into the FileList class.

Another shortcut is instead of calling resolve on each method, using some metaprogramming to add the "resolve" call to every method that might need it, like this:

RESOLVING_METHODS = [:this, :that]
RESOLVING_METHODS.each do |method|
...
end

The big lesson here is when trying to mimic a class, use "to_ary" and "to_str" rather than inheritance.

Box 2 - The Art of Doing Nothing
Builder is a very cool library which is part of the standard Ruby library to create XMl files, but using a friendly Ruby syntax. Did I mention that Jim is the original creator of Builder? Here is an example of Builder in use, if you are not familiar with it:

xml = Builder::XmlMarkup.new(:indent =>2)
xml.student {
xml.name("Jim")
xmp.phone_number
}

Builder uses method_missing to construct tags. This works really well... except what happens if you try to use it with a predefined method? method_missing will not work anymore, since the method is actually there.

Jim solution is to "inherit from Object without actually inheriting from Object", a class he calls BlankSlate. We want to have our Builder class inherit from BlankSlate, instead of Object.

class BlankSlate
instance_methods.each do |method|
undef_method(method)
end
end

That does indeed get rid of all of the methods on the class. But that does not work, because there are some internal methods that Ruby needs that we do not want to get rid of, so we extend the class to this:

class BlankSlate
instance_methods.each do |method|
undef_method(method) unless name =~ /~__/
end
end

This is not the only problem, however. Since in Ruby classes are open, we can also extend them using Modules.

require 'blank_slate'

module Kernel
def name
"hi"
end
end

xml.name("Jim")

class BlankSlate
def self.hide(method)
...
end

instance_methods.each do |method|
undef_method(method) unless method =~ /^__/
end
end


module Kernel
class << self
alias_method :original_method_added, :method_added

def method_added(name)
result = original_method_added(name)
BlankSlate.hide(name) if self == Kernel
result
end
end
end

We will need to do something similar for Object, in order to avoid the same problem. So are we done? Not quite, there is still one more thing... but I didn'y quite catch what it was! I will update this when Jim puts his slides up:

require 'blank_slate'

module Kernel
def name
"hi"
end
end

class Object
include Name
end
...
xml.name("Jim")

Hint: Use #append_features to modify open classes.

Box 3 - Parsing Without Parsing
ActiveRecord is a wonderful abstraction to use, but why is it that we use such a non-Ruby-like technique to select records. For example, we would use this in Rails:

User.find(:all, :conditions => ["name = ?", 'jim'])

Versus using a more standard Ruby language enumerable approach, like this:

user_list.select { |user|
user.name == "jim"
}

Wouldn't it be nicer to do something like this:

User.select { |user|
user.name == "Jim"
}

Jim starts out with a naive implementation, like this:

class User
def self.select(&blk)
find(:all).select(&blk)
end
end

There are several problems, not the least of which is that the above code is far from efficient. A large set of results will use an enormous amount of memory.

Jim then goes on to show a properly "magic" implementation:

class User
def self.select(&blk)
cond = translate_block_to_sql(&blk)
find(:all, :conditions => cond)
end
end

How to implement the magic translate_block_to_sql method?
- write a parser yourself
- Use Parse Tree (Ambition project)
- Just execute the code in the block

As one might suspect, the answer is of course "just execute the code". In other words, create appropriate methods that are called when the block is executed to return the correct SQL conditions clause for the query. Let me warn you, dear reader, that I typed as fast as I could, but some of the code examples here are a little incomplete. As soon as Jim posts his slides online, I will revise and complete them.

class User
def self.select(&blk)
cond = translate_block_to_sql(&blk)
find(:all, :conditions => cond)
end

def translate_block_to_sql(&blk)
instance_eval(&blk) # this is not exactly the code, but I couldn't type fast enough!
end
end

class MethodNode < Node
def to_s
...
end
end

OK, now what about the "==" operator?

class Node
def ==(other)
BinaryOpNode.new("=", self, other)
end
end

class BinaryOpNode < Node
def initialize(operand, left, right)
@operand = operand
@left = left
@right = right
end

def to_s
"#{@left} #{@operand} #{@right}"
end
end

class LiternalNode < Node
...
end

class StringNode < Node # puts quotes around the string for SQL query
...
end

Do not use a case statement to differentiate between types. Instead open core classes, like this:

class Object
def as_a_sql_node
...
end
end

class String
def as_a_sql_node
...
end
end

Be careful how you name methods to avoid collisions.

Possible problems? Literals on left, because "==" is commutative. The solution is to use "coerce" method to handle numeric operators.

More possible problems?
"&&" and "||" operators cannot be overridden in Ruby cause they have short-circuit semantics in the Ruby language interpreter itself. Perhaps & and | instead? Too bad, because we have to write "special" semantics. Also "!" and "!=" cannot be overridden in Ruby

The ruby "criteria' lib already implements some of these ideas.

Conclusion
One important lesson to take away, is that programming languages really shape the way we approach problems. Learn the corners of whatever language you are using to take full advantage of it. Don't be afraid to think outside the box of past experience...

Jim was an amazing and dynamic speaker. All I can say is Joe O'Brian and the people at EdgeCase are very fortunate to have him around.

RubyConf 2007 - Day 1 - "What Makes Code Beautiful" - Marcel Molina

I remember Marcel Molina from the first RailsConf, when the Rails core team was introduced to the audience. What had impressed me at the time, besides his cool glasses, was the fact that Marcel comes from a literature background.

That makes his take on programming in Ruby very interesting, because he approaches it from an aesthetic perspective, not just a functional one. To Marcel, code must achieve both, for it to be considered beautiful.

What Is Beautiful?
Here are some historical definitions of beauty:
Plato - "The ability to grasp mere appearances cannot lead to adequate understanding. At its worst, the appreciation of beauty can mire us in the world of sense experience... but at its best it can lead to the understanding of goodness."
Rousseau - "I have always believed that good is none other than Beauty in action, that the one is inextricably bound up with the other and that both have a common source..."

There is something deeper than appearances that makes something beautiful.

Looking at human language, meaning is often implicit in sentences. Normally in software, using rhetorical effects is considered bad, unlike literature.

Ruby had an appeal to Marcel as a language, as a visceral response to the language itself. But why? Elegance and beauty are used to describe Ruby code, but what does that mean?

Settle On A Working Definition
Marcel goes with Thomas Aquinas for a working definition of beauty requiring three qualities:
Proportion - Economy of size & ratio of parts
Integrity - a glass hammer may look good, but it doesn't work for a hammer - to have integrity, a thing must fit its intended purpose
Clarity - something should be simple and clear. There is a big difference between sophistication and complication

Apply definition of beauty to software
Marcel provided a contrived example, a case study that created a Coercion class to "help" when parsing XML. In his example, he starts with a 25 line class with three methods and such obfuscated code that even the author admitted that he does not understand it. He then proceeds to show how it can be reduced to 12 lines of reasonably clear syntax.

To achieve beauty, we need checks and balances between each of the qualities of beauty - each is necessary, but none are sufficient themselves alone.

Does code quality relate to beauty?
Marcel cites Kent Beck's "Smalltalk - Best Practice Patterns" as a strong influence. The book is full of pearls of wisdom like "most good Smalltalk methods fit into a few lines". After reading the book, Marcel realized that it was a set of descriptions of the elements that make Smalltalk code beautiful.

How Is This Useful?
We may not be very impressed by the beauty in a case statement. But imagine programming before the 'if' statement. 'If' is way better than assembly code... there is a relativity to what makes code beautiful. Today, Ruby is considered beautiful. In the future, we may consider it as ugly as 70's assembly code based on the aesthetics available to us.

"An expert is someone who has made all the mistakes that can be made in a very narrow field" - Neils Bohr

Ruby is optimized for beauty.
- try to imagine better modes of expression
- violations of beauty rules reveal mistakes
- do enough of this and you will innovate

Sunday, November 04, 2007

RubyConf 2007 - Day 1

Where RailsConf is growing to become a spectacle, RubyConf still has that special, small feeling of sharing. It is like the difference seeing a really great band perform at a small club before they get "discovered", and then seeing them again in an arena. Still the same band, but a much different experience. Being here at RubyConf 2007 brings back the joy of hacking Ruby code for its own sake, not just creating the latest and greatest social web application. Although Rails is Ruby, Ruby is not just Rails.

As I arrived for the opening address, I immediately ran into many Ruby friends, starting with Michael Hartl, author of the popular Rails book, RailsSpace. Michael had kindly saved me a seat up front and center. Wow, thanks Michael!

Despite losing our electrical power (due to the ultra-powerful toasters outside interacting badly with the dozens of daisy-chained power strips?), the proceedings were ready to get underway. For those who have not followed the history of RubyConf, this is the 7th annual Ruby conference! According to David Black, who gave the brief introduction, the attendance this year is 15 times the size of the first conference. That is a lot of toast.

And this is going to be a lot of text. Thanks to feedback from many of you, my wonderful friends, I am splitting my RubyConf 2007 in-depth coverage into separate smaller postings. I will post links to each individual session, as soon as I complete them. Here is what I attended on day 1:

RubyConf 2007 - Day 1 Sessions
"What Makes Code Beautiful" - Marcel Molina
"Advanced Ruby Class Design" - Jim Weirich
"Controlling Electronics with Ruby" - Ben Bleything
"Hurting Code For Fun and Profit" - Ryan Davis

After the day's sessions, I went to a very nice dinner with a group of new friends including "The Ruby Way" author Hal Fulton, and David Koontz, creator of a slick new tool for programming Swing entirely in Ruby called Monkeybars. Thanks for a nice time everybody!

We then hurried back, just in time to catch the "town hall" with Matz. Perhaps it was all the rushing around, but to me, the town hall was too chaotic. I'm sure the Ruby Central people had a good concept in choosing that particular format, but I just think it worked out so well. Perhaps doing a town hall on the second night of the conference? Or perhaps just scrap the idea... I'm not sure, but it just wasn't that good, especially after some of the strong sessions we had seen earlier in the day.

Let me be clear that this was no fault of Matz, who was very gracious thru the whole thing, but I think there were too many people with too many different agendas and lines of questioning to pull it off.

After such a very full day of Rubyism, I went back to my room and crashed out, certain that Matz's keynote address the next evening would be much more satisfying.