Incremental development
One of the advantages of inheritance and
composition is that these support incremental
development by allowing you
to introduce new code without causing bugs in existing code. If bugs do appear,
they are isolated within the new code. By inheriting from (or composing with) an
existing, functional class and adding data members and member functions (and
redefining existing member functions during inheritance) you leave the existing
code – that someone else may still be using – untouched and
unbugged. If a bug happens, you know it’s in your new code, which is much
shorter and easier to read than if you had modified the body of existing
code.
It’s rather amazing how cleanly the
classes are separated. You don’t even need the source code for the member
functions in order to reuse the code, just the header file describing the class
and the object file or library file with the compiled member functions. (This is
true for both inheritance and composition.)
It’s important to realize that
program development is an
incremental process, just like
human learning. You can do as much analysis as you want, but you still
won’t know all the answers when you set out on a project. You’ll
have much more success – and more immediate feedback – if you start
out to “grow” your project as an organic, evolutionary creature,
rather than constructing it all at once like a glass-box
skyscraper[52].
Although
inheritance for experimentation is a useful technique,
at some point after things stabilize you need to take a new look at your class
hierarchy with an eye to collapsing it into a sensible
structure[53].
Remember that underneath it all, inheritance is meant to express a relationship
that says, “This new class is a type of that old class.” Your
program should not be concerned with pushing bits around, but instead with
creating and manipulating objects of various types to express a model in the
terms given you from the problem
space.