Ruby on Rails, Io, Lisp, JavaScript, Dynamic Languages, Prototype-based programming and more...

Technoblog reader special: $10 off web hosting by FatCow!

Thursday, November 16, 2006

Context Switches

Joel Spolsky responded to Dmitri Zimine's article about context swtiching. Dmitri talks about the developer pains caused by context switches and how abusing context switching can lead to lower productivity and less code for your dollar. Joel's response is that if you work against context switching, you are not being agile. He backs his reasoning with an example: a huge bug was discovered that crashed the browser for a loyal customer, so their 2.0 release was held back to fix this.

First of all, Joel declares that having two week release cycles is not agile, which I think is a faulty assumption to start with. Telling a client that they will have to wait two weeks for the feature of their dreams is not always the deal breaker situation Joel makes it out to be, in fact I would think most clients would be impressed if a company released a requested feature within two weeks.

More importantly, there is a huge difference between necessary and unnecessary context switches. The high priority bug fix that Joel mentions is indeed a good reason to switch contexts, however that doesn't mean that if some random person in Zimbabwe says that he wants them to add feature X before the next release, I would hardly think that would be a good reason to switch contexts and focus on X. There certainly should be some abstraction and safety nets in place to make sure that programmers switch context as little as possible but no less. To say, as Joel does, that a 30" monitor means that a great programmer should magically be able to switch context on demand for any reason is a gross over-generalization.

Abuse your car's clutch and it will eventually break, no matter how good of a car or how well you take care of the rest of it.

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!

Monday, November 13, 2006

Syntactic Vinegar vs. Syntactic Sugar

Syntactic vinegar is to punishing your dog for bad behavior as syntactic sugar is to rewarding them for good behavior.

I certainly don't want to be the dog being choked and scolded all day.

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!

A Fatal Flaw in Opinionated Software

David Heinemeier Hansson has written a lot about opinionated software and syntactic vinegar. At first glance, the term opinionated software sounds perfectly reasonable. It seems, at least to me, to mean that the software looks and acts in a certain way... it has opinions like DRY and convention over configuration. That is not what opinionated software means to David. To David, a piece of opinionated software is written in such a way that makes it easy to do things one way and ugly and difficult to do things another way.

What does this mean? Glad you asked. Let's look for example at the ActiveRecord find method.

User.find(:first, :conditions => "active = 1")
# => # "1", "active"=>"1"}>

User.find(:first, :with => {:active => 1})
# ArgumentError: Unknown key(s): with

Ok, so the find method does not accept the key :with. That is fine, but let's say you and I are clever hackers and we wanted to enhance ActiveRecord to accept the :with key in order to do some neat magic that reduces the amount of code we have to write. For a Ruby developer, this type of modification sounds like it should be easy, but this is what I found when I first looked at the Rails source.

def validate_find_options(options) #:nodoc:

options.assert_valid_keys([:conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from])


That is right, the keys were all hard coded, meaning that if I wanted to add my own :with key, I would have to completely overwrite the undocumented
validate_find_options method, which inevitably would break things down the line as Rails added its own new keys.

When I first saw this I thought to myself: ah, must be an oversight. I wrote a patch in a few seconds that abstracted the array passed to options.assert_valid_keys into something mutable. I submitted the patch and had a lengthy discussion with DHH in which I was slapped by the opinionated software stick. Apparently, David thought that if I wanted to hack ActiveRecord, I was going to have to be punished by writing ugly code. It was the "opinion" of ActiveRecord that people shouldn't add a key to the find method, so David intentionally made it much harder than necessary to accomplish.

That is right, this was not a simple oversight, this type of code was completely intentional. It is David's opinion that Rails be harder than necessary to hack around and play with. That if I was going to stretch the limits of Rails, take it places nobody else had thought of, that I should be punished for doing so, and that punishment is ugly code.

This is the fatal flaw of opinionated software... in order to make design decisions that limit people's ability to do things you don't think they should do, you must punish them. The form of punishment that David is interested in is syntactic vinegar, like having to override a method instead of append to an array.

The problem with this approach is that punishment is only appropriate for children and criminals. By actively working to make my life as a hacker more difficult, David is treating me like a child or a criminal. Saying either that I am not old enough to know what I am doing and must be punished for doing it, or that I am wrong to think that way at all. Punishment is a very dangerous tool to use because it is fundamentally condescending.

Rails is David's baby, so he can do whatever he wants to it, and that is fine, but to treat a seasoned professional as a child only goes so far in my book. Some might argue that it is for the greater good... that it makes people who don't know what they are doing write better code, keeps people in their place. First of all, the people who end up being punished the most are the ones who want to push the envelope--a beginner is never going to try to add a keyword to the find method. Second of all, I don't want to give up my work productivity for the productivity of those who do not know what they are doing, I want a tool that works best for me. Every time I run into "opinionated software" in Rails, it makes the back of my ears burn reminding me of how much I can't wait to find, start, or help the next generation of highly productive web development software.

Opinionated software is fine until you want to do interesting, new, and innovative things with ease. I am not interested in being treated like a child or a criminal for doing so, which means those opinions which David holds most dear are the ones that will eventually drive out the people that Rails initially attracted... the hackers, the innovators, the bleeding edge developers. Give us freedom or give us another tool that provides freedom.

As a side note, apparently I may have been the first but certainly not the last to complain about the particular form of syntactic vinegar presented with validate_find_options because I see now that they ended up abstracting it and you can now add accepted keys by modifying the VALID_FIND_OPTIONS array. If you would like to see my failed attempt over a year ago to add this feature, check out this ticket.

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!

Wednesday, November 08, 2006

Functional Programming in Ruby

In Ruby, iteration is done mainly functionally with methods like each and map. We call this type of iteration functional because we are passing a function to be called on each item in the collection.

[1,2,3].each { |item| puts item + 1 }

In this example. the function being passed is { |item| puts item + 1 }. In fact!

print_function = lambda { |item| puts item + 1 }
[1,2,3].each &print_function

Accomplishes the exact same behavior.

This is very much from the functional programing paradigm. Now, one thing that I can not stand to see in Ruby code is this.

def convert(old)
new = Array.new
old.each do |item|
new << transform(item)

The first hint that there is something wrong is the very odd call to return the new variable at the end of the convert method. It seems odd and awkward, and that is a hint that you are working against the grain. Here is how it should look.

def convert(old)
old.map { |item| transform(item) }

Or alternatively:

def convert(old)
old.map &method(:transform)

Notice how clean and beautiful this is. We are working with the grain of functional programming here. Not only that, but there is less to debug, less to maintain and it takes less time to grok what is going on.

If you want to learn more about the functional programming roots of Ruby, I recommend learning OCaml, I am really enjoying it.

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!


If you like this blog, you might also like top photography schools.