The Case for Multiple-Inheritance

Discussion in 'Ruby' started by Trans, Oct 5, 2007.

  1. Trans

    Trans Guest

    So I working on little lib that's ripe for an adapter pattern, when I
    see quite clearly that I have a bit of a dilemma. I have two clear
    inheritance hierarchies converging. I want to create a
    LinuxVideoPlayerApplication subclass, but it needs to inherit from
    both VideoPlayerApplication and LinuxApplication.

    class VideoPlayerApplication < Application


    class LinuxApplication < Applicaiton

    Oh no!

    class LinuxVideoPlayerApplication < VideoPlayerApplication

    or

    class LinuxVideoPlayerApplication < LinuxApplication

    Ruby forces me make a choice. Which is "more real" I guess is it's
    demand. But the choice is contrived. Both apply, and Ruby's strict
    single-inheritance philosophy does nothing for me in the end except
    make my life more complicated. One way or the other I am going to get
    both behaviors in there. Period.

    So as things are, I'm stuck with making one of them a module instead
    of a class. But then I loose metaclass inheritance, which can be a
    real pain sometimes. I become inclined to make them both modules and
    use separate meta-modules if need be, to keep things nicely symmetric.
    But really, why should I have to make such a fuss? Why do I have to
    draw so many abstract distinctions when there is no such thing in my
    actual model?

    I think it would be a good idea to really give some deep consideration
    as to why modules and classes are distinct in Ruby. It's clear from
    Ruby's source that the distinction is self-inflicted to begin with.
    Why? Are we really gaining anything by the distinction, or are we just
    making things harder for ourselves w/o necessarily realizing it,
    simply because that's the "philosophy".

    Food for thought,
    T.
    Trans, Oct 5, 2007
    #1
    1. Advertising

  2. On 10/5/07, Trans <> wrote:
    > So I working on little lib that's ripe for an adapter pattern, when I
    > see quite clearly that I have a bit of a dilemma. I have two clear
    > inheritance hierarchies converging. I want to create a
    > LinuxVideoPlayerApplication subclass, but it needs to inherit from
    > both VideoPlayerApplication and LinuxApplication.


    I think that you've got a problem here, and it won't be solved with MI.
    You need to reapproach the issue. I have yet to find a time when MI
    makes sense even in C++.

    > class VideoPlayerApplication < Application
    > class LinuxApplication < Application
    >
    > Oh no!
    >
    > class LinuxVideoPlayerApplication < VideoPlayerApplication
    > or
    > class LinuxVideoPlayerApplication < LinuxApplication


    Frankly, I don't think you've got a good design here, without seeing
    anything else.

    A LinuxApplication isn't sensible. What makes a LinuxApplication
    different from a GenericApplication or from a WindowsApplication? In
    other words, I think that you've set yourself up for the dichotomy by
    not considering this the right way.

    Think of it in terms of aspects. What are the aspects that make an
    application a Linux application? How can you pull those in cleanly?


    > Ruby forces me make a choice. Which is "more real" I guess is it's
    > demand. But the choice is contrived. Both apply, and Ruby's strict
    > single-inheritance philosophy does nothing for me in the end except
    > make my life more complicated. One way or the other I am going to get
    > both behaviors in there. Period.


    That's fine, but nothing you've written suggests that MI is a good idea.

    > So as things are, I'm stuck with making one of them a module instead
    > of a class.


    Why?

    Avoid inheritance when you don't need it -- and you need it a lot less
    than you think. Composition is usually a better approach than
    inheritance.

    > But then I loose metaclass inheritance, which can be a
    > real pain sometimes. I become inclined to make them both modules and
    > use separate meta-modules if need be, to keep things nicely symmetric.
    > But really, why should I have to make such a fuss? Why do I have to
    > draw so many abstract distinctions when there is no such thing in my
    > actual model?


    Why are you choosing to implement this in perhaps the worst OO way
    possible? Why have you made metaclass inheritance important? Again:
    consider composition.

    > I think it would be a good idea to really give some deep consideration
    > as to why modules and classes are distinct in Ruby. It's clear from
    > Ruby's source that the distinction is self-inflicted to begin with.
    > Why? Are we really gaining anything by the distinction, or are we just
    > making things harder for ourselves w/o necessarily realizing it,
    > simply because that's the "philosophy".
    >
    > Food for thought,


    I'm sending it back. It's overcooked and watery.

    -austin
    --
    Austin Ziegler * * http://www.halostatue.ca/
    * * http://www.halostatue.ca/feed/
    *
    Austin Ziegler, Oct 5, 2007
    #2
    1. Advertising

  3. Trans

    MenTaLguY Guest

    On Sat, 6 Oct 2007 06:06:45 +0900, Trans <> wrote:
    > I think it would be a good idea to really give some deep consideration
    > as to why modules and classes are distinct in Ruby. Why?


    One reason is to avoid ambiguity about object representations. Let's
    say that instance methods of class A assume one representation, and the
    instance methods of class B assume another, incompatible, representation
    [1].

    class C < A, B
    end

    Should A's methods or B's methods break when called on an instance of
    C?

    One solution I can think of immediately would be for a newly allocated
    instance of C to allocate an instance of A and an instance of B behind
    the scenes, delegating method calls to them as appropriate.

    However, at that point it's starting to sound suspiciously like
    aggregation... have you considered using aggregation rather than just
    inheritance for modeling your problem?

    -mental

    [1] In Ruby 1.8, representations can be incompatible because they either
    used instance variables with conflicting names, or because they are
    of different RBasic types -- e.g. T_STRUCT versus T_DATA
    MenTaLguY, Oct 5, 2007
    #3
  4. MenTaLguY wrote:
    > On Sat, 6 Oct 2007 06:06:45 +0900, Trans <> wrote:
    >> I think it would be a good idea to really give some deep consideration
    >> as to why modules and classes are distinct in Ruby. Why?

    >
    > One reason is to avoid ambiguity about object representations. Let's
    > say that instance methods of class A assume one representation, and the
    > instance methods of class B assume another, incompatible, representation
    > [1].

    ...
    > [1] In Ruby 1.8, representations can be incompatible because they either
    > used instance variables with conflicting names, or because they are
    > of different RBasic types -- e.g. T_STRUCT versus T_DATA


    Isn't ivar conflict an argument against mixins just as much as it is an
    argument against MI?

    Solutions to this have been discussed...

    T_STRUCT vs T_DATA is still a problem for MI, of course. (As is T_DATA
    vs T_DATA when the underlying C types are different.)

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Oct 5, 2007
    #4
  5. Trans

    MenTaLguY Guest

    On Sat, 6 Oct 2007 07:25:13 +0900, Joel VanderWerf <> wrote:
    > Isn't ivar conflict an argument against mixins just as much as it is an
    > argument against MI?


    Yes, although I don't think it's as strong an argument as differing RBasic
    types. Well-designed mixins can usually (not always) avoid using instance
    variables, and the possibility of conflict can be greatly reduced, if you
    give the instance variables meaningful suffixes.

    That isn't to say that I've never experienced an ivar conflict, though...

    -mental
    MenTaLguY, Oct 5, 2007
    #5
  6. Trans

    Trans Guest

    Hi Austin,

    It's been a while. Glad to see your still ready to go a round :)

    On Oct 5, 3:13 pm, "Austin Ziegler" <> wrote:
    > On 10/5/07, Trans <> wrote:
    >
    > > So I working on little lib that's ripe for an adapter pattern, when I
    > > see quite clearly that I have a bit of a dilemma. I have two clear
    > > inheritance hierarchies converging. I want to create a
    > > LinuxVideoPlayerApplication subclass, but it needs to inherit from
    > > both VideoPlayerApplication and LinuxApplication.

    >
    > I think that you've got a problem here, and it won't be solved with MI.
    > You need to reapproach the issue. I have yet to find a time when MI
    > makes sense even in C++.


    Huh. Seems to me whatever you call it, that's exactly how it is going
    to end up. I've encapsulated two different behaviors and they are
    going to end in one place --i.e. multiple inheritance. Whether I
    implement it via classes, modules, composition or even code injection,
    the formal result is the same. That's really the crux of my argument.

    > > class VideoPlayerApplication < Application
    > > class LinuxApplication < Application

    >
    > > Oh no!

    >
    > > class LinuxVideoPlayerApplication < VideoPlayerApplication
    > > or
    > > class LinuxVideoPlayerApplication < LinuxApplication

    >
    > Frankly, I don't think you've got a good design here, without seeing
    > anything else.
    >
    > A LinuxApplication isn't sensible. What makes a LinuxApplication
    > different from a GenericApplication or from a WindowsApplication? In
    > other words, I think that you've set yourself up for the dichotomy by
    > not considering this the right way.
    >
    > Think of it in terms of aspects. What are the aspects that make an
    > application a Linux application? How can you pull those in cleanly?


    Why do you think it is not sensible? I would say, a LinuxApplication
    has a different null device method for instance, just to pick
    something out the blue. Do you think it isn't sensible b/c a
    LinuxApplication isn't something to be initialized --that it is just a
    base class? But then the VideoPlayerApplication class isn't sensible
    either for the same reason. Neither is useful until they come
    together. Or is it not sensible b/c a LinuxApplication is something
    more general than a VideoPlayerApplication? Well, that's a fair
    argument for making the LinuxApplication the module of the two. But
    still that's just a matter of degree not of completely different
    character. Or is it not sensible for some other reason?

    > > Ruby forces me make a choice. Which is "more real" I guess is it's
    > > demand. But the choice is contrived. Both apply, and Ruby's strict
    > > single-inheritance philosophy does nothing for me in the end except
    > > make my life more complicated. One way or the other I am going to get
    > > both behaviors in there. Period.

    >
    > That's fine, but nothing you've written suggests that MI is a good idea.
    >
    > > So as things are, I'm stuck with making one of them a module instead
    > > of a class.

    >
    > Why?
    >
    > Avoid inheritance when you don't need it -- and you need it a lot less
    > than you think. Composition is usually a better approach than
    > inheritance.


    What this point of having inheritance if we're just going to avoid it?
    I can use composition in any language. Ruby's an OOP. Shouldn't we use
    OOP and it's patterns where they apply? Isn't that the whole point?
    Plus composition is generally slower. On an already slow language like
    Ruby that kind of stinks.

    > > But then I loose metaclass inheritance, which can be a
    > > real pain sometimes. I become inclined to make them both modules and
    > > use separate meta-modules if need be, to keep things nicely symmetric.
    > > But really, why should I have to make such a fuss? Why do I have to
    > > draw so many abstract distinctions when there is no such thing in my
    > > actual model?

    >
    > Why are you choosing to implement this in perhaps the worst OO way
    > possible? Why have you made metaclass inheritance important? Again:
    > consider composition.


    How is it the worse OO way possible? What you are advocating is not
    OOP at all. Don't get me wrong. I have nothing against composition,
    but I'm surprised you would suggest it in an OOP language to model
    something that has a clear inheritance structure.

    > > I think it would be a good idea to really give some deep consideration
    > > as to why modules and classes are distinct in Ruby. It's clear from
    > > Ruby's source that the distinction is self-inflicted to begin with.
    > > Why? Are we really gaining anything by the distinction, or are we just
    > > making things harder for ourselves w/o necessarily realizing it,
    > > simply because that's the "philosophy".

    >
    > > Food for thought,

    >
    > I'm sending it back. It's overcooked and watery.


    LOL.

    That's because it's stew not potatoes ;)

    T.
    Trans, Oct 6, 2007
    #6
  7. I agree with Austin. And here's a good explanation as to why:

    http://brighton.ncsa.uiuc.edu/prajlich/T/node14.html

    > I can use composition in any language. Ruby's an OOP. Shouldn't we use
    > OOP and it's patterns where they apply? Isn't that the whole point?


    In summary: inheritance is "white-box reuse" and composition is
    "black-box reuse". There are strong arguments that essentially point
    out that inheritance is a tighter coupling of parts and less
    encapsulated in terms of abstraction than composition, which also
    happens to be my favorite of the two.


    Cheers,

    -r.

    On 10/5/07, Trans <> wrote:
    > Hi Austin,
    >
    > It's been a while. Glad to see your still ready to go a round :)
    >
    > On Oct 5, 3:13 pm, "Austin Ziegler" <> wrote:
    > > On 10/5/07, Trans <> wrote:
    > >
    > > > So I working on little lib that's ripe for an adapter pattern, when I
    > > > see quite clearly that I have a bit of a dilemma. I have two clear
    > > > inheritance hierarchies converging. I want to create a
    > > > LinuxVideoPlayerApplication subclass, but it needs to inherit from
    > > > both VideoPlayerApplication and LinuxApplication.

    > >
    > > I think that you've got a problem here, and it won't be solved with MI.
    > > You need to reapproach the issue. I have yet to find a time when MI
    > > makes sense even in C++.

    >
    > Huh. Seems to me whatever you call it, that's exactly how it is going
    > to end up. I've encapsulated two different behaviors and they are
    > going to end in one place --i.e. multiple inheritance. Whether I
    > implement it via classes, modules, composition or even code injection,
    > the formal result is the same. That's really the crux of my argument.
    >
    > > > class VideoPlayerApplication < Application
    > > > class LinuxApplication < Application

    > >
    > > > Oh no!

    > >
    > > > class LinuxVideoPlayerApplication < VideoPlayerApplication
    > > > or
    > > > class LinuxVideoPlayerApplication < LinuxApplication

    > >
    > > Frankly, I don't think you've got a good design here, without seeing
    > > anything else.
    > >
    > > A LinuxApplication isn't sensible. What makes a LinuxApplication
    > > different from a GenericApplication or from a WindowsApplication? In
    > > other words, I think that you've set yourself up for the dichotomy by
    > > not considering this the right way.
    > >
    > > Think of it in terms of aspects. What are the aspects that make an
    > > application a Linux application? How can you pull those in cleanly?

    >
    > Why do you think it is not sensible? I would say, a LinuxApplication
    > has a different null device method for instance, just to pick
    > something out the blue. Do you think it isn't sensible b/c a
    > LinuxApplication isn't something to be initialized --that it is just a
    > base class? But then the VideoPlayerApplication class isn't sensible
    > either for the same reason. Neither is useful until they come
    > together. Or is it not sensible b/c a LinuxApplication is something
    > more general than a VideoPlayerApplication? Well, that's a fair
    > argument for making the LinuxApplication the module of the two. But
    > still that's just a matter of degree not of completely different
    > character. Or is it not sensible for some other reason?
    >
    > > > Ruby forces me make a choice. Which is "more real" I guess is it's
    > > > demand. But the choice is contrived. Both apply, and Ruby's strict
    > > > single-inheritance philosophy does nothing for me in the end except
    > > > make my life more complicated. One way or the other I am going to get
    > > > both behaviors in there. Period.

    > >
    > > That's fine, but nothing you've written suggests that MI is a good idea.
    > >
    > > > So as things are, I'm stuck with making one of them a module instead
    > > > of a class.

    > >
    > > Why?
    > >
    > > Avoid inheritance when you don't need it -- and you need it a lot less
    > > than you think. Composition is usually a better approach than
    > > inheritance.

    >
    > What this point of having inheritance if we're just going to avoid it?
    > I can use composition in any language. Ruby's an OOP. Shouldn't we use
    > OOP and it's patterns where they apply? Isn't that the whole point?
    > Plus composition is generally slower. On an already slow language like
    > Ruby that kind of stinks.
    >
    > > > But then I loose metaclass inheritance, which can be a
    > > > real pain sometimes. I become inclined to make them both modules and
    > > > use separate meta-modules if need be, to keep things nicely symmetric.
    > > > But really, why should I have to make such a fuss? Why do I have to
    > > > draw so many abstract distinctions when there is no such thing in my
    > > > actual model?

    > >
    > > Why are you choosing to implement this in perhaps the worst OO way
    > > possible? Why have you made metaclass inheritance important? Again:
    > > consider composition.

    >
    > How is it the worse OO way possible? What you are advocating is not
    > OOP at all. Don't get me wrong. I have nothing against composition,
    > but I'm surprised you would suggest it in an OOP language to model
    > something that has a clear inheritance structure.
    >
    > > > I think it would be a good idea to really give some deep consideration
    > > > as to why modules and classes are distinct in Ruby. It's clear from
    > > > Ruby's source that the distinction is self-inflicted to begin with.
    > > > Why? Are we really gaining anything by the distinction, or are we just
    > > > making things harder for ourselves w/o necessarily realizing it,
    > > > simply because that's the "philosophy".

    > >
    > > > Food for thought,

    > >
    > > I'm sending it back. It's overcooked and watery.

    >
    > LOL.
    >
    > That's because it's stew not potatoes ;)
    >
    > T.
    >
    >
    >



    --
    "We can try to do it by breaking free of the mental prison of
    separation and exclusion and see the world in its interconnectedness
    and non-separability, allowing new alternatives to emerge." -- after
    Vandana Shiva
    Rudi Cilibrasi, Oct 6, 2007
    #7
  8. Trans

    Eric Hodel Guest

    On Oct 5, 2007, at 16:02 , Trans wrote:

    > What this point of having inheritance if we're just going to avoid it?
    > I can use composition in any language. Ruby's an OOP. Shouldn't we use
    > OOP and it's patterns where they apply? Isn't that the whole point?


    No.

    OO features are just another tool to use when you need it (note that
    I said need, not want). Just because you can use an eight-pound
    sledge for any nail-driving purpose doesn't mean you should.
    Likewise you shouldn't use complicated OO features when simple
    procedural code will suffice.

    Keeping things simple benefits everyone, but yourself most
    importantly. There's no reason to construct something so large you
    can barely maintain or understand it.

    WTF had an excellent post about this, including this quote from
    Michael A. Jackson's Principles of Program Design:

    > Programmers [...] often take refuge in an understandable, but
    > disastrous, inclination towards complexity and ingenuity in their
    > work. Forbidden to design anything larger than a program, they
    > respond by making that program intricate enough to challenge their
    > professional skill.


    http://worsethanfailure.com/Comments/The-Mythical-Business-Layer.aspx

    Instead of starting with objects, you should start with a method,
    then add another. Objects will spring out of it naturally as you
    refactor for reuse.

    Attempting to determine your objects before writing any methods is
    like performing surgery with meat-hooks and salad tongs. It can be
    done, but most of the time you'll end up with a sloppy, sagging mess.

    --
    Poor workers blame their tools. Good workers build better tools. The
    best workers get their tools to do the work for them. -- Syndicate Wars
    Eric Hodel, Oct 6, 2007
    #8
  9. On 10/5/07, Trans <> wrote:
    > It's been a while. Glad to see your still ready to go a round :)


    > On Oct 5, 3:13 pm, "Austin Ziegler" <> wrote:
    >> On 10/5/07, Trans <> wrote:
    >>> So I working on little lib that's ripe for an adapter pattern, when
    >>> I see quite clearly that I have a bit of a dilemma. I have two clear
    >>> inheritance hierarchies converging. I want to create a
    >>> LinuxVideoPlayerApplication subclass, but it needs to inherit from
    >>> both VideoPlayerApplication and LinuxApplication.

    >> I think that you've got a problem here, and it won't be solved with MI.
    >> You need to reapproach the issue. I have yet to find a time when MI
    >> makes sense even in C++.

    > Huh. Seems to me whatever you call it, that's exactly how it is going
    > to end up. I've encapsulated two different behaviors and they are
    > going to end in one place --i.e. multiple inheritance. Whether I
    > implement it via classes, modules, composition or even code injection,
    > the formal result is the same. That's really the crux of my argument.


    The problem with your argument is that it isn't actually based on
    something correct. Composition isn't at all related to MI, although
    delegation can fake it out pretty well, and with fewer problems (since
    you're managing your delegation directly).

    What you have is not a LinuxVideoPlayerAppllication but an Application
    for Linux with VideoPlayer capabilities (this actually implies a lot
    more than just what's written, but I'll leave it as that for now).

    It's a bit harder to talk about the design because, as I said, it's
    unclear what a LinuxApplication has that's separate from a generic
    Application or why inheritance (of any sort) is the way to model that.

    >>> So as things are, I'm stuck with making one of them a module instead
    >>> of a class.

    >> Why?
    >>
    >> Avoid inheritance when you don't need it -- and you need it a lot
    >> less than you think. Composition is usually a better approach than
    >> inheritance.

    > What this point of having inheritance if we're just going to avoid it?
    > I can use composition in any language. Ruby's an OOP. Shouldn't we use
    > OOP and it's patterns where they apply? Isn't that the whole point?
    > Plus composition is generally slower. On an already slow language like
    > Ruby that kind of stinks.


    There's nothing inherently slower about composition. You should use an
    inheritance model when you can clearly say that something IS-A rather
    than HAS-A. Let's consider:

    A Video Player Application on Linux

    Right? Well, it IS an Application. It HAS Linux support and HAS the
    ability to play Video. One can break down Video support several ways,
    too (and probably should). A video player has something that reads the
    file (Reader), passes it through a (polymorphic with inheritance) Codec,
    and then takes the Audio and Video streams and sends them to a
    SoundPlayer and DisplayBuffer, that may or may not actually be visible
    on screen.

    Inheritance is important and powerful, but should only be used to
    represent things that are essentially interchangeable. Otherwise,
    composition is better.

    >>> But then I loose metaclass inheritance, which can be a
    >>> real pain sometimes. I become inclined to make them both modules and
    >>> use separate meta-modules if need be, to keep things nicely symmetric.
    >>> But really, why should I have to make such a fuss? Why do I have to
    >>> draw so many abstract distinctions when there is no such thing in my
    >>> actual model?

    >> Why are you choosing to implement this in perhaps the worst OO way
    >> possible? Why have you made metaclass inheritance important? Again:
    >> consider composition.

    > How is it the worse OO way possible? What you are advocating is not
    > OOP at all. Don't get me wrong. I have nothing against composition,
    > but I'm surprised you would suggest it in an OOP language to model
    > something that has a clear inheritance structure.


    But it doesn't have a clear inheritance structure. It's a contrived
    inheritance structure. Do you consider JavaScript an OO language? You
    should, because it is. It also doesn't have inheritance by default. (It
    can be added, but it's not there by default.)

    Like I said, I have yet to see where MI is better than composition and
    delegation.

    -austin
    --
    Austin Ziegler * * http://www.halostatue.ca/
    * * http://www.halostatue.ca/feed/
    *
    Austin Ziegler, Oct 6, 2007
    #9
  10. --=-JJ2uY/1lcl2eOzCCFUfG
    Content-Type: multipart/alternative; boundary="=-24/9nLeEDLiKmCRYoFTA"


    --=-24/9nLeEDLiKmCRYoFTA
    Content-Type: text/plain
    Content-Transfer-Encoding: quoted-printable

    On Sat, 2007-06-10 at 07:13 +0900, Austin Ziegler wrote:

    > Avoid inheritance when you don't need it -- and you need it a lot less
    > than you think. Composition is usually a better approach than
    > inheritance.



    This is the big thing about OOP that I don't like: the "golden hammer"
    solution of making everything a class and using inheritance as the
    be-all, end-all of construction.

    Inheritance makes things fragile, not robust. It interferes with
    re-usability in most circumstances instead of enhancing it. Why is it
    such a popular technique?!

    --=20
    Michael T. Richter <> (GoogleTalk:
    )
    There are two ways of constructing a software design. One way is to make
    it so simple that there are obviously no deficiencies. And the other way
    is to make it so complicated that there are no obvious deficiencies.
    (Charles Hoare)

    --=-24/9nLeEDLiKmCRYoFTA
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: quoted-printable

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
    <HTML>
    <HEAD>
    <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; CHARSET=3DUTF-8">
    <META NAME=3D"GENERATOR" CONTENT=3D"GtkHTML/3.12.1">
    </HEAD>
    <BODY>
    On Sat, 2007-06-10 at 07:13 +0900, Austin Ziegler wrote:
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">Avoid inheritance when you don't need it -- and you=
    need it a lot less</FONT>
    <FONT COLOR=3D"#000000">than you think. Composition is usually a better app=
    roach than</FONT>
    <FONT COLOR=3D"#000000">inheritance.</FONT>
    </PRE>
    </BLOCKQUOTE>
    <BR>
    This is the big thing about OOP that I don't like: the &quot;golden hammer&=
    quot; solution of making everything a class and using inheritance as the be=
    -all, end-all of construction.<BR>
    <BR>
    Inheritance makes things fragile, not robust.&nbsp; It interferes with re-u=
    sability in most circumstances instead of enhancing it.&nbsp; Why is it suc=
    h a popular technique?!<BR>
    <BR>
    <TABLE CELLSPACING=3D"0" CELLPADDING=3D"0" WIDTH=3D"100%">
    <TR>
    <TD>
    -- <BR>
    <B>Michael T. Richter</B> &lt;<A HREF=3D"mailto:">ttmri=
    </A>&gt; (<B>GoogleTalk:</B> )<BR>
    <I>There are two ways of constructing a software design. One way is to make=
    it so simple that there are obviously no deficiencies. And the other way i=
    s to make it so complicated that there are no obvious deficiencies. (Charle=
    s Hoare)</I>
    </TD>
    </TR>
    </TABLE>
    </BODY>
    </HTML>

    --=-24/9nLeEDLiKmCRYoFTA--

    --=-JJ2uY/1lcl2eOzCCFUfG
    Content-Type: application/pgp-signature; name=signature.asc
    Content-Description: This is a digitally signed message part

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.3 (GNU/Linux)

    iD8DBQBHBtijLqyWkKVQ54QRAvlCAJ97TWf3BAb+yrbWQYi9Ku+4mL5ORgCeMBXg
    K7GZCzOwl25cBLErJtu/ENI=
    =5C05
    -----END PGP SIGNATURE-----

    --=-JJ2uY/1lcl2eOzCCFUfG--
    Michael T. Richter, Oct 6, 2007
    #10
  11. --=-KsW0G4xOpuM1Wi7RJj69
    Content-Type: multipart/alternative; boundary="=-W+d/wcyIfoDcraZHToqk"


    --=-W+d/wcyIfoDcraZHToqk
    Content-Type: text/plain
    Content-Transfer-Encoding: quoted-printable

    On Sat, 2007-06-10 at 08:02 +0900, Trans wrote:

    > > Avoid inheritance when you don't need it -- and you need it a lot less
    > > than you think. Composition is usually a better approach than
    > > inheritance.




    > What this point of having inheritance if we're just going to avoid it?



    "I use it because I have it" is not a valid reason for using any
    language feature of any kind. Why do we have the plethora of
    $-variables in Ruby if we're just going to avoid it? Why do we have the
    loop method if we generally don't use it? Why do we have any language
    constructs at all beyond 16 basic assembly language statements, in fact?

    Switch over to cars for a moment. A car mechanic -- a good one, anyway
    -- will have a huge chest of tools. Some of those tools only get used
    perhaps once or twice a year. Why does he have them? Because when
    they're used, they're the single best tool for the job and other tools
    are just not adequate is why.

    The features of a programming languages (as well as the set of
    programming languages known) are the "mechanics tools" of the
    professional programmer. If you're a decent programmer, you have quite
    a few of them (much like a decent mechanic has quite a few tools in his
    chest). But just like a decent mechanic doesn't randomly do brake
    adjustments because he happens to have a set of brake calipers, you
    shouldn't be stuffing everything into inheritance trees just because the
    language you use supports inheritance.

    Object-oriented programming has at its core objects. Inheritance is
    just one tool used for manipulating objects. Composition is another.
    Your question could easily be reworded (and it's a rewording I prefer
    since this is the normal problem in libraries and applications) to:
    "What is the point of supporting composition and aggregation if we're
    just going to avoid them?"

    Branch out. Investigate other ways of constructing programs. Look
    specifically into decoupling of objects if you want a more flexible and
    maintainable approach to building systems.


    > I can use composition in any language. Ruby's an OOP. Shouldn't we use
    > OOP and it's patterns where they apply? Isn't that the whole point?



    Look into the Gang of Four's Design Patterns book sometime. Count the
    patterns that use composition and aggregation over inheritance. And
    read the part that warns against overuse of inheritance....

    --=20
    Michael T. Richter <> (GoogleTalk:
    )
    We should sell bloat credits, the way the government sells pollution
    credits. Everybody's assigned a certain amount of bloat, and if they go
    over, they have to purchase bloat credits from some other group that's
    been more careful. (Bent Hagemark)

    --=-W+d/wcyIfoDcraZHToqk
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: quoted-printable

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
    <HTML>
    <HEAD>
    <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; CHARSET=3DUTF-8">
    <META NAME=3D"GENERATOR" CONTENT=3D"GtkHTML/3.12.1">
    </HEAD>
    <BODY>
    On Sat, 2007-06-10 at 08:02 +0900, Trans wrote:
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">&gt; Avoid inheritance when you don't need it -- an=
    d you need it a lot less</FONT>
    <FONT COLOR=3D"#000000">&gt; than you think. Composition is usually a bette=
    r approach than</FONT>
    <FONT COLOR=3D"#000000">&gt; inheritance.</FONT>
    </PRE>
    </BLOCKQUOTE>
    <PRE>

    </PRE>
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">What this point of having inheritance if we're just=
    going to avoid it?</FONT>
    </PRE>
    </BLOCKQUOTE>
    <BR>
    &quot;I use it because I have it&quot; is <B>not</B> a valid reason for usi=
    ng <B>any</B> language feature of <B>any</B> kind.&nbsp; Why do we have the=
    plethora of $-variables in Ruby if we're just going to avoid it?&nbsp; Why=
    do we have the loop method if we generally don't use it?&nbsp; Why do we h=
    ave <B>any</B> language constructs at all beyond 16 basic assembly language=
    statements, in fact?<BR>
    <BR>
    Switch over to cars for a moment.&nbsp; A car mechanic -- a good one, anywa=
    y -- will have a <B><I>huge</I></B> chest of tools.&nbsp; Some of those too=
    ls only get used perhaps once or twice a year.&nbsp; Why does he have them?=
    &nbsp; Because when they're used, they're the single best tool for the job =
    and other tools are just not adequate is why.<BR>
    <BR>
    The features of a programming languages (as well as the set of programming =
    languages known) are the &quot;mechanics tools&quot; of the professional pr=
    ogrammer.&nbsp; If you're a decent programmer, you have quite a few of them=
    (much like a decent mechanic has quite a few tools in his chest).&nbsp; Bu=
    t just like a decent mechanic doesn't randomly do brake adjustments because=
    he happens to have a set of brake calipers, you shouldn't be stuffing ever=
    ything into inheritance trees just because the language you use supports in=
    heritance.<BR>
    <BR>
    Object-oriented programming has at its core objects.&nbsp; Inheritance is j=
    ust one tool used for manipulating objects.&nbsp; Composition is another.&n=
    bsp; Your question could easily be reworded (and it's a rewording I prefer =
    since this is the normal problem in libraries and applications) to: &quot;W=
    hat is the point of supporting composition and aggregation if we're just go=
    ing to avoid them?&quot;<BR>
    <BR>
    Branch out.&nbsp; Investigate other ways of constructing programs.&nbsp; Lo=
    ok specifically into decoupling of objects if you want a more flexible and =
    maintainable approach to building systems.<BR>
    <BR>
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">I can use composition in any language. Ruby's an OO=
    P. Shouldn't we use</FONT>
    <FONT COLOR=3D"#000000">OOP and it's patterns where they apply? Isn't that =
    the whole point?</FONT>
    </PRE>
    </BLOCKQUOTE>
    <BR>
    Look into the Gang of Four's Design Patterns book sometime.&nbsp; Count the=
    patterns that use composition and aggregation over inheritance.&nbsp; And =
    read the part that warns against overuse of inheritance....<BR>
    <BR>
    <TABLE CELLSPACING=3D"0" CELLPADDING=3D"0" WIDTH=3D"100%">
    <TR>
    <TD>
    -- <BR>
    <B>Michael T. Richter</B> &lt;<A HREF=3D"mailto:">ttmri=
    </A>&gt; (<B>GoogleTalk:</B> )<BR>
    <I>We should sell bloat credits, the way the government sells pollution cre=
    dits. Everybody's assigned a certain amount of bloat, and if they go over, =
    they have to purchase bloat credits from some other group that's been more =
    careful. (Bent Hagemark)</I>
    </TD>
    </TR>
    </TABLE>
    </BODY>
    </HTML>

    --=-W+d/wcyIfoDcraZHToqk--

    --=-KsW0G4xOpuM1Wi7RJj69
    Content-Type: application/pgp-signature; name=signature.asc
    Content-Description: This is a digitally signed message part

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.3 (GNU/Linux)

    iD8DBQBHBtvVLqyWkKVQ54QRAlaXAKDP+Z14W5ksv82h8bDRoO5qtihqDwCglOlp
    EzB/q9kIkRwWRnfEImSO5zU=
    =XW7y
    -----END PGP SIGNATURE-----

    --=-KsW0G4xOpuM1Wi7RJj69--
    Michael T. Richter, Oct 6, 2007
    #11
  12. On 10/5/07, Rudi Cilibrasi <> wrote:
    > I agree with Austin. And here's a good explanation as to why:
    >
    > http://brighton.ncsa.uiuc.edu/prajlich/T/node14.html
    >
    > > I can use composition in any language. Ruby's an OOP. Shouldn't we use
    > > OOP and it's patterns where they apply? Isn't that the whole point?

    >
    > In summary: inheritance is "white-box reuse" and composition is
    > "black-box reuse". There are strong arguments that essentially point
    > out that inheritance is a tighter coupling of parts and less
    > encapsulated in terms of abstraction than composition, which also
    > happens to be my favorite of the two.


    One should also realize the effect of the different meaning of
    inheritance in languages like C++ and languages like Ruby.

    In statically typed languages like C++ inheritance is first and
    foremost a mechanism for categorizing and constructing types, where as
    in Ruby its a mechanism for reusing implementation. The user of an
    object in Ruby is unaffected by whether or not that object obtained
    it's capabilities via implementation inheritance or independent
    implementation of the required methods.

    C++ like languages treat classes like cookie cutters and users of
    object rely on all of the cookies coming out of a particular cookie
    cutter to have a particular shape, and for sub-cookie cutters to leave
    the basic shape unchanged and just add a bump to it. In other words,
    both methods and users have intimate knowledge (which many
    implementations rely on) of the layout of objects and how that layout
    is affected by inheritance.

    Dynamically typed oo languages hide the actual shape of the cookie
    from the user of the cookie.

    And among the dynamically typed languages, Ruby is one of the most
    dynamically typed. For example in Smalltalk, methods know about the
    shape of the cookie in the sense that the compiler knows that instance
    variable x is at offset y from the beginning of every instance which a
    method is attached to (whether the instance is actually an instance of
    a subclass or not). In Ruby instance variables are dynamically
    resolved via a hash, and all instances of a particular class don't
    even have to have all of the instance variables mentioned in methods
    of the class at any given time.

    Because of this, many of the things which "have to be true" in a
    language like C++, or to a slightly lesser extent Java, are irrelevant
    in dynamic languages like Smalltalk, and to a greater extent in Ruby.
    And it also means that what's a white box in a language is actually
    considerably darker, even if not completely black in a language like
    Ruby.

    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
    Rick DeNatale, Oct 6, 2007
    #12
  13. Trans

    Ryan Davis Guest

    On Oct 5, 2007, at 17:37 , Michael T. Richter wrote:

    > This is the big thing about OOP that I don't like: the "golden =20
    > hammer" solution of making everything a class and using inheritance =20=


    > as the be-all, end-all of construction.
    >
    > Inheritance makes things fragile, not robust. It interferes with =20
    > re-usability in most circumstances instead of enhancing it. Why is =20=


    > it such a popular technique?!


    While I agree with your following email (=AB"I use it because I have =20
    it" is not a valid reason for using any language feature of any =20
    kind.=BB) whole-heartedly, I disagree thoroughly with the above claims. =20=

    I suggest it is such a popular technique because it disproves your =20
    claims more often than not.
    Ryan Davis, Oct 6, 2007
    #13
  14. On Oct 5, 2007, at 7:02 PM, Trans wrote:

    > What this point of having inheritance if we're just going to avoid it?


    Maybe the point, given Ruby's modules and single inheritance, is that
    each different subclass can mix-in a different module set.

    module X
    end

    module Y
    end

    class A
    end

    class AX
    include X
    end

    class AY
    include Y
    end

    class AXY
    include X
    include Y
    end

    where
    X = Linux
    Y = VideoPlayer
    A = Application

    I don't know that you can actually re-structure your code in this
    way, but if you can, wouldn't it be more in tune with Ruby's
    strengths than the class structure you are trying to impose?

    Regards, Morton
    Morton Goldberg, Oct 6, 2007
    #14
  15. --=-3Ly+Bh5SO73GQiweOmsE
    Content-Type: multipart/alternative; boundary="=-nx213ZHHki82TZXAV0Os"


    --=-nx213ZHHki82TZXAV0Os
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: quoted-printable

    On Sat, 2007-06-10 at 10:13 +0900, Ryan Davis wrote:

    > > This is the big thing about OOP that I don't like: the "golden =20
    > > hammer" solution of making everything a class and using inheritance =20
    > > as the be-all, end-all of construction.




    > > Inheritance makes things fragile, not robust. It interferes with =20
    > > re-usability in most circumstances instead of enhancing it. Why is =20
    > > it such a popular technique?!




    > While I agree with your following email (=C2=AB"I use it because I have =20
    > it" is not a valid reason for using any language feature of any =20
    > kind.=C2=BB) whole-heartedly, I disagree thoroughly with the above claims=

    =20
    > I suggest it is such a popular technique because it disproves your =20
    > claims more often than not.



    Do you really mean to be using "proof by popularity"-style arguments
    here? Because if you do, Ruby is a worse programming language than,
    say, Python. Or Java. Or C++. Or C. Or COBOL (!).

    I have tended to find zero correlation between popularity and quality.
    Between, as the old chestnut goes, "truth" and the "number of votaries".

    --=20
    Michael T. Richter <> (GoogleTalk:
    )
    We should sell bloat credits, the way the government sells pollution
    credits. Everybody's assigned a certain amount of bloat, and if they go
    over, they have to purchase bloat credits from some other group that's
    been more careful. (Bent Hagemark)

    --=-nx213ZHHki82TZXAV0Os
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: quoted-printable

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
    <HTML>
    <HEAD>
    <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; CHARSET=3DUTF-8">
    <META NAME=3D"GENERATOR" CONTENT=3D"GtkHTML/3.12.1">
    </HEAD>
    <BODY>
    On Sat, 2007-06-10 at 10:13 +0900, Ryan Davis wrote:
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">&gt; This is the big thing about OOP that I don't l=
    ike: the &quot;golden </FONT>
    <FONT COLOR=3D"#000000">&gt; hammer&quot; solution of making everything a c=
    lass and using inheritance </FONT>
    <FONT COLOR=3D"#000000">&gt; as the be-all, end-all of construction.</FONT>
    </PRE>
    </BLOCKQUOTE>
    <BR>
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">&gt; Inheritance makes things fragile, not robust. =
    It interferes with </FONT>
    <FONT COLOR=3D"#000000">&gt; re-usability in most circumstances instead of =
    enhancing it. Why is </FONT>
    <FONT COLOR=3D"#000000">&gt; it such a popular technique?!</FONT>
    </PRE>
    </BLOCKQUOTE>
    <PRE>

    </PRE>
    <BLOCKQUOTE TYPE=3DCITE>
    <PRE>
    <FONT COLOR=3D"#000000">While I agree with your following email («&quo=
    t;I use it because I have </FONT>
    <FONT COLOR=3D"#000000">it&quot; is not a valid reason for using any langua=
    ge feature of any </FONT>
    <FONT COLOR=3D"#000000">kind.») whole-heartedly, I disagree thoroughly=
    with the above claims. </FONT>
    <FONT COLOR=3D"#000000">I suggest it is such a popular technique because it=
    disproves your </FONT>
    <FONT COLOR=3D"#000000">claims more often than not.</FONT>
    </PRE>
    </BLOCKQUOTE>
    <BR>
    Do you <B>really</B> mean to be using &quot;proof by popularity&quot;-style=
    arguments here?&nbsp; Because if you do, Ruby is a worse programming langu=
    age than, say, Python.&nbsp; Or Java.&nbsp; Or C++.&nbsp; Or C.&nbsp; Or CO=
    BOL (!).<BR>
    <BR>
    I have tended to find zero correlation between popularity and quality.&nbsp=
    ; Between, as the old chestnut goes, &quot;truth&quot; and the &quot;number=
    of votaries&quot;.<BR>
    <BR>
    <TABLE CELLSPACING=3D"0" CELLPADDING=3D"0" WIDTH=3D"100%">
    <TR>
    <TD>
    -- <BR>
    <B>Michael T. Richter</B> &lt;<A HREF=3D"mailto:">ttmri=
    </A>&gt; (<B>GoogleTalk:</B> )<BR>
    <I>We should sell bloat credits, the way the government sells pollution cre=
    dits. Everybody's assigned a certain amount of bloat, and if they go over, =
    they have to purchase bloat credits from some other group that's been more =
    careful. (Bent Hagemark)</I>
    </TD>
    </TR>
    </TABLE>
    </BODY>
    </HTML>

    --=-nx213ZHHki82TZXAV0Os--

    --=-3Ly+Bh5SO73GQiweOmsE
    Content-Type: application/pgp-signature; name=signature.asc
    Content-Description: This is a digitally signed message part

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.3 (GNU/Linux)

    iD8DBQBHBv+OLqyWkKVQ54QRAuh6AKCJ4riEeJs3PjVtVtPppcGSmdrssQCgyb/8
    lb0LIOilyNukvPYGtnqoeaU=
    =vuT3
    -----END PGP SIGNATURE-----

    --=-3Ly+Bh5SO73GQiweOmsE--
    Michael T. Richter, Oct 6, 2007
    #15
  16. I'm all with you on that :p

    People on this list tend to think *only* as "duck typing": don't care about
    the actual class of an object as long as the object responds as it should.

    In my work, I *need* to reason about the types of my objects. They are not
    instances, they are instances of classes (=models) and I need to reason
    about those models. As soon as you're thinking that way, you *have* to
    have multiple inheritance because single inheritance is not enough.

    For now, I'm stuck with using modules to emulate some kind of multiple
    inheritance. It sucks.

    Sylvain
    Sylvain Joyeux, Oct 6, 2007
    #16
  17. > Yes, although I don't think it's as strong an argument as differing
    > RBasic types. Well-designed mixins can usually (not always) avoid using
    > instance variables, and the possibility of conflict can be greatly
    > reduced, if you give the instance variables meaningful suffixes.

    Yes. You have to think, when writing mixins, in the context of *all other
    mixins they will have to interact with*. Mmmmmm ... looks like MI problem
    to me.

    Sylvain
    Sylvain Joyeux, Oct 6, 2007
    #17
  18. Trans

    Pat Maddox Guest

    On 10/5/07, Sylvain Joyeux <> wrote:
    > > Yes, although I don't think it's as strong an argument as differing
    > > RBasic types. Well-designed mixins can usually (not always) avoid using
    > > instance variables, and the possibility of conflict can be greatly
    > > reduced, if you give the instance variables meaningful suffixes.

    > Yes. You have to think, when writing mixins, in the context of *all other
    > mixins they will have to interact with*. Mmmmmm ... looks like MI problem
    > to me.
    >
    > Sylvain
    >
    >


    I'm probably just being naive here, but what problems does MI solve
    that mixins can't?

    Pat
    Pat Maddox, Oct 6, 2007
    #18
  19. Trans

    Pat Maddox Guest

    On 10/5/07, Sylvain Joyeux <> wrote:
    > I'm all with you on that :p
    >
    > People on this list tend to think *only* as "duck typing": don't care about
    > the actual class of an object as long as the object responds as it should.
    >
    > In my work, I *need* to reason about the types of my objects. They are not
    > instances, they are instances of classes (=models) and I need to reason
    > about those models. As soon as you're thinking that way, you *have* to
    > have multiple inheritance because single inheritance is not enough.
    >
    > For now, I'm stuck with using modules to emulate some kind of multiple
    > inheritance. It sucks.
    >
    > Sylvain
    >
    >


    It's funny because a lot of people on this list have a hard time
    wrapping their head around duck-typing :) Not that it's hard of
    course, but foreign to a lot of people.

    I think what you mean is that experienced Rubyists tend to think in
    terms of duck-typing. I would say that's because that's the *Ruby
    way* Ruby OOP is all about message passing, and as such an object's
    type is simply the messages it handles. Classes are mostly an
    implementation detail, i.e. an easy way to construct objects, as far
    as the interpretter is concerned.

    Of course I don't know your specific situation...but it's a pretty
    simple OOP principle that you should avoid performing operations based
    on an object's class, and instead move that behavior to the object
    itself. Even Java eschews the use of instanceof :)

    If "types" are very important to your domain, then I would suggest
    they ought to be promoted to a domain-level concept. Classes aren't
    intended to be used in that way, nor do I think they're the
    appropriate level of abstraction.

    Pat
    Pat Maddox, Oct 6, 2007
    #19
  20. Trans

    Neil Wilson Guest

    On Oct 6, 7:45 am, Sylvain Joyeux <>
    wrote:

    > In my work, I *need* to reason about the types of my objects. They are not
    > instances, they are instances of classes (=models) and I need to reason
    > about those models. As soon as you're thinking that way, you *have* to
    > have multiple inheritance because single inheritance is not enough.
    >
    > For now, I'm stuck with using modules to emulate some kind of multiple
    > inheritance. It sucks.


    No, you are stuck in a mindset and you have mapped that mindset onto
    classes as though they are the only modelling tool available. There
    are lots of other ways of modelling domains.

    Classes in dynamic languages are just a convenient shorthand that
    covers the general case very well. To be honest you could dump the
    abstraction but it would mean more keyboard work.

    You might want to consider whether using sets or states may be a
    better way of modelling your domain. If you think a network is the
    only model that will work, then you might want to brush up on your
    graph theory and see if an edge/vector abstraction is suitable.
    Clearly a simple tree isn't suitable (which is what a Class strcture
    is).

    First choose the correct data structure. If you find a model hard
    always reconsider your data structure. It is very common to get the
    wrong one, or try and shoehorn a model into the ones you are more
    familiar with than learn how to use new ones.

    Get your structure reviewed by a peer and try and keep an open mind.
    There is nothing shameful about getting the wrong structure. We all do
    it all the time.

    NeilW
    Neil Wilson, Oct 6, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve Franks
    Replies:
    2
    Views:
    1,251
    Steve Franks
    Jun 10, 2004
  2. Tee
    Replies:
    3
    Views:
    7,803
    Herfried K. Wagner [MVP]
    Jun 23, 2004
  3. Janice

    lower case to upper case

    Janice, Dec 10, 2004, in forum: C Programming
    Replies:
    17
    Views:
    1,177
    Richard Bos
    Dec 14, 2004
  4. Rouslan Korneychuk
    Replies:
    8
    Views:
    599
    Rouslan Korneychuk
    Feb 10, 2011
  5. Michael T. Richter
    Replies:
    0
    Views:
    84
    Michael T. Richter
    Oct 9, 2007
Loading...

Share This Page