Design by contract for Ruby

Here's a nice little module Brian and I hacked together a few weeks ago. It adds basic design by contract capabilities to classes with a fairly clean syntax (yay for Ruby's flexibility!)

Take a look for yourself:

class Foo
   include DesignByContract

   pre(:sqrt, "value must be >= 0") { |v| v >= 0 }

   pre("divisor must be != 0") { |dividend, divisor| divisor != 0 }
   post { |result, a, b| a - b * result < 1e-3 }
   def div(dividend, divisor)
      dividend / divisor
   end

   def sqrt(value)
      Math.sqrt value
   end

   post(:sqrt, "error is greater than expected") { |result, value|
         result * result - value < 1e-3
   }
end


When the DesignByContract module is included in a class, the pre and post methods become available. The parameters to these methods are a symbol representing the method to add the pre or post condition to, the message to print if the condition fails and a block that implements the condition.

The method name and message are optional, though. If the method name is missing, the condition will applied to the first method definition following the pre/post declaration. Note that if the method name is present, the condition can be defined anywhere in the class definition, as shown in the example above.

The condition block receives all the arguments passed to the method it applies to. They must return a boolean value indicating whether the condition succeeded. A minor difference between pre and post blocks is that the post block receives the result returned by the method as the first argument. This makes it possible to validate the results against the inputs such as in:

post { |result, dividend, divisor| dividend - divisor * result < 1e-3 }


Get it here!

How it works


In a nutshell, the pre and post methods intercept the existing method using the technique I described a few weeks ago (i.e., no poluting the class' namespace with aliased methods). The new methods test the provided condition before or after delegating the call to the original method and raise an exception if the condition fails.

There is a small caveat, though. If pre/post are called before the method is first created, it cannot be intercepted. To get around this the module uses an alternative trick. Whenever the module is included, it hooks into the method_added callback of class it's included into. If pre/post are called and the corresponding method does not exist, the interception is scheduled until the method is added.

Indexed Search Engine 0.2.0 Released

The 0.2.0 release of the Indexed Search Engine is released. The Indexed Search Engine is a Ruby on Rails Engine which helps you to easily add quick indexing and search capabilities to your application.

Check out the project page for more info.

Rails: Why Use Anything Else?

From a friend who I've been working on a Rails app with:

I can't see why, if you were starting a new web app today, you would use anything else.

Enough said.

Addendum: This comment immediately started a discussion on why we didn't use Seaside, so it wasn't really enough said, but having written a metric ton of java apps on any number of different frameworks, I'm not going back to that world.

Neverending Bugs!

The last few days have served as a good reminder that, even with all of our cool new Agile programming toys, if you're trying to do something super cool that no one else has ever done before, sometimes this shit is still just hard.

Enterprise Software

“I think of the ‘Enterprise’ label as an excuse to deliver expensive and painful software over budget and late.” David Heinemeier Hansson

Wow – knocking over sacred cows for sure! Though, believe me, I’ve been involved in many an enterprise project that could fit that description.

Check the full article