The three line rule

A frustrating couple days of coding has crystalized a new rule for me:

If you can’t demonstrate your new feature in three lines of code, you’re not done.

But it works from the client UI? Great. And it’s fully tested? Super! But you’re still not done.

If it took twenty lines of setup code to make the unit tests work, you’re not done. There should be a close to one-to-one correspondence between artifacts in the UI and artifacts in your codebase. Did you add a new command? There should be a single methodthat encapsulates that command. Did you add a new form? There should be a single classwhich can be instantiated in a valid state with a single constructor or factory call.

I’m not saying this just for the sake of style. This is for your own good. It’s so that six months from now, you can look at that feature on the screen and track it to a single point in the code. It’s so that when you’re training the new guy, you can open up a console and type three lines to demonstrate how that feature works. It’s so that when you write a conference presentation on your brilliant code, you can fit the examples on one slide.

Don’t just be a domain expert; be an API designer. A humane one. The brain you may save from imploding is your own.

I don’t have time to go into technical details, but the Facade pattern is your friend.

Is your keyboard jammed, or are you just writing Haskell?

I’ve been getting back into Haskell lately because I’ve been using the XMonad window manager, which is written and configured in Haskell. Haskell has always held a special place in my heart; I taught myself Haskell by plowing through the ironically-named “Gentle Introduction to Haskell” several years ago, and it taught me more about clean side-effect free functional programming than any amount of Lisp.

A programming language must be considered in the context of its community, and Haskell has an exemplary one. #xmonad is without a doubt one of the friendliest and most helpful channels on IRC, without any of the elite condescension one usually finds on channels devoted to hardcore geek tools like Emacs. I have come to believe, however, that this polite exterior conceals a deep and consuming madness.

I refer to the Haskell community’s addiction to defining operators. Haskell permits virtually any string of nonword characters to be defined as a new operator. This in itself is not a problem, but Haskell programmers seem not to have absorbed the lesson that just because you can, doesn’t mean you should.

To make my point, I call upon Mark Twain, somewhat paraphrased:

In my note-book I find this entry:

July 1. — In the hospital yesterday, an operator of thirteen characters was successfully removed from a patient — a web developer from near Baltimore; but as most unfortunately the surgeons had opened him in the wrong place, under the impression that he contained a stack trace, he died. The sad event has cast a gloom over the whole community.

That paragraph furnishes a text for a few remarks about one of the most curious and notable features of my subject — the length and obscurity of Haskell operators. Some Haskell operators are so long that they have a perspective. Observe these examples:

  • -->
  • < &&>
  • |||

These things are not operators, they are symbolic processions. And they are not rare; one can open an xmonad.hs at any time and see them marching majestically across the screen — and if he has any imagination he can see the banners and hear the music, too. They impart a martial thrill to the meekest subject. I take a great interest in these curiosities. Whenever I come across a good one, I stuff it and put it in my museum. In this way I have made quite a valuable collection. When I get duplicates, I exchange with other collectors, and thus increase the variety of my stock. Here are some specimens which I lately bought at an auction sale of the effects of a bankrupt bric-a-brac hunter:

  • .|.
  • < +>
  • >>>
  • ^>>
  • +++

Of course when one of these grand mountain ranges goes stretching across the LCD screen, it adorns and ennobles that coding landscape — but at the same time it is a great distress to the new student, for it blocks up his way; he cannot crawl under it, or climb over it, or tunnel through it.

[ad#PostInline]

The Three Virtues

So somewhere along the line this blog lost it’s tagline, making the title somewhat obscure. No, I didn’t name the blog “Virtuous Code” because I believe I’m a paragon. It’s a reference to a quote by Larry Wall in the the famous “Camel Book”:

“We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris.”

These virtues are elaborated on as follows:

Laziness
The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful, and document what you wrote so you don’t have to answer so many questions about it. Hence, the first great virtue of a programmer. Also hence, this book. See also impatience and hubris. (p.609)

Impatience
The anger you feel when the computer is being lazy. This makes you write programs that don’t just react to your needs, but actually anticipate them. Or at least pretend to. Hence, the second great virtue of a programmer. See also laziness and hubris. (p.608)

Hubris
Excessive pride, the sort of thing Zeus zaps you for. Also the quality that makes you write (and maintain) programs that other people won’t want to say bad things about. Hence, the third great virtue of a programmer. See also laziness and impatience. (p.607)

For more, see WikiWiki.

The quote has now been restored to its rightful place of honor, along with sundry other updates.

Using AlterEgo with ActiveRecord

François Beausoleil has a nice post up demonstrating “how to use AlterEgo with ActiveRecord”:http://blog.teksol.info/2008/12/09/how-to-use-alterego-with-activerecord.html. If you’re interested in introducing state-specific behaviors to your ActiveRecord objects, check it out!

[ANN] HookR 1.0.0

I’m pleased to announce the availability of “HookR”:http://hookr.rubyforge.org 1.0.0

h2. Description

HookR is a publish/subscribe callback hook facility for Ruby.

h2. What is it?

HookR can be understood in a few different ways.

  • If you are familiar with Events and Event Listeners in “Java”:http://java.sun.com/docs/books/tutorial/javabeans/events/index.html or “C#”:http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx; “Hooks”:http://www.gnu.org/software/emacs/manual/html_node/elisp/Hooks.html#Hooks in Emacs-lisp; or signals-and-slots as implemented in the “Qt”:http://doc.trolltech.com/4.4/signalsandslots.html, “Boost.Signals”:http://www.boost.org/doc/libs/1_37_0/doc/html/signals.html, or “libsigc++”:http://libsigc.sourceforge.net/ frameworks – HookR provides a very similar facility.
  • If you’ve ever used the Observer standard library, but wished you could have more than one type of notification per observable object, HookR is the library for you.
  • HookR is an easy way to add “Rails-style”:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html before- and after-filters to your own classes.
  • HookR is an “Inversion-of-Control”:http://martinfowler.com/bliki/InversionOfControl.html framework in that it makes it easy to write event-driven code.
  • HookR is a way to support a limited, structured form of Aspect Oriented Programming (“AOP”:http://en.wikipedia.org/wiki/Aspect-oriented_programming) where the advisable events are explicitly defined.

h2. What HookR is not:

  • HookR is not (yet) an asynchronous event notification system. No provision is made for multi-threaded operation or event queueing.
  • HookR will show you a good time, but it will not make you breakfast in the morning.

h2. Synopsis

  require 'rubygems'
  require 'hookr'

  class ZeroWing
    include HookR::Hooks
    define_hook :we_get_signal, :message

    def start_game
      execute_hook(:we_get_signal, "How are you gentlemen?")
    end

    def bomb(event, message)
      puts "somebody set us up the bomb!"
      puts "All of your hookrs are belong to us!!!"
    end

    we_get_signal do |event, message|
      puts "Main screen turn on!"
      puts "Cats: #{message}"
    end

    we_get_signal :bomb

  end

  zw = ZeroWing.new
  zw.we_get_signal do
    puts "Take off every zig!"
  end

  zw.start_game
  # >> Main screen turn on!
  # >> Cats: How are you gentlemen?
  # >> somebody set us up the bomb!
  # >> Take off every zig!

h2. Get it Now

Pull your hat way down over your eyes, drive over to the your local red-light district, and type:

sudo gem install hookr

For more information, check out the website: http://hookr.rubyforge.org

[ANN] fail-fast 1.0.0 Released

Number two out of three in my weekend releasing spree, I’m happy to announce the availability of “FailFast”:http://fail-fast.rubyforge.org v.1.0.0.


h2. Description

FailFast is a collection of assertion methods intended for lightweight contract checking.

h2. Installing

sudo gem install fail-fast

h2. Synopsis

  def try
    yield
  rescue FailFast::AssertionFailureError
    ""
  end

  include FailFast::Assertions

  try { assert(true) }            # => true
  try { assert(false) }           # => ""
  try { assert(nil) }             # => ""

  # We can check multiple values at once
  try { assert("foo", :bar, 42) } # => 42
  try { assert(1, 2, nil) }       # => ""

  # assert_exists only checks for nil-ness - false is OK.
  try { assert_exists(true) }     # => true
  try { assert_exists(false) }    # => false
  try { assert_exists(nil) }      # => ""

  # check further constraints after verifying the object is non-nil
  try { assert_exists(99) {|n| n > 100 } } # => ""

  # Assert that a collection is non-empty
  try { assert_one_or_more([1]) }         # => [1]
  try { assert_one_or_more(:foo => :bar) } # => {:foo=>:bar}
  try { assert_one_or_more([]) }           # => ""

  # #deny is the opposite of #assert
  try {  deny(true) }             # => ""
  try { deny(false) }             # => false
  try { deny(nil) }               # => nil

  # Assert that an object is hash-like and contains non-nil values for given keys
  h = {:foo => 1, :bar => 2, :baz => nil}
  try { assert_keys(h, :foo, :bar) } # => {:foo=>1, :bar=>2, :baz=>nil}
  try { assert_keys(h, :baz) }       # => ""
  try { assert_keys(h, :buz) }       # => ""

h2. Rationale

Unexpected nils and other bad values will usually bring a Ruby program down eventually, but the actual point of failure might be deep down the call stack and the error message less than revealing. Judicious use of FailFast assertions to check your assumptions can ensures that the program will end as soon as a contract violation is detected, with a stack trace that points directly at the assertion which failed.

One of the primary goals of FailFast is to make assumption-checking declarative. Assumption checking should be simple and concise so that we can get to the meat of a method without getting bogged down in verifications. At the same time, FailFast is lightweight. It is not a metaprogrammed Design-by-Contract DSL. It is a simple set of shorthand methods for validating values.

It is not the intent of FailFast to have specialized assertions for every eventuality. Rather, it seeks to cover a few common cases where there is a potential for significantly increased clarity and declarativeness.

h2. Features

  • Fully spec’d/tested.
  • In most cases assertions return their last argument. This makes it easy to check values inline. For instance: assert_exists(obj).foo()
  • Most assertions can take a block where a further boolean check can be performed. For instance, use assert_exists(x) { x.predicate? } to check first that x is not nil, and then that it satisfies a predicate.
  • AssertionFailure derives directly from Exception so that it will never be silently eaten by no-argument catch statements.

h2. Documentation

See the RDoc.


See the “project site”:http://fail-fast.rubyforge.org for more.

[ANN] alter-ego 1.0.0 Released

Today I’m happy to announce the release of AlterEgo, a state-pattern library for Ruby. AlterEgo was born about a year ago, when I found a need to formalize state-based behavior in Ruby objects. I surveyed the existing libraries at the time (a set which, IIRC, consisted of just acts_as_state_machine), and found they didn’t do quite what I wanted. Other solutions were focused on defining states and transitions, not on providing the kind of delegation-based behavior switching that the Gang of Four State Pattern describes. So I wrote AlterEgo, and it has been serving us well at “MDLogix”:http://mdlogix.com ever since. I’ve been wanting to open-source it for a while, but this month I finally got around to getting approval and doing the necessary extraction and packaging.

There’s plenty of explanation and documentation at the “AlterEgo project site”:http://alter-ego.rubyforge.org , so I won’t go into depth here. In a nutshell, AlterEgo is a library you include into your classes in order to give them state-based “personalities”. Here’s the canonical example:

  class TrafficLight
    include AlterEgo

    state :proceed, :default => true do
      handle :color do
    "green"
      end
      transition :to => :caution, :on => :cycle!
    end

    state :caution do
      handle :color do
    "yellow"
      end
      transition :to => :stop, :on => :cycle!
    end

    state :stop do
      handle :color do
    "red"
      end 
      transition :to => :proceed, :on => :cycle!
    end
  end

  light = TrafficLight.new
  light.color                     # => "green"
  light.cycle!
  light.color                     # => "yellow"
  light.cycle!
  light.color                     # => "red"
  light.cycle!
  light.color                     # => "green"

Under the covers this is all accomplished with a proxy module and method forwarding. The underlying model, as well as much of the terminology used in the API, is based on the State Pattern as described in the book Design Patterns:

A “context” object – the class you want to have state-based behavior – always has a reference to one and only one “state” object. When “requests” – methods calls – are received, they are delegated to the current state object, which handles them in whatever way is appropriate for that state. In AlterEgo, we take advantage of Ruby’s dynamic nature to execute these “handlers” in the context of the original context object – so we can write them as if they were instance methods of the context object, with full access to instance variables, private methods, etc.

For more information, documentation, and information about how to contribute, see “the project site”:http://alter-ego.rubyforge.org.

Writing Self-Confident Code

A common idiom in ruby is to call a method only if its receiver is not nil:

thing.foo if thing

or:

thing && thing.foo

Various libraries exist for making this a little more convenient. You can use andand, or if you are using Facets you can use ergo. And seriously, you should be using them – they make your code cleaner and more succinct.

But don’t let the existence of these libraries give you the idea that having null-checks throughout your code is OK. It’s not. Pervasive null tests are a code smell.

If you find you are using the elvis operator or its equivalent everywhere, you most likely have a design problem. Is it really OK for that attribute to ever be null? In a lot of cases the existence of a null attribute or association is indicative of an insufficiently specified contract. Maybe you should be setting that attribute to a default value at initialization, or requiring an explicit value for it at initialization. If it really is OK for that attribute to be null, consider whether you should be using a Null Object or some kind of default placeholder object rather than generic nil.

Checking for null is almost always an implementation detail, not a part of the domain you are modeling. As such the null check should be isolated to the boundaries of your code, or eliminated altogether. Code that constantly checks if things are null has an insecurity complex, always second-guessing itself. Make your code self-confident. Eliminate null checks wherever you can.