Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Mark Leighton Fisher (4252)

Mark Leighton Fisher
  (email not shown publicly)

I am a Systems Engineer at Regenstrief Institute []. I also own Fisher's Creek Consulting [].
Friday February 09, 2007
12:46 PM

Composition is More Important Than Inheritance

[ #32361 ]

As a general rule, I have found that composition is more important than inheritance in software design. Just look around you how many things do you see that are related to each other by inheritance? A lot fewer than the number of things that are related to each other by composition, I suspect.

You may be reading this in some type of office. If that is the case, around you will be chairs, tables, lamps, staplers, Although inheritance can be found anywhere if you look hard enough, for most practical purposes there is no inheritance among the objects of an office. From what I have seen (in a design career spanning database management systems, electronic CAD, knowledge management systems, electronic health record systems, and systems administration software) you will spend a lot more time composing software out of various different types of modules than you will spend in creating more specialized classes of existing software. For that is what inheritance buys you in software design the ability to have ever-more specialized classes and behaviors for your objects.

CPAN is a prime example of this. If inheritance was as important in design as generally seems to be believed, then CPAN would consist mostly of derived classes, with only a relatively small number of base classes. Instead, CPAN is made up of mostly unrelated (by inheritance) classes.

Polymorphism is useful only when you have a subclass a class that has inherited from a parent class. What I seem to see more often in practice is interfaces objects with multiple unrelated (by inheritance) sets of behaviors. In a dog behavior simulation, a pet dog IS-A dog that IS-ALSO a pet. For mammalian pets, the behaviors of different species of pets are closer to each other in a lot of ways than to the behaviors of those mammals in the wild (interfaces vs. inheritance).

To look at the question taxonomically, inheritance and polymorphism are most advantageous when your Tree of Domain Objects is relatively deep but narrow. With a wide and shallow Tree of Domain Objects, only a few of your classes will be related by inheritance, so polymorphism will be of lesser value than is generally perceived. In my experience, wide and shallow Trees of Domain Objects seem to be the common case. Polymorphism does solve the otherwise nasty problem of setting up different behaviors for related objects in a clean, non-brittle fashion (think of many large switch statements that must be modified each time you create a new class...)

So if modules don't inherit from each other (inheritance), and code doesn't morph into the modules you need (polymorphism), then how do you usually build your modules? By composing them (composition), as you have guessed by this point. One beautiful aspect of CPAN is that there are so many different modules to go into a composition (10,000+ last I knew).

This doesn't mean that inheritance is useless far from it. It just means (IMHO) you will end up using a lot more composition than inheritance and polymorphism. Take, for example, a desktop GUI application for automatically building written group status reports from written status reports by individuals. Inheritance and polymorphism will be used in the GUI, but a storage API like DBI is effectively much more a case of interfaces than inheritance (PostgreSQL vs. Oracle vs. flat files vs. ...), and the main classes of objects (people, groups, configurations, and report text) bear little inheritable relationship to each other.

One area where I haven't done much software engineering is the mega-system: 1M+ LOC in a single system. Maybe this is where inheritance and polymorphism get used as the main design techniques I simply do not know.

I think this is a contrarian position to the current received wisdom, so I welcome the comments of those who are better experienced than I am.

(P.S. Why am I talking about Composition instead of Encapulation? Because (IMHO) encapsulation is of greatest use only when it serves the purpose of composition plus, that's the way I often think about software design, as a series of compositions.)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • If inheritance was as important in design as generally seems to be believed, then CPAN would consist mostly of derived classes, with only a relatively small number of base classes.

    Perhaps you would, if CPAN modules generally had good design (I'm not willing to make that assumption in general) or if module authors were truly egoless programmers (I point you to templating systems, argument processing modules, web frameworks, class creation modules...).

    Polymorphism is useful only when you have a subclass

    • Very True. JavaScript and other prototype-based languages are good examples of languages that implement a very extreme form of polymorphism without even supporting language-level inheritance.
  • In the few large systems I've implemented, the most obvious use for me of large-scale inheritance was a widget system. 90 classes, 30-50k LOC, and large scale inheritance.

    But beyond that, I think inheritance is just another implementation method.

    Pick the best one for the job.