Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re^3: Inheritance, just say no! Read the traits paper.

by Ovid (Cardinal)
on Aug 04, 2006 at 07:07 UTC ( #565616=note: print w/replies, xml ) Need Help??

in reply to Re^2: Inheritance: the root of the problem
in thread Inheritance: the root of the problem

This is not "poe-tay-toe versus poe-tah-toe". Inheritance can be useful and it's sometimes appropriate, but it's often a lousy way to build systems, particularly since it tends to constrain code reuse to a given heirarchy.

If you think of a class as an something which has a responsibility to cover a problem domain, then this class needs to do everything it needs to do. That sounds like a silly tautology, but what it means is that there's an upward pressure on the size of a class. The more things it needs to do, the larger it tends to get.

However, leaving aside the question of responsibilities, we can also think of objects as units of code reuse. As an object of code reuse, it should do as little as possible. What's the sense of using inheritance when you might inherit twelve methods but only need two? What if, instead of ignoring those other methods, you explicitly don't want them? Or what if you use multiple inheritance you discover you have conflicting methods which ordering problems make difficult to call? Heck, what if you discover that you need to call both of the conflicting methods to maintain proper state in your superclasses? Ack! Many languages suggest using SUPER to get around this, but one keyword doesn't resolve which class you want to call, so you wind up with hacks like hard-coding the superclass name in your method and later wondering why things break when you refactor things.

Now some of these are issues with poor composition but this is not always the case. Inheritance schemes lead to conflicting pressures of needing both larger and smaller classes. Sure, you can jump through a bunch of hoops to set up delegates to solve problems, but do you really want to do that every time you face this problem? And if you're delegating to another class when you only need a tenth of the features it provides, why even load that other class in the first place? Traits make these problems go away. They're just gone, finished, kaput.

If you really want to understand the problems with inheritance and how traits solve them, read this traits paper (PDF). Many people (including me) admit that it can take a few tries to see what's going on, but once you get it, it makes perfect sense. chromatic's article shows how easy it is to use traits. The traits paper I linked to is the smoking gun.


New address of my CGI Course.

  • Comment on Re^3: Inheritance, just say no! Read the traits paper.

Replies are listed 'Best First'.
Re^4: Inheritance, just say no! Read the traits paper!
by apotheon (Deacon) on Aug 04, 2006 at 07:28 UTC

    I think you misunderstood what I was saying. I didn't mean that "inheritance v. not-inheritance" is the same as "poe-tay-toe v. poe-tah-toe". Rather, I mean that "How can we boil a (perceived) necessity for inheritance down to its essentials, in the form of underlying problems it's meant to solve?" is "poe-tay-toe", while "What are the problems we might solve with inheritance, and do we need inheritance or something else entirely to solve them in this case?" is "poe-tah-toe". In other words, I'm referring to different means of phrasing the question as being nearly equivalent (we're talking about the same thing in different languages). The refactor of my question is a better approach to explicitly describing the intent of the question, but it ultimately amounts to roughly the same question, as far as I can see.

    On the other hand, I can't say I'm unhappy I failed to be clearer about my "poe-tay-toe versus poe-tah-toe" statement, because it prompted to you to say a bunch of stuff that helps me think more clearly about the problem at hand. I'd never really encountered lucid explanations of the traits/roles approach before my OP here, and between you and others I've received some good indications about how to approach figuring out what it's all about. Thus, thanks.

    print substr("Just another Perl hacker", 0, -2);
    - apotheon
    CopyWrite Chad Perrin

      Those similar questions emphasize different things, so will lead you to different answers.. And they go hand in hand with the third essential question, which is, What are the problems that inheritance causes?

      The key to understanding all three is that inheritance is an imperfect mechanism for turning an ontology into well-factored code. Debates over what kind of inheritance mechanism to use come down to debates over how rich we'll allow our realizable ontologies to become (noting that richness brings both benefits and drawbacks), how efficient we wish the implementation to be, and where we wish to place surprises for the unwary programmer. (One of the tradeoffs is that the richer we allow the ontology to become, the more surprises we wind up with.)

      It is, to say the least, highly unclear what the optimal tradeoff is. In fact it is apparent to me that the optimal tradeoff is different in different situations, and is again different for different programmers. Therefore beyond vague generalities (like the ones I give above), a real discussion of this problem needs to be informed by concrete examples. Certainly trying to answer it in perfect abstract generality is bound to fail.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://565616]
and the questions are moot...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2018-04-21 10:27 GMT
Find Nodes?
    Voting Booth?