CHAPTER 20 ■ OBJECTS, PATTERNS, PRACTICE
Encapsulate the Concept That Varies
If you find that you are drowning in subclasses, it may be that you should be extracting the reason for all
this subclassing into its own type. This is particularly the case if the reason is to achieve an end that is
incidental to your type’s main purpose.
Given a type UpdatableThing, for example, you may find yourself creating FtpUpdatableThing,
HttpUpdatableThing, and FileSystemUpdatableThing subtypes. The responsibility of your type, though, is
to be a thing that is updatable—the mechanism for storage and retrieval are incidental to this purpose.
Ftp, Http, and FileSystem are the things that vary here, and they belong in their own type—let’s call it
UpdateMechanism. UpdateMechanism will have subclasses for the different implementations. You can then
add as many update mechanisms as you want without disturbing the UpdatableThing type, which
remains focused on its core responsibility.
Notice also that I have replaced a static compile-time structure with a dynamic runtime
arrangement here, bringing us (as if by accident) back to our first principle: “Favor composition over
inheritance.”
Practice
The issues that I covered in this section of the book (and introduced in Chapter 14) are often ignored by
texts and coders alike. In my own life as a programmer, I discovered that these tools and techniques
were at least as relevant to the success of a project as design. There is little doubt that issues such as
documentation and automated build are less revelatory in nature than wonders such as the Composite
pattern.
■Note Let’s just remind ourselves of the beauty of Composite: a simple inheritance tree whose objects can be
joined at runtime to form structures that are also trees, but are orders of magnitude more flexible and complex.
Multiple objects that share a single interface by which they are presented to the outside world. The interplay
between simple and complex, multiple and singular, has got to get your pulse racing—that’s not just software
design, it’s poetry.
Even if issues such as documentation and build, testing, and version control are more prosaic than
patterns, they are no less important. In the real world, a fantastic design will not survive if multiple
developers cannot easily contribute to it or understand the source. Systems become hard to maintain
and extend without automated testing. Without build tools, no one is going to bother to deploy your
work. As PHP’s user base widens, so does our responsibility as developers to ensure quality and ease of
deployment.
A project exists in two modes. A project is its structures of code and functionality, and it is also set of
files and directories, a ground for cooperation, a set of sources and targets, a subject for transformation.
In this sense, a project is a system from the outside as much as it is within its code. Mechanisms for
build, testing, documentation, and version control require the same attention to detail as the code such
mechanisms support. Focus on the metasystem with as much fervor as you do on the system itself.