Kent Dahl wrote:
However, there is a middle ground. Back to the parser example.
[snip]
But this will:
module Text::SGML
class XML::Parser < Parser
end
endThis might seem like a step backwards, as we have more than one
body.
However, notice that I “cut off” the namespace at Text::SGML,
telling
the reader that I am in need of it, and go on to implement all the
methods of the XML parser that depends on the SGML stuff. I also
avoid
including the XML namespace, just in case there is something icky
there.
In the next step, I’ll implement some basic methods inside the
parser
that doesn’t depend on SGML nor XML:class Text::SGML::XML::Parser
def boring_bookkeeping
end
endHere I cut of the namespaces completely, telling the reader:
“Just working on the parser innards, nothing to see here, move along!”Then there will be methods that need other parts of the XML
namespace,
and I’ll do something like:module Text::SGML::XML
class Parser
def pure_xml_stuff
end
end
endNow I seem to have been opening the Parser class umpteen times and
for
what? For separation of concerns.
I must say, I was doubtful that anyone would come up
with a good example of why this behavior was useful
until I saw this. It’s a very intriguing example,
and appeals to me quite a bit.
People often boast about how it’s possible to add
methods to existing classes, and I agree it’s a great
feature of the language, especially for smallish
scripts. However, I don’t know how well you could
sell it to more staunchly statically minded people.
However, your example also illustrates a method of
design that is (at least in the languages I know)
unique to ruby. Namely that you can use the fact
that you can open classes multiple times to group
like things together, and segregate unrelated things.
For example, at the top of some ruby library, you
could do something like:
module Mod1
module Mod2
class Class1
end
…
class ClassN < Class1
end
end
class ClassM
end
end
Which only describes the overall module/class
hierarchy of the library, and then below that, go
on to write the actual implementation (in ways
broken up as you show.
If it seems clearer, you could even write the above
as
module Mod1; end
module Mod1::Mod2; end
class Mod1::Mod2::Class1; end
…
I’m not sure how valid or useful this technique
might be, but it seems to me that something of the
sort should be explored a little bit, because it
could turn out to be a unique, interesting, and
powerful design tool of ruby.
Does anyone agree, or am I being too starry-eyed,
or am I wrong altogether?
- Dan