« PRINCE2 vs. PMI's PMBoK | Main

Humane Interfaces: Fowler vs. Harold

Today I noticed an interesting exchange between two of my regular reads: Martin Fowler's blog and Elliotte Rusty Harold's Cafe au Lait web site. I respect both of the authors for their interesting view points which spark many an interesting thought, but on this occassion Elliotte has disappointed me.

Martin was discussing the value of what he terms 'Humaine Interfaces' - software interfaces which are designed to provide the methods you need with names that are easy to remember and type. Apologies for my explanation which is probably an oversimplification.

Elliotte comes in with an unsubstantiated expression of disapproval and claims that simplicity is key, and that too many methods is a bad thing.

Well in short, I disagree.

Do more methods automatically mean more complexity? No, they allow the methods to provide a better reflection of the underlying intention. Martin gives an example of the Ruby code:

anArray.last

compared with the Java:

aList.get(aList.size - 1)

Martin comments that the former is simpler to use, whilst Elliotte says that it presents a larger and therefore more complex API to use.

My view is that there is nothing to be lost by providing alternative and more specific methods within a class to deal with specific cases that users may require. The user of a class doesn't have to understand or memorise every method in order to use it. Scanning through method names isn't a chore as long as they are presented alphabetically. There are no significant processor cycles wasted by only using 2 out of 78 methods of a class.

Getting into the detail you start to see some real valuable reasons for using a more specific method rather than applying a more minimal set of methods to a task. In some implementations of a list, getting the size of a list, or getting the last element by it's index number might be very expensive, whilst a dedicated method for getting the last item may be able to be optimised in some useful way because it represents a special case.

It also avoids some of the silly mistakes that you get from forgetting whether to use:

aList.get(aList.size) or aList.get(aList.size - 1)

Of course there are no perfect answers. Being required to provide 78 methods to conform to some interface standard could be extremely frustrating, so I wouldn't advocate it for abstract methods / interfaces. Similarly, there's no value in having a rag-bag mix of every method name the author thought of over the last 3 years of development - the methods should be there for a good reason, well named and suitably documented.

Finally, if I'm going to agree with Elliotte at all, I guess I should express doubt in the value of method aliases. One of the values of Java over C is that it provides fewer ways of expressing the same thing. I can't see any great value in having two methods with different names that do exactly the same thing. In a collaborative project it would inevitably lead to situations where code confusing uses of both method names for no apparent reason. On the other hand, aliases in the method documentation would be good, e.g. you look for a method length() and it says "see method size()".

December 6, 2005 in Agile, Computing, OpenSource | Permalink

Comments

I completely disagree. I abhor convience methods because they make API's complex to understand and often can have unintended side effects. (For example, I've seen 'readAll' methods that reade in an entire text file in one swoop, leaving the end user to deal with things like platform specific linefeeds.) Also, from experience working on team projects, I've seen that folks tend to introduce convience methods into classes and then forget about them, so these methods (which aren't used very much) are not maintained as the class is refactored or modified. (Unless, of course, you've managed excellent code covareage with yoru unit tests)

Of course, I realize this is only my opinion.

Posted by: hohonuuli | 7 Dec 2005 17:18:45

Actually, aliasing comes in very handy to solve inconsistencies in API's, such as Java's "length" and "size" which are used left and right with no apparent reason. Even now, ten years later, I still find myself unsure of which one I should use depending on the class.

Otherwise, I'm in agreement with you (see my blog).

--
Cedric

Posted by: Cedric | 7 Dec 2005 22:27:53

Let's put both Fowler and Harold in a small cubicle together, and place a partition over the exit. We'll toss in some languages one at a time, and see what happens. First Java:

Harold: Sweet. Short and sweet. I like that. This Collections/List/ArrayList thing is a breeze to use.

Fowler: Nitwit. While you been sittin' there cranking out Java idioms by the tonne, I wrote and optimized these other 53 methods that I use all the time! It was a pain, but now I have a type that's 100% compatible with yours, and with extended functionality! I showed this to Sun, and they're gonna put my class in the next release...

Hmm... Okay, now let's toss Ruby in there:

Fowler: That's more like it! 78 methods standard, all heavily optimized behind the scenes. Whoo! See you in the future, buddy!

Harold: Narrgh! Can't I get rid of this stuff? No? Fine, I'll write my own... Tada! Two new classes, one for basic functionality, and one with extended functionality for those corner cases I use once a year. Now isn't this cool?

Fowler: Yeah, but nobody else can use it, 'cause it's not an Array!

That was fun.

Posted by: Chris Moorhouse | 8 Dec 2005 00:53:14

"Being required to provide 78 methods to conform to some interface standard could be extremely frustrating, so I wouldn't advocate it for abstract methods / interfaces."

The common design pattern here would be

interface MinimalInterface
foo()
bar()
end

interface HumaneInterface extends MinimalInterface
super_foo()
ultra_bar()
...
etc()
end

class MinimalExtender implements HumaneInterface
MinimalExtender(MinimalInterface m)
min = m
end
super_foo()
min.foo.super!
end
...
end

People implement the MinimalInterface, and then their implementing object is wrapped in an extender.

Posted by: Mike | 8 Dec 2005 02:13:45

Too complicated! Just use an abstract class, and provide implementations for all the convenience methods. People use interfaces too much.

Posted by: Brian Slesinsky | 8 Dec 2005 02:34:37

Better yet, use AspectJ and introduce convenience methods, along with their implementation. See http://ramnivas.com/blog/index.php?p=20 for more details.

Posted by: Ramnivas Laddad | 8 Dec 2005 05:23:42

As a small aside to the more important debate (intention vs implementation, humane vs minimalist, good OO vs Demeter violations) please, please stop talking about the method count as any sort of meaningful metric: it is an apples to oranges comparison.

In Ruby, an Array is something you can new up and actually use. It mixes in (think inherits from an abstract class, java people) 23 methods from the Enumerable module. It also adds another 11 sugary/c++/operator sort of methods like [] + & etc.

In java, List is a java construct called an interface. To actually use a list, a typical java programmer will new up a LinkedList (or an ArrayList). A LinkedList implements 6 interfaces, 4 of which are generified in java 1.5. It has 5 parent classes in its parent hierarchy. The resulting surface area is 58 methods (not including the "virtual" surface area of the generics). That does not count static methods in utility classes like Collections that can operate on Lists and adds things like sort, shuffle, min, max, reverse, swap...just the sort of things that the Ruby Array gets from its Mixin.

So the real comparison is 23 + 11 + 44 to 58 + about 30 or so...wow, imagine that; if you think of the common things you would do with a list, Ruby and Java do about the same stuff. They just do it in a different OO structure.

It is also obvious but worth noting that we are looking at the sort of classes that should end up with the largest surface area: basic CS things like Bags, Dictionaries, and Lists are going to have more methods than your average complex business class in your custom app that only your team uses.

Posted by: John Lindsey | 8 Dec 2005 10:13:51

That's about as Nerdy as it gets!

Posted by: The Anti-Nerd | 8 Dec 2005 22:33:58

About forgetting to use n or n-1 in a get...what happens if you want the second element? If you want to iterate through them? Do you start at 0 or 1? What if you're using a number contained elsewhere to index into the class? Do you subtract 1 or not? It's pretty important to understand the class's contract, and that's much easier for a class with a smaller number of methods.

I don't find the last()/get(size()-1) argument all that compelling, but some of those methods in the Ruby Array class are ridiculous.

Frankly, people who claim they can't keep the question of whether the list indexed starting at 0 or 1 straight are completely out of their depth with a class as complex as Ruby's Array.

Posted by: Robert Sanders | 15 Dec 2005 20:05:00

A while ago, i found myself happy using array.last(4).first! ... but also feel free to check out http://bigbold.com/snippets/ for more array-related Ruby stuff!

Posted by: foo | 4 May 2006 10:31:36

Nearly two years ago a bunch of people too stupid to understand the difference between application code and a library used by thousands of programmers had a silly and pointless debate ...

Posted by: truth machine | 5 Aug 2007 03:48:49

10mg 50mg ultram

Posted by: ultram 50mg methadone | 5 Sep 2007 22:11:40

10mg 50mg ultram

Posted by: ultram 50mg methadone | 5 Sep 2007 22:11:54

tamiflu state

Posted by: tamiflu find | 1 Oct 2007 12:22:31

insurance homeowners providers

Posted by: insurance homeowners best | 2 Oct 2007 21:25:23

effexor antidepressant

Posted by: effects effexor | 20 Oct 2007 09:08:03

My mind is like an empty room. Nothing seems worth thinking about. More or less not much noteworthy happening worth mentioning, but it's not important. I guess it doesn't bother me. I've just been letting everything wash over me lately.

Posted by: sdpahsrqudbsxfsrw | 26 Oct 2007 23:02:41

Bridgette Kerkove

Posted by: Bridgette Kerkove | 28 Oct 2007 01:24:24

Asia Carrera

Posted by: Asia Carrera | 28 Oct 2007 01:03:54

Nicole Sheridan

Posted by: Nicole Sheridan | 28 Oct 2007 01:36:18

Nina Hartley

Posted by: Nina Hartley | 28 Oct 2007 02:11:07

Nicole Sheridan

Posted by: Nicole Sheridan | 28 Oct 2007 02:43:51

Jenna Jameson

Posted by: Jenna Jameson | 28 Oct 2007 15:48:40

Carmen Luvana

Posted by: Carmen Luvana | 28 Oct 2007 16:40:53

Alexis Silver

Posted by: Alexis Silver | 29 Oct 2007 13:40:46

There was merrily!
http://danuegonax.com
So interesting there was that I fell asleep...

Posted by: aspilkins | 29 Nov 2007 20:38:44

Excellent site with fantastic references and reading.... well done indeed...!
http://srubibablo.com
I just wanted to pass on a note to let you know what a great job you have done with this forum.Thanks!

Posted by: aspilkins | 30 Nov 2007 12:35:42

prescription phentermine no required

Posted by: phentermine prescription no fedex | 15 Dec 2007 01:11:30

effexor affects

Posted by: effexor time | 4 Jan 2008 21:46:19

I've just been letting everything pass me by lately. Maybe tomorrow. Today was a complete loss, but that's how it is. Eh. Oh well.

Posted by: pass xxx gay | 11 Feb 2008 18:29:26

Post a comment