Elliotte adds another post to the "Humane Interface" debate -
the quote below follows on from an analogy about which remote is
easier to use (an example Steve Jobs gave when introducing Front
Row) - follow the link for the picture and analogy. Here's the
meat, IMHO:
More buttons/methods does not make an object more
powerful or more humane, quite the opposite in fact. Simplicity is
a virtue. Smaller is better. Do you want to go all the way down to
the absolutle theoretical minimum? For a list class that's probably
about four public methods (new, insert, delete, get). Probably not.
That's too few, but 78 is way too many. 10-12 is ideal purely from
human-interface concerns. (I'd say 7-8 except I don't think most
classes can really get that small. Maybe it is 7-8 if we count all
overloaded variants as a single method though.) 25-30 is sort of
the outside maximum: roughly the most signatures you can fit on a
single piece of paper so that the programmer can see the whole
class at once without scrolling their eyes. If that still doesn't
convince you, tomorrow I'll take another look at the Array class
that started this whole brouhaha and show exactly how pointless
most of those 78 methods really are.
Well, I'm going to have to refer back to this post for part of the argument. Instead of dwelling on Ruby though (with which I'm less familiar), I'll look at Smalltalk, class OrderedCollection. In a base image, there are 55
instance methods in that class. There might be more with more
packages loaded; have a look at
this post on extensions to see how that's managed.
Now, I'm pretty sure that Elliotte would dislike 59 methods as
much as he dislikes 78 :) Some of this is an Apples to Oranges
comparison though. To wit: there are methods in the Smalltalk class
implemented for polymorphic reasons that would not be done the same
way in Java. For instance: #inspectorClass lets the collection tell
the system how the development tools should look at the object. I'm
fairly certain that Java IDE's approach that problem
differently.
Additionally, exception raising has been factored out to
individual methods. For instance:
notEnoughElementsError
self error: (#errRemovedTooManyCollection <<
#dialogs >> 'attempt to remove more elements than are
in the collection')
That's an exception that gets raised if we try to access past the end of a collection (on either end). An example:
removeFirst: numElements
"Remove the first numElements elements of the receiver,
and answer an Array of them. If the receiver has fewer
than numElements elements, create an error
notification."
numElements > limit ifTrue: [^self notEnoughElementsError].
^self privateRemoveIndex: 1 to: numElements returnElements: true
In Smalltalk, there's a strong bias to make the object responsible for its own actions. So when you try to index past the end, the object itself raises the exception - it's not handled by deep machinery in the VM.
Elliotte says that 10-12 methods are "enough" and that past that, we get into bloat. Well, looking at class OrderedCollection, I'm not sure what he'd want me to pull out. I suppose he might consider #add:before: fluff, but it's a useful method - it allows me to add some object before some other object in the collection. There's a ton of convenience methods of that sort in the class. Would it be better to simply have #add:, and then force developers to write their own versions of all the convenience protocol in their own classes? Recall that in Java, I can't extend a class, so these new methods will end up in some utility class. Clean OO, that's not.
Smalltalkers - and I think Rubyists - look at this problem very differently from Java folks. The Java people seem to like sparse classes, but they don't seem to realize that sparse classes combined with an inability to extend leads to everyone creating their own set of utility classes. In Smalltalk, the useful protocol that people add tends to migrate up to the vendor over time. For instance, in VisualWorks 3.0, OrderedCollection had 53 methods. More interestingly, the abstract Collection class (Collection) had 40 methods in VisualWorks 3.0 - and has 51 now. What we seem to have a two very different approaches to the class design problem. I think the Smalltalk/Ruby one is better, because it favors putting code where it belongs. The Java approach implicitly favors lots of utility classes.