Francis Hwang
11/11/2004 3:41:00 PM
On Nov 11, 2004, at 10:19 AM, James Edward Gray II wrote:
>
> Does Ruby combat The Fragile Base Class Problem with philosophy alone?
> I'm referring to Duck Typing here, of course. Let them pass in what
> they want and if it responds to all the right messages, we don't care
> what it is. In this scenario, we're not supposed to check "kind_of?"
> at all, right? In that case, how do you document a method like this?
>
> class DatabaseTable
> # ...
>
> def export( exporter )
> exporter.start_table
> exporter.store_metadata(@name, @width, @column_names)
> @rows.each { |row| exporter.store_row(row) }
> exporter.end_table
> end
> end
>
> You don't really just say, "Pass in an object that responds to X, Y,
> and Z." in the RDoc, do you?
>
In the RDoc, you usually say "Pass in an object of X class." RDoc
comments ideally are a sort of loose contract, so when you say that
you're implying "You can poke around with other classes, but there's no
guarantee this library won't blow up when you do it, and there's no
guarantee the internals won't change in the future so that a hack that
works today will break tomorrow."
It's a philosophical difference, and it's fairly profound. Heavy OO
theory seems to believe more or less in Platonic ideals: There are
universal types that exist in the universe, and if you do a lot of
domain research up front you'll discover them all and won't have to
refactor much as you implement. (This is comparable, incidentally, to
Islamic illustrators of antiquity, who were not allowed to make
drawings that mimicked nature, so every time they drew, say, a horse,
they would say they weren't drawing a particular horse in the world,
but the essence of all horses.)
Lightweight OO theory -- expressed in the idioms of Ruby and other
light OO languages like Smalltalk -- says that types are provisional,
and to a certain extent, they're just convenient lies we tell ourselves
to get our work done. (If you want, you can tie this into certain
strains of Buddhism which argue that the self is an illusion we hold up
to get through the day.) You define your classes as you need them, but
the time may come when you discover that the class needs to be
redefined or discarded entirely, so you do what is necessary for the
moment and move on.
Note that most of this is untenable without rigorous unit testing. And
in fact, the recent popularity of Ruby and *cough* Python owe more than
a little to the bubble in XP and Agile methodologies a few years back.
People started unit-testing in Java, then they realized that once they
were writing the tests, all that static typing caused more harm then
good.
On a level of expressiveness, I think one of the nice consequences of
unit testing is the fact that you can encode a lot of subtle
assumptions into those tests. As opposed to trying to write a class and
interface, that's not going to encode nearly as much.
F.