On 10/7/07, Trans <transfire / gmail.com> wrote:
> On Oct 7, 8:42 am, "Austin Ziegler" <halosta... / gmail.com> wrote:
>> No, actually, it doesn't provide maximum code reusability. Ruby
>> supports a rich vocabulary and you're choosing to use a form that,
>> while clearly useful in some cases, is not right.
> Yes it does, b/c if methods are placed in a class, the only reuse if
> via a subclass.

You are 100% wrong here. Not all reuse is defined by mixin or
inheritance. Delegation and composition are also reuse.

> If they are in a module they are not limited by that constraint. I
> haven't lost anything at all by putting all behavior in modules, I
> have only gained. The approach is a superset.

The approach is a mess and tries to abstract things out in a nonsensical
way. Essentially, you're saying that UP FRONT you divide things into one
or more "class modules" and one or more "instance modules". With few
exceptions, modules should be extracted from classes when you can think
of a more-generic case for it. And you don't extract the whole damned
class to pull it off; you pull the special-purpose-for-similar-objects
code out.

> I seem to be the only one who ever gives code examples. How about you
> show me an example of how you'd do it?

You've got plenty of examples of how I'd do it: it's called my existing
Ruby code that's out there publicly on RubyForge. (This is probably
close to ten thousand lines of code ... that doesn't do what you're
talking about except in one instance I can think of that I only did it
that way for clarity and wouldn't do it that way again.)

I mostly do it as classes. I don't screw around with modularizing things
that simply *aren't* modules. Just because you CAN extract all of the
purpose out of a class and put it into a module just to include it right
back in doesn't mean you SHOULD.

>> Modules in Ruby are useful for adding new "generic" class
>> capabilities.
>>
>> Enumerable is a way of using the ability to iterate over a collection
>> object (and a collection is defined by #each, which goes through the
>> *state values* of the object in turn). It's like a Java interface
>> except that you don't need to reimplement each and every piece of the
>> interface because the interface is always expressed in terms of
>> #each.
>>
>> Transaction::Simple is a way of adding "extra" state to an object
>> that allows it to be versioned in memory. All of that extra state is
>> managed by the methods defined in the module.
>>
>> What you're talking about is on par with components and graphical
>> development. They can work in simple cases, but the moment you start
>> having complex cases, you start realizing that the code is becoming a
>> bit more complex to integrate that way. You can either refactor your
>> code, or start looking at ways that the language can change to
>> accomodate your model's inflexibility.
>>
>> Modules aren't really meant for providing state that the object
>> depends on normally. They're *extra*. So you should be working with
>> classes that have implementations; you should re-factor out common
>> functionality (and I mean REALLY common functionality) into modules;
>> you should have a class hierarchy if it's appropriate; you should
>> compose multiple objects into a single object where appropriate.
> You are constraining the use of modules according to your own view of
> how they "should" be used, and in the process I think you're missing
> my point.

No, I didn't miss your point at all. I think your approach is stupid and
shortsighted. Sorry for the harshness, but the reality is that using
modules this way is nonsense and you're running into limitations because
you're trying to do something that doesn't make sense. I'm not saying
that Ruby's perfect or that everything in it makes sense, but if it
*hurts* to do something one way in Ruby, that's usually a sign that
you're doing it wrong.

There's HUGE code smell in what you've shown.

> You've created an artificial separation between forms of code
> encapsulation because, you reason to yourself, one is for handling
> state and one if for generic capabilities.

It's not artificial. In Ruby, modules do not contain state. Period. Only
objects, which are instances of classes, contain state. The canonical
examples of modules (Enumerable, Comparable) don't deal with state
directly, but only through a defined interface that DOES deal with state
in an object. Transaction::Simple is a module because it adds functions
to objects that allow those objects to manipulate state in different
ways.

Transaction::Simple has generic applicability. Text::Format does not.

> But that is putting a hard line in a soft world. There really is no
> need to make that hard distinction. If a coder, like yourself, wants
> to do that you can do so just as easily with a single form of
> encapsulation....

[snip the rest of this nonsensical paragraph and the entire next
paragraph that has nothing to do with what I said]

Do NOT try to put words in my mouth.

>> I'll put it clearly: if I were running a Ruby consultancy and a
>> programmer of mine used your methodology for everything (e.g.,
>> classes defined by composing modules), I would not keep that
>> programmer on. It's a bad style. Sorry.
> Clearly there is a reason you aren't running a consultancy.

...which has nothing to do with this stance. You write bad code and
design badly. You always want to change the language to fix the fact
that you've coded yourself into a corner. You've done this for years,
Trans.

Classes defined by composing modules is bad practice. There are times
for doing things like this, but they are few and far between and people
who do it should be prepared to defend their reasons for doing so
because it smells like bad code.

-austin
-- 
Austin Ziegler * halostatue / gmail.com * http://www.halostatue.ca/
               * austin / halostatue.ca * http://www.halostatue.ca/feed/
               * austin / zieglers.ca