Hashiness
Sunday, April 8th, 2007Back in college, the killer Intro to CS class used a home grown object-oriented version of Pascal. It was a bit like Borland’s Pascal, except it ran on Solaris and the IDE was about 100x slower. We quickly covered some programming fundamentals, then dutifully moved on to inheritance and polymorphism. One particularly grueling assignment involved writing a linked list where the nodes used polymorphism instead of conditionals.
Turns out that in the real world you never want to write a linked list with polymorphism, but the lesson obviously struck a nerve. Since then I’ve pretty much used objected oriented languages exclusively. For the purposes of this blog post I’m skipping over our flirtations with C and optimized MMX instructions at Strangeberry, as well as a nightmarish Perl project at Jobster.
I can finally report that my long honeymoon with OOP is coming to an end. These days, I use the Hash much more often than I use the Class. The Hash has a certain appeal that it’s hard to resist.
The Rise of the Hash
Maybe it’s because I spend so much of my time these days on data manipulation and deployment scripts. Maybe it’s frustration with poor design. Maybe it’s because machines have simply gotten fast enough to enable my inherent laziness. Maybe it’s because of YAML.
Whatever the reason, I simply love Hash tables. I can’t get enough of them. I use Hash tables for complex method arguments, just like the rest of Rails. I’ll use a Hash table instead of a Class for as long as possible, right up until I absolutely need to add a method. Hash tables are so syntactically light and malleable, it feels like a real sacrifice to switch to a full blown Class.
Ruby’s Hash
I especially love the somewhat obscure Ruby feature that allows you to attach a block to Hash. The block gets called whenever a new element is created. I talk about this a bit in my Ruby at 60 post, but I wanted to give a different example here. I often find that I need to partition a data set based on a key. Imagine a set of employees, each with a role:
employees =
[
{ :role => ‘ceo’, :name => ‘Mr. Burns’ },
{ :role => ‘underling’, :name => ‘Smithers’ },
{ :role => ’slave’, :name => ‘Homer’ },
{ :role => ’slave’, :name => ‘Lenny’ },
{ :role => ’slave’, :name => ‘Carl’ },
…
]
The following snippet breaks up the employees by role:
by_role = Hash.new { |hash, key| hash[key] = [] } employees.each { |i| by_role[i[:role]] << i }
We use techniques like this all over the place for managing data sets that aren’t in a database.
Hashiness
Using Hash tables allows me to experience a sense of satisfaction that I call Hashiness.
The authors of ActiveRecord clearly were going for Hashiness. Ditto for sessions/params in Rails. There are oodles of Classes in Rails that masquerade as Hashes. Many of the essential Rails methods take a Hash as a parameter, and I’ve lifted this pattern for my own work.
I claim that Hashiness makes me a more productive engineer, and makes Urbanspoon a better product. Are you getting enough Hashiness?