Just A Summary

Piers Cawley Practices Punditry

Humane interfaces again

Posted by Piers Cawley Fri, 16 Dec 2005 16:38:00 GMT

A friend just popped up on IRC and pointed me to one of Elliote Rusty Harold’s contributions to the humane interfaces debate that was sparked by Martin Fowler’s post on the subject. I didn’t recognize the URL and ended up rereading it.

As I did so, I suddenly realised that yes, Harold does have a point, but that he’s missing another one that seems rather more important to me.

His complaint stems from mystification at the presence of methods like Array#abbrev, Array#nitems and Array#compact!. Methods that, he argues, have no place on a general List object.

He’s sort of right, maybe the distributed ruby Array class wouldn’t suffer if they were removed. But where else are you going to put them? In a world of closed classes, your only choice is to write a utility function somewhere and to hold your nose as you write a function that never touches self and which monkeys with the state of an object in a different class.

Those of us who use dynamic languages with open classes would see that the method needs to be moved onto the appropriate class where it can manipulate the state of self to its heart’s content. Smalltalk excels here; as well as creating the method, you must decide what protocol to place it in. So you could create a ‘foo support’ protocol for methods you’ve put on a class to support your ‘foo’ application. When you discover that the method is of of more general utility, you would move it into another, more general protocol. All of Smalltalk’s tools are protocol aware, and they are a really useful tool for organizing code.

I’m sure that Ruby’s Array has the methods it does because Matz needed them for particular problem and implemented them on the class because that is where they belong.

If I were redesigning the Ruby Array class, I wouldn’t remove the methods that Elliotte objects to, but I would do the nearest thing possible to moving them into a protocol. I’d move them into one or more Mixin packages that Array mixes in by default. The ‘offensive’ methods would still be there, but the would be, in a sense, set apart from the class’s ‘fundamental’ properties. It should even be possible to make Array a subclass of some stripped down BasicArray, but if you’re going to wear that hair shirt you wouldn’t get the syntactic sugar of the [ ... ] constructor.

It seems to me that the users of static languages (and even some dynamic ones) have never got into the habit of asking “Where does this method belong?” Or maybe they did ask it, but got bored of being told “You can’t put that there!” by the compiler.

One could certainly quibble with the choice of which methods got included in Ruby’s core classes, but you certainly couldn’t put those methods anywhere else without compromising them. One could even make a case for leaving them where they are because they act as pointers along the Ruby Way.

The guiding principle is that you should put behaviour in the Right Place. Ruby’s lovely because it allows me to apply that principle everywhere, so is Smalltalk, and Perl 6 (when it gets here). The fact that Java’s classes are closed in this way is just one more bullet point on my ‘Why I don’t code in Java’ list.

As for the “What’s Ruby’s Array doing with push/pop and shift/unshift?” question. If it bothers you that much, try pronouncing ‘Array’ as ‘Deque’.



Just A Summary