On 8/22/06, Just Another Victim of the Ambient M. <
[email protected]> wrote: The problem is that dynamic typing,
while
very powerful, also hid the
intent of the method. Obviously, any object that satisfied whatever the
method was trying to do will suffice as a parameter, and that would be the
point of duck typing, there was obviously some concrete example of some
type the method was expecting. It would really have helped to let me know
what that was…
Thinking about this thread, I was wondering why I’ve generally had so
little
of this kind of problem. For about a year after I first learned Ruby, I
thought the most irritating thing about the language was that I had to
do my
own type checks of all the arguments in every single method I wrote,
because
the d**n language wouldn’t do it for me. (Can you tell I’m a hard-core
security-oriented C programmer?)
When duck typing finally sunk through my thick skull, it changed
everything.
But I notice one thing. It’s often said that the intent (including the
desired datatypes) isn’t too hard to discern from a quick look at a
method’s
code or documentation. But this is primarily true if the argument types
are
simple or primitive. Strings, IOs, numbers, or collections of same. If
you’re passing around objects that are more complex, especially ones
that
incorporate domain-specific information, that’s when you really get into
trouble.
Because whether you use static or dynamic typing, you are tightly
coupling
one set of domain knowledge
(in the argument) with another (that of the method you’re writing). This
is
where a lot of fragility comes from, to say nothing of difficulty in
understanding the intent. Seeing the argument-type declarations in the
text
of a method you are trying to understand
isn’t much better than seeing them described in a document, because
your
real challenge is still to grasp how the non-primitive design contained
in
the argument interacts with that of the method.
This is where one of Ruby’s more distinctive features, the yield, can
help a
lot. I find that when I’m tempted to pass a big chunky object to a
method of
some other big chunky object, I either look for the design commonalities
that I obviously missed in the first place, or else I look for ways for
the
method to yield to the argument. Just to avoid coupling them more than
is
really necessary.
In the more typical case where you’re passing around integers, strings,
and
IOs, it just doesn’t seem to matter nearly so much. Your first guess on
looking at a method you’re trying to understand is probably going to be
right, and spelling out the arg types in the text subtracts readability
without adding comprehensibility.
In short, it’s been said here that documentation is the key to the
problem,
but I’d like to put in a good word for design as well.