The Case for Multiple-Inheritance

On Oct 7, 10:42 am, “Pat M.” [email protected] wrote:

The thing is (and maybe this will help clarify how I see this) the
include Y
Agreed. That looks painful.
end
T.

You misunderstand me. What looks painful to me is having the behavior
of a class tucked away behind 15 different modules, instead of being
right in the class where it belongs.

I see. Well it’s a trade-off. Would you prefer a class with 50
attributes or one that divides those into a few groups based on what
they concern? For instance I have a Package class, it consists of
General, Version, Content and Control components. I use that as a
library reference object. However when I want to use it for creating
distributable packages I mixin Distribution and Dependency modules.

T.

In most cases, it is not a problem: I represent the fact that
TakePictureAt(x, y) is in fact a sequence of MoveTo(x, y) and a
TakePictureNow. It is therefore possible to repesent the thing with
single inheritance.

That is not a is-a relationship, it is a sequence that contains
TakePictureNow and MoveTo. Can’t you freely arrange other Actions in
sequences? How do you model that?

But there are cases where this kind of separation cannot be done –
hence the need for one class to be an implementation of multiple
models.

And how do they look like?

And where do you need kind-of? Such a question is not very OOP.

mfg, simon … l

On Oct 7, 9:13 am, “Pat M.” [email protected] wrote:

module X; end

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.

Agreed. That looks painful.

Bahahahahahahahahaha!

You’re right! But it’s only painful b/c it’s what you HAVE to do today
to achieve this level of code reuse. If I had my way, it would as
simple as:

class X
def self.foo # instead of needing M

end

class Y; end

class Z
is X
is Y
end

And we’d still have complete code reuse.

T.

On Mon, 2007-10-08 at 01:12 +0900, Pat M. wrote:

end

class WindowsVideoApplication
include WindowsApplication
include VideoApplication
end

def only_linux_video_please(app)
raise “Must be a LinuxVideoApplication” unless LinuxApplication ===
app && VideoApplication === app
end

I’m not sure this is a particularly good example; it’s based off of
Trans’ example, not Sylvain’s, and it also does use multiple inheritance
inasmuch as modules amount to restricted MI.

-mental

On Mon, 2007-10-08 at 00:44 +0900, Austin Z. wrote:

It’s possible to use delegation with non-dynamic languages. Hard, but possible.

I dunno, it mostly just means writing wrapper methods. I actually do
“static” delegation in Ruby more often than I do “dynamic” delegation.

-mental

On 10/7/07, MenTaLguY [email protected] wrote:

include VideoApplication
end

I’m not sure this is a particularly good example; it’s based off of
Trans’ example, not Sylvain’s, and it also does use multiple inheritance
inasmuch as modules amount to restricted MI.

-mental

Well, neither one gave examples, afaik, and I think this whole thing
is kind of stupid. I have a feeling that when these guys post their
examples, people will show them much better ways to design their code,
so I wanted to get the ball rolling.

Pat

On Mon, 8 Oct 2007 00:44:26 +0900, Austin Z. wrote:

It’s possible to use delegation with non-dynamic languages. Hard, but possible.

Why hard? If you’ve got function pointers or their equivalent, you have
delegation, no?

On 10/7/07, Trans [email protected] wrote:

I can’t inherit from two classes, in the end I just made the
LinuxApplication a module. If it were a bigger deal I would go ahead
and make the VideoApplication a module too, just as you describe, but
it’s not that important. It just seemed like a good example to share
in support of MI because Ruby’s SI forced me to make a rather
arbitrary choice of which gets to be the class and which doesn’t.

T.

The point is that if you “have to make an arbitrary choice of which
gets to be the class and which doesn’t” then it’s likely that neither
one “has” to be the class nor should one be the class. You’ve
created objects with composable behavior, so you’re better off passing
in objects and using delegation, or using modules.

Pat

On Oct 7, 7:04 pm, “Pat M.” [email protected] wrote:

Well, neither one gave examples, afaik, and I think this whole thing
is kind of stupid. I have a feeling that when these guys post their
examples, people will show them much better ways to design their code,
so I wanted to get the ball rolling.

Pat, my program is almost as simple as the first example I gave. Since
I can’t inherit from two classes, in the end I just made the
LinuxApplication a module. If it were a bigger deal I would go ahead
and make the VideoApplication a module too, just as you describe, but
it’s not that important. It just seemed like a good example to share
in support of MI because Ruby’s SI forced me to make a rather
arbitrary choice of which gets to be the class and which doesn’t.

T.

On 10/7/07, Trans [email protected] wrote:

On Oct 7, 8:42 am, “Austin Z.” [email protected] 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.

Transaction::Simple is a way of adding “extra” state to an object
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

On 10/7/07, MenTaLguY [email protected] wrote:

On Mon, 2007-10-08 at 00:44 +0900, Austin Z. wrote:

It’s possible to use delegation with non-dynamic languages. Hard,
but possible.
I dunno, it mostly just means writing wrapper methods. I actually do
“static” delegation in Ruby more often than I do “dynamic” delegation.

I do both; it depends on how much I need Container to Act Like
Containee.

But you’re right.

-austin

On 10/7/07, Trans [email protected] wrote:

On Oct 7, 10:42 am, “Pat M.” [email protected] wrote:

You misunderstand me. What looks painful to me is having the
behavior of a class tucked away behind 15 different modules, instead
of being right in the class where it belongs.
I see. Well it’s a trade-off. Would you prefer a class with 50
attributes or one that divides those into a few groups based on what
they concern? For instance I have a Package class, it consists of
General, Version, Content and Control components. I use that as a
library reference object. However when I want to use it for creating
distributable packages I mixin Distribution and Dependency modules.

Personally? I’d prefer the former. If I was dumb enough to design
something that required 50 attributes. Let’s pick on your example:

class Package
class Description end
# Should be Package::Description
attr_accessor :description

class Version; end
# Should be Package::Version
attr_accessor :version

class Contents; end
# Should be Package::Contents
attr_accessor :contents

class Controller; end
# Should be Package::Controller
attr_accessor :controller

class Distributable < Package
  class Distribution; end
  attr_accessor :distribution

  class Dependency; end
  # Probably should be specialized further so that it's a list of
  # dependencies, so it should be attr_reader with a good initialize
  # to fix this issue.
  attr_accessor :dependencies
end

end

There we go. It’s now a properly composed object that doesn’t mix in
multiple pieces of functionality into a flat access hierarchy. I now
have a Package::Version class to reuse elsewhere if I want, and it’s a
full-on black box. I don’t have any worries that Package::Version the
class will have any instance variables that conflict with another item
because I used a module.

It took me all of thirty seconds to fix your design and make it
class-oriented rather than module-oriented. My objects are now more
usable as a whole and the overall interface substitution capabilities
are improved because now my Package class doesn’t HAVE fifty attributes;
it’s got FIVE. The Distributable package is properly specialized, too.
It might be possible to use a module to extend a package object into a
distributable package object rather than a subclass, but I’m not sure
that the design for that is a good one.

Because each of my classes is smaller, my code is likely to be
significantly more robust, and I have functionality that I can
test independently of the whole Package class without trying to mix it
into something different.

That’s what I mean, Trans: your design approach for mixing in 50
attributes or writing 50 attributes is bad. If you need that many, your
object is PROBABLY way too big. (Yes, there are times when such things
are necessary; they’re extremely uncommon, though.)

-austin

On 10/7/07, Jay L. [email protected] wrote:

On Mon, 8 Oct 2007 00:44:26 +0900, Austin Z. wrote:

It’s possible to use delegation with non-dynamic languages. Hard, but possible.
Why hard? If you’ve got function pointers or their equivalent, you have
delegation, no?

I was referring to Ruby’s #method_missing capabilities more than
anything else. You can’t do that in C++. (As I said to MentalGuy, it’s
something that depends on how much I need a containing object to Act
As a contained object. Ruby doesn’t care because of its fully dynamic
dispatch; C++ cares because of the static typing limitations.)

-austin

On Oct 7, 8:57 pm, “Austin Z.” [email protected] wrote:

library reference object. However when I want to use it for creating
class Version; end

end
usable as a whole and the overall interface substitution capabilities

That’s what I mean, Trans: your design approach for mixing in 50
attributes or writing 50 attributes is bad. If you need that many, your
object is PROBABLY way too big. (Yes, there are times when such things
are necessary; they’re extremely uncommon, though.)

Fantastic jobs Austin. Now initialize the class from a YAML file for
me. Did I mention the file spec looks like this:


package:
version:
created:
homepage:
devsite:
authors:
description:
libpaths:

etc…

It has some 35+ possible entires and some of those have aliases
besides (because I like giving my users some flexibility). Plus it
should be extensible because other utilities (like the distributable
packaging tool) will need additional information.

Come on, show the dumb-dumb how it’s properly done.

T.

On Oct 7, 8:45 pm, “Austin Z.” [email protected] wrote:

inheritance. Delegation and composition are also reuse.
Fair enough, although that’s only 50% wrong :wink: But the point was the
restriction of having to pick one construct (class vs. module) over
the other. A module can almost do anything a class can. One can even
effectively initialize a method via Class.new{ include Mod }. Of
course this is less convenient and one must fuss with ClassMethods and
be careful of the Double Inclusion Problem, but my point clearly
stands: modules are more versatile than classes. Thus by using all
modules for behavior (and classes as only compositions of modules)
maximizes reusability. And for this simple fact: classes cannot be
mixed-in.

code out.
Huh? It’s a mess to divide these things into modules for mixin, but
its ok to divide them as classes and delegate? The point is to make
less mess by dividing things up into more manageable pieces. Those
pieces may prove nicely reusable, too, if well thought out, btw. But
my example of extraction of the whole damned class was to make a
point about the limitations of class vs module reuse. For instance,
here’s an example I didn’t mention before. Did you know that if you
use all modules then AOP coding is very simple? It’s easy to prepend a
module relative to other modules in the inheritance chain. But not so
for classes. Dynamic AOP for classes takes some mind-numbing meta-
coding for sure.

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.)

Of course I’ve seen some of your code, Austin. And you’re quite a
capable coder. But your Ruby code has a very classic feel to it. Like
you were programming in C. You’re very conservative and don’t much
venture into the meta-coding deep. I’m not insinuating anything
negative in that, btw. I think it’s good that there are all types of
coders. But you seem almost religious about your way of doing things.

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.

Of course not. And of course I don’t. But I wish Ruby didn’t make me
have to choice one over the other. It reduces the flexibility of it’s
otherwise extremely elegant inheritance model; and likewise makes
delegation the better choice in more cases than otherwise would be
necessary.

Transaction::Simple is a way of adding “extra” state to an object
Modules aren’t really meant for providing state that the object
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.

Ah yea, and “If God meant for men to fly, he would have given them
wings.”

You’re arguing that I have the problem, not Ruby. But I’m not arguing
Ruby has a problem, I’m arguing that maybe it could be even better.
Nor do I have a problem. I finished the program yesterday. I didn’ run
into a limitation per-se, I ran in to a “why am I having to make an
ultimately pointless distinction?”

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.

Now you’re knit picking words. Of course only object instances have
state. But classes, and modules!, define objects.

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.

Yep. A well defined interface is an important aspect of code reuse –
that’s true for all forms of composition.

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.

What words? You always do this Austin. You makes some admonishing
remark and then never explain what your talking about. It’s a very
deceptive conversational tactic. And I wish you’d cut it out. Explain
yourself. What words do you mean? What I have I said that is
nonsensical? And why do you think it’s all in reference to what you
said. What about the point I trying to make?

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.

No. For years I have explored the language. Pushed up against it’s
boundaries. Investigate what it can and can’t do. I bring up ideas and
make suggestions to explore those further, not because I’m stuck, but
because I’m curious. I’m forever learning. I didn’t come from a C
background and just started writing my C program’s in Ruby. I learned
Ruby as Ruby. And I try to use Ruby for what it is, and enjoy
considering what more it could be. Does this exploration lead me down
rough roads sometimes? Damn right it does. But in the end I’m a better
coder for it. Am I the best coder around here? Of course not, I don’t
pretend to be. But you sure do.

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.

Good gracious. You have so utterly missed the whole point I’m not sure
why I continue to type. What was my point Austin? Please, I want you
to put words in my mouth so I can see if there’s actually any
communication going on here.

T.

On 10/6/07, Sylvain J. [email protected] wrote:

properties from a code point of view. And this is called the
class/object relationship.

The bottom line being: if I was to not use inheritance for my purposes, I
would have to reinvent the “inheritance wheel”.

What I’m stuck with is having “first class models” (classes) and “second
class models” (modules). Know what ? What I gained by using Ruby and the
single inheritance still outperfoms the bunch of code I would have had
to write without them. Still, I’d like to have MI :stuck_out_tongue:
That is funny Sylvain, the more I program in Ruby the less I want to
have MI and
actually I could perfectly dispose of SI too as long as Mixins behaved
a tiny little bit different, well I have expressed the thoughts about
this in my Blog (URL in sign.)
but if you want some more serious ideas about this you might want to
read this
maybe.
http://www.iam.unibe.ch/~scg/Archive/Papers/Scha03aTraits.pdf
HTH
Robert

On 10/8/07, Trans [email protected] wrote:

Fair enough, although that’s only 50% wrong :wink:
No, it’s 100% wrong. You said “the only reuse [is] via a subclass.” Just
using the instance as an object is reuse (composition).

[snip]

modules are more versatile than classes. Thus by using all modules for
behavior (and classes as only compositions of modules) maximizes
reusability. And for this simple fact: classes cannot be mixed-in.

Wrong. Look VERY CAREFULLY at your code, Trans. How many of your modules
are used in more than one place?

If the answer is few, then you’re doing it wrong and you’re introducing
negative consequences in terms of maintainability, while not actually
increasing reuse. Most methods are specific behaviour for a given state.
Pretending that by extracting that into modules that youre increasing
reuse is nonsense. Unless you’re actually reusing the code, you’re not
increasing 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.

You’ve lost maintainability and clarity. You’ve lost any sense of good
design.

pieces may prove nicely reusable, too, if well thought out, btw.
Yeah, it’s much cleaner to think in terms of objects. It’s much
preferable to compose than inherit. Delegation is only necessary when
you need to Act As something else.

But my example of extraction of the whole damned class was to make a
point about the limitations of class vs module reuse. For instance,
here’s an example I didn’t mention before. Did you know that if you
use all modules then AOP coding is very simple? It’s easy to prepend a
module relative to other modules in the inheritance chain. But not so
for classes. Dynamic AOP for classes takes some mind-numbing meta-
coding for sure.

That’s part of the problem, I guess: I don’t think that AOP is
worthwhile in Ruby. AOP doesn’t add any readability to the code, in the
end, than doing it a bit smarter. AOP only sort-of makes sense in Java
because Java’s (otherwise) a static language. But even there, it’s not
all that useful.

venture into the meta-coding deep. I’m not insinuating anything
negative in that, btw. I think it’s good that there are all types of
coders. But you seem almost religious about your way of doing things.

That’s because you’re tone-deaf. I’m saying that from experience with
other people actually having to maintain code or having to maintain
other peoples’ code, the way that you’re doing things is nonsense and
reduces overall maintainability.

If you think my code looks like C, you’d be quite wrong; I simply don’t
do metaprogramming where it isn’t appropriate. (I have an experimental
branch of PDF::Writer that used quite a bit of metaprogramming to
encapsulate a number of rules that PDFs impose on objcts; if I ever pick
up PDF::Writer again, then I will probably be going from that
direction.) Most of the problems that I’ve solved haven’t needed meta-
programming and I’m not going to inflict it on others just to show how
kewl I am.

There’s also code that I have written that I can’t show (it’s
work-related) that does stuff within a particular domain that I would
never advocate in any other way. (I have one, in particular, that
overrides const_missing to return a string value representing the name
of the const just tried. The code where you’d use this expects that.)

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.
Of course not. And of course I don’t. But I wish Ruby didn’t make me
have to choice one over the other. It reduces the flexibility of it’s
otherwise extremely elegant inheritance model; and likewise makes
delegation the better choice in more cases than otherwise would be
necessary.

“Necessary” is a matter of opinion. To pick up on a different message
(to which I’ll be replying to here, as well), I consider an object with
50 attributes an abomination. I don’t care whether you’ve gotten those
attributes by mixins or manually writing them; it means you haven’t
thought about your class design well enough. You seem to prefer flat
classes; I think that flat classes are a disaster in waiting.

[snip]

Ah yea, and “If God meant for men to fly, he would have given them
wings.”

You’re arguing that I have the problem, not Ruby. But I’m not arguing
Ruby has a problem, I’m arguing that maybe it could be even better.
Nor do I have a problem. I finished the program yesterday. I didn’ run
into a limitation per-se, I ran in to a “why am I having to make an
ultimately pointless distinction?”

Yeah. You do have a problem and you have been arguing that Ruby has a
problem. If one is suggesting an improvement to something, it’s because
one has hit a pain point. Sometimes those pain points are legitimate;
sometimes they’re like the old joke:

Man: Doctor, it hurts when I put my arm behind my back.
Doctor: Well, don’t put your arm behind your back.

Your example is precisely one of those situations. The distinction, by
the way, MAY be pointless. Inasmuch as it would encourage the sort of
design decisions you’re making and have demonstrated in this discussion?
I’m more than happy to have it there, because if you’re doing it, far
less capable programmers than you would make even dumber decisions from
it.

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.
Now you’re knit picking words. Of course only object instances have
state. But classes, and modules!, define objects.

I’m not nit-picking at all. It’s the fundamental distinction between the
two right now. Classes can be turned into things that have state;
modules can’t. Modules can only add features to objects.

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.
Yep. A well defined interface is an important aspect of code reuse –
that’s true for all forms of composition.

Not even related to what I said. Modules have some generic
applicability.

deceptive conversational tactic. And I wish you’d cut it out. Explain
yourself. What words do you mean? What I have I said that is
nonsensical? And why do you think it’s all in reference to what you
said. What about the point I trying to make?

“If a coder, like yourself, wants to … with a single form of
encapsulation.” You rambled on for two paragraphs as if I had said
something about a single form for development. Which I didn’t. Never
have, never will. (In fact, it’s pretty much you that’s talked about
only using one form for development. I know you don’t, but you’re still
talking nonsense here.)

boundaries. Investigate what it can and can’t do. I bring up ideas and
make suggestions to explore those further, not because I’m stuck, but
because I’m curious.

Really? If that’s the case, then you really need to work on your
presentation skills, because you’ve yet to present something in a way
that says “I’m exploring this…” and instead nearly always say “Ruby
should do this…” while presenting examples that in every single case
could be coded easier and cleaner if you simply stepped back and thought
a little more. The example you opened this discussion with
(LinuxVideoPlayerApplication) is such BAD design that you SHOULD have
been able to see it.

Like I said, Ruby isn’t perfect and there are things that can improve
about it – and yes, you’ve pointed out a few of those areas. But when
it “hurts” to do something one way in Ruby, it usually means that you’re
doing something suboptimally.

I’m forever learning. I didn’t come from a C background and just
started writing my C program’s in Ruby. I learned Ruby as Ruby. And I
try to use Ruby for what it is, and enjoy considering what more it
could be.

Nice misdirection and assumption of the martyr position.

Does this exploration lead me down rough roads sometimes? Damn right
it does. But in the end I’m a better coder for it. Am I the best coder
around here? Of course not, I don’t pretend to be. But you sure do.

Again, nice misdirection. I don’t pretend to be the best coder. I am,
however, a professional software developer that has to deliver a lot of
code on a regular basis. There are things that I know I wouldn’t put up
with from people who worked with me if I had to maintain their code.
There are things that I don’t care about.

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.
Good gracious. You have so utterly missed the whole point I’m not sure
why I continue to type. What was my point Austin? Please, I want you
to put words in my mouth so I can see if there’s actually any
communication going on here.
I haven’t missed the point. You believe that modules are more flexible
than classes and that things would be better if you could mix classes in
the same way you can mix modules in, or at least if you could “properly”
instantiate modules. You may believe that, but in Ruby at least, you’re
wrong.

On 10/8/07, Trans [email protected] wrote:

library reference object. However when I want to use it for creating
distributable packages I mixin Distribution and Dependency modules.
Personally? I’d prefer the former. If I was dumb enough to design
something that required 50 attributes. Let’s pick on your example:

[snip layered redesign]

are improved because now my Package class doesn’t HAVE fifty attributes;
That’s what I mean, Trans: your design approach for mixing in 50
attributes or writing 50 attributes is bad. If you need that many,
your object is PROBABLY way too big. (Yes, there are times when such
things are necessary; they’re extremely uncommon, though.)

Fantastic jobs Austin. Now initialize the class from a YAML file for
me. Did I mention the file spec looks like this:

[…]

It has some 35+ possible entires and some of those have aliases
besides (because I like giving my users some flexibility). Plus it
should be extensible because other utilities (like the distributable
packaging tool) will need additional information.

Come on, show the dumb-dumb how it’s properly done.

class Package
def self.from_yaml(yaml)
pkg = Package.new

  YAML.load(yaml).each do |key, value|
    case key
    when 'package' then # ...
    when 'version' then # ...
    when 'created' then # ...
    when 'homepage' then # ...
    when 'devsite' then # ...
    when 'authors' then # ...
    when 'description' then # ...
    when 'libpaths' then # ...
    else
      # save the unknown pairs somewhere so that subclasses can deal
      # with them, too.
    end
  end
end

end

Just because your storage representation is flat doesn’t mean your
in-memory object has to be. (And you can define your own #to_yaml on the
Package class that flattens things for saving.)

This is no different than what I wrote for Ruwiki four years ago (I
eschewed YAML because Syck was broken in a couple of different releases
of Ruby.)

-austin

On 10/8/07, Trans [email protected] wrote:

Fair enough, although that’s only 50% wrong :wink:
No, it’s 100% wrong. You said “the only reuse [is] via a subclass.” Just
using the instance as an object is reuse (composition).

[snip]

modules are more versatile than classes. Thus by using all modules for
behavior (and classes as only compositions of modules) maximizes
reusability. And for this simple fact: classes cannot be mixed-in.

Wrong. Look VERY CAREFULLY at your code, Trans. How many of your modules
are used in more than one place?

If the answer is few, then you’re doing it wrong and you’re introducing
negative consequences in terms of maintainability, while not actually
increasing reuse. Most methods are specific behaviour for a given state.
Pretending that by extracting that into modules that youre increasing
reuse is nonsense. Unless you’re actually reusing the code, you’re not
increasing 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.

You’ve lost maintainability and clarity. You’ve lost any sense of good
design.

pieces may prove nicely reusable, too, if well thought out, btw.
Yeah, it’s much cleaner to think in terms of objects. It’s much
preferable to compose than inherit. Delegation is only necessary when
you need to Act As something else.

But my example of extraction of the whole damned class was to make a
point about the limitations of class vs module reuse. For instance,
here’s an example I didn’t mention before. Did you know that if you
use all modules then AOP coding is very simple? It’s easy to prepend a
module relative to other modules in the inheritance chain. But not so
for classes. Dynamic AOP for classes takes some mind-numbing meta-
coding for sure.

That’s part of the problem, I guess: I don’t think that AOP is
worthwhile in Ruby. AOP doesn’t add any readability to the code, in the
end, than doing it a bit smarter. AOP only sort-of makes sense in Java
because Java’s (otherwise) a static language. But even there, it’s not
all that useful.

venture into the meta-coding deep. I’m not insinuating anything
negative in that, btw. I think it’s good that there are all types of
coders. But you seem almost religious about your way of doing things.

That’s because you’re tone-deaf. I’m saying that from experience with
other people actually having to maintain code or having to maintain
other peoples’ code, the way that you’re doing things is nonsense and
reduces overall maintainability.

If you think my code looks like C, you’d be quite wrong; I simply don’t
do metaprogramming where it isn’t appropriate. (I have an experimental
branch of PDF::Writer that used quite a bit of metaprogramming to
encapsulate a number of rules that PDFs impose on objcts; if I ever pick
up PDF::Writer again, then I will probably be going from that
direction.) Most of the problems that I’ve solved haven’t needed meta-
programming and I’m not going to inflict it on others just to show how
kewl I am.

There’s also code that I have written that I can’t show (it’s
work-related) that does stuff within a particular domain that I would
never advocate in any other way. (I have one, in particular, that
overrides const_missing to return a string value representing the name
of the const just tried. The code where you’d use this expects that.)

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.
Of course not. And of course I don’t. But I wish Ruby didn’t make me
have to choice one over the other. It reduces the flexibility of it’s
otherwise extremely elegant inheritance model; and likewise makes
delegation the better choice in more cases than otherwise would be
necessary.

“Necessary” is a matter of opinion. To pick up on a different message
(to which I’ll be replying to here, as well), I consider an object with
50 attributes an abomination. I don’t care whether you’ve gotten those
attributes by mixins or manually writing them; it means you haven’t
thought about your class design well enough. You seem to prefer flat
classes; I think that flat classes are a disaster in waiting.

[snip]

Ah yea, and “If God meant for men to fly, he would have given them
wings.”

You’re arguing that I have the problem, not Ruby. But I’m not arguing
Ruby has a problem, I’m arguing that maybe it could be even better.
Nor do I have a problem. I finished the program yesterday. I didn’ run
into a limitation per-se, I ran in to a “why am I having to make an
ultimately pointless distinction?”

Yeah. You do have a problem and you have been arguing that Ruby has a
problem. If one is suggesting an improvement to something, it’s because
one has hit a pain point. Sometimes those pain points are legitimate;
sometimes they’re like the old joke:

Man: Doctor, it hurts when I put my arm behind my back.
Doctor: Well, don’t put your arm behind your back.

Your example is precisely one of those situations. The distinction, by
the way, MAY be pointless. Inasmuch as it would encourage the sort of
design decisions you’re making and have demonstrated in this discussion?
I’m more than happy to have it there, because if you’re doing it, far
less capable programmers than you would make even dumber decisions from
it.

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.
Now you’re knit picking words. Of course only object instances have
state. But classes, and modules!, define objects.

I’m not nit-picking at all. It’s the fundamental distinction between the
two right now. Classes can be turned into things that have state;
modules can’t. Modules can only add features to objects.

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.
Yep. A well defined interface is an important aspect of code reuse –
that’s true for all forms of composition.

Not even related to what I said. Modules have some generic
applicability.

deceptive conversational tactic. And I wish you’d cut it out. Explain
yourself. What words do you mean? What I have I said that is
nonsensical? And why do you think it’s all in reference to what you
said. What about the point I trying to make?

“If a coder, like yourself, wants to … with a single form of
encapsulation.” You rambled on for two paragraphs as if I had said
something about a single form for development. Which I didn’t. Never
have, never will. (In fact, it’s pretty much you that’s talked about
only using one form for development. I know you don’t, but you’re still
talking nonsense here.)

boundaries. Investigate what it can and can’t do. I bring up ideas and
make suggestions to explore those further, not because I’m stuck, but
because I’m curious.

Really? If that’s the case, then you really need to work on your
presentation skills, because you’ve yet to present something in a way
that says “I’m exploring this…” and instead nearly always say “Ruby
should do this…” while presenting examples that in every single case
could be coded easier and cleaner if you simply stepped back and thought
a little more. The example you opened this discussion with
(LinuxVideoPlayerApplication) is such BAD design that you SHOULD have
been able to see it.

Like I said, Ruby isn’t perfect and there are things that can improve
about it – and yes, you’ve pointed out a few of those areas. But when
it “hurts” to do something one way in Ruby, it usually means that you’re
doing something suboptimally.

I’m forever learning. I didn’t come from a C background and just
started writing my C program’s in Ruby. I learned Ruby as Ruby. And I
try to use Ruby for what it is, and enjoy considering what more it
could be.

Nice misdirection and assumption of the martyr position.

Does this exploration lead me down rough roads sometimes? Damn right
it does. But in the end I’m a better coder for it. Am I the best coder
around here? Of course not, I don’t pretend to be. But you sure do.

Again, nice misdirection. I don’t pretend to be the best coder. I am,
however, a professional software developer that has to deliver a lot of
code on a regular basis. There are things that I know I wouldn’t put up
with from people who worked with me if I had to maintain their code.
There are things that I don’t care about.

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.
Good gracious. You have so utterly missed the whole point I’m not sure
why I continue to type. What was my point Austin? Please, I want you
to put words in my mouth so I can see if there’s actually any
communication going on here.
I haven’t missed the point. You believe that modules are more flexible
than classes and that things would be better if you could mix classes in
the same way you can mix modules in, or at least if you could “properly”
instantiate modules. You may believe that, but in Ruby at least, you’re
wrong.

On 10/8/07, Trans [email protected] wrote:

library reference object. However when I want to use it for creating
distributable packages I mixin Distribution and Dependency modules.
Personally? I’d prefer the former. If I was dumb enough to design
something that required 50 attributes. Let’s pick on your example:

[snip layered redesign]

are improved because now my Package class doesn’t HAVE fifty attributes;
That’s what I mean, Trans: your design approach for mixing in 50
attributes or writing 50 attributes is bad. If you need that many,
your object is PROBABLY way too big. (Yes, there are times when such
things are necessary; they’re extremely uncommon, though.)

Fantastic jobs Austin. Now initialize the class from a YAML file for
me. Did I mention the file spec looks like this:

[…]

It has some 35+ possible entires and some of those have aliases
besides (because I like giving my users some flexibility). Plus it
should be extensible because other utilities (like the distributable
packaging tool) will need additional information.

Come on, show the dumb-dumb how it’s properly done.

class Package
def self.from_yaml(yaml)
pkg = Package.new

  YAML.load(yaml).each do |key, value|
    case key
    when 'package' then # ...
    when 'version' then # ...
    when 'created' then # ...
    when 'homepage' then # ...
    when 'devsite' then # ...
    when 'authors' then # ...
    when 'description' then # ...
    when 'libpaths' then # ...
    else
      # save the unknown pairs somewhere so that subclasses can deal
      # with them, too.
    end
  end
end

end

Just because your storage representation is flat doesn’t mean your
in-memory object has to be. (And you can define your own #to_yaml on the
Package class that flattens things for saving.)

This is no different than what I wrote for Ruwiki four years ago (I
eschewed YAML because Syck was broken in a couple of different releases
of Ruby.)

-austin

On Tue, 2007-10-09 at 00:17 +0900, Austin Z. wrote:

If the answer is few, then you’re doing it wrong and you’re introducing
negative consequences in terms of maintainability, while not actually
increasing reuse. Most methods are specific behaviour for a given state.
Pretending that by extracting that into modules that youre increasing
reuse is nonsense. Unless you’re actually reusing the code, you’re not
increasing reuse.

On the other hand, if you’re reusing them in multiple places, e.g.:

class FooWithBarAndBaz
include Foo
include Bar
include Baz
end

class FooWithBarAndHoge
include Foo
include Bar
include Hoge
end

…you’ve got to create a distinct class up front for every permutation
of features. If you were composing objects instead, you’d be able to
compose objects dynamically, instead of being limited to the particular
compositions that you’ve baked into classes.

Just because your storage representation is flat doesn’t mean your
in-memory object has to be.

I’ve come to recognize a tying of the internal representation to the
serialized form as a code smell, because usually (especially) when the
serialized form is designed to be human-editable, the requirements for
the structure of the two can be very different.

-mental

I’ve been following the drama in this thread with great interest.

I tried to interject a thought a few days ago and it seems to have
fallen on deaf ears.

Let me try again.

The perceived ‘need’ for MI in Ruby comes from a
misunderstanding/ignorance of the difference of the meaning of
inheritance in languages like Ruby vs. languages like Java/C++.

In Java/C++ inheritance is primarily a means of expressing type
relationships, and secondarily a means of sharing implementation.
Because of the statically typed nature of these languages, related
types HAVE to be related by inheritance.

In Ruby, inheritance is solely a mechanism for sharing implementation.
Inheritance in Ruby does not build a type hierarchy, even though it
might superficially appear to.

  1. It doesn’t build a type hierarchy in the sense that two objects
    which can be substituted for each other in a given context don’t have
    to have any kind of implementation relationship, the need only
    correctly implement the set of behaviors required by the user.
  2. It doesn’t build a type hierarcy because in general the whole
    notion of types in Ruby is rather flexible, recall the discussion of
    whether or not it was ‘proper’ to make ranges of floats. Sometimes
    range elements need to have a succ method, sometimes not, depending on
    how you use the resulting Range.

In a statically typed language the coupling of type specification with
implementation leads to a particular set of pressures on the design of
both the language and programs in that language which are different
from the pressures on Ruby and it’s programs. Many of the things
which drove statically typed languages come from addressing problems
caused when compiled code which expected an object to be laid out in
memory a certain way ran across an object which had been miscast,
leading to run-time crashes, or hard to debug behavior. Static typing
provides a mechanism to winnow out some of these bugs at compile time,
however most bugs in the development of any program are more subtle
and arise not from type but from logic errors.

Dynamic languages exhibit different failure behavior. Executable code
is less sensitive to the bits and bytes layout, and the kind of errors
caught by static typing tend to fail faster at run-time with better
debugging information available at the time of failure. The main
reason test-first techniques came out of the dynamic language
community was that it was a ‘substitute’ for static type checking
which actually covers a much broader spectrum of the kind of errors
programmers make.

I certainly understand how this flexibility and decoupling of the
notion of types from inheritance can seem wrong to one trained in
Java/C++ or the like, but the point is that these different
philosophies lead to different approaches to design. Trying to bend
Ruby inheritance and mixins as a means of typing is working against
the strengths of the language, just as trying to manually simulate
dynamic binding in C++ is an indication that you aren’t working with
your technology.

As the old maxim goes, “When in Rome…”


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/