One
pattern that emerges from the examples we've examined so far in this
chapter is this: If you want transparent code, the most effective
route is simply not to layer too much abstraction over what you
are manipulating with the code.
In Chapter4's
section on the value of detachment, our advice was to abstract and
simplify and generalize, to try and detach from the particular,
accidental conditions under which a design problem was posed. The
advice to abstract does not actually contradict the advice against
excessive abstractions we're developing here, because there is a
difference between getting free of assumptions and forgetting the
problem you're trying to solve. This is part of what we were driving
at when we developed the idea that glue layers need to be kept
thin.
One of the main lessons of Zen is that we ordinarily see the
world through a haze of preconceptions and fixed ideas that proceed
from our desires. To achieve enlightenment, we must follow the Zen
teaching not merely to let go of desire and attachment, but to
experience reality exactly as it is — without the preconceptions
and the fixed ideas getting in the way.
This is excellent pragmatic advice for software designers. It's
part of what's implicit in the classic Unix advice to be minimalist.
Software designers are clever people who form ideas (abstractions)
about the application domains they deal with. They organize the
software they write around those ideas. Then, when debugging, they
often find they have great trouble seeing through those ideas to what
is actually going on.
Any Zen master would recognize this problem instantly, yell
“Three pounds of flax!”, and probably clout the student a
good one.[63] Consciously
designing for transparency is a slightly less mystical way of
addressing it.
In Chapter4 we
criticized object-oriented programming in terms likely to prove a bit
shocking to programmers who were raised on the 1990s gospel of
OO. Object-oriented design doesn't have
to be over-complicated design, but we've observed that too often it
is. Too many OO designs are spaghetti-like tangles of is-a and has-a
relationships, or feature thick layers of glue in which many of the
objects seem to exist simply to hold places in a steep-sided pyramid
of abstractions. Such designs are the opposite of transparent; they
are (notoriously) opaque and difficult to debug.
As we've previously noted, Unix programmers are the original
zealots about modularity, but tend to go about it in a quieter way.
Keeping glue layers thin is part of it; more generally, our tradition
teaches us to build lower, hugging the ground with algorithms and
structures that are designed to be simple and transparent.
As with Zen art, the simplicity of good Unix code depends on
exacting self-discipline and a high level of craft, neither of which
are necessarily apparent on casual inspection. Transparency is hard
work, but worth the effort for more than merely artistic reasons.
Unlike Zen art, software requires debugging — and usually needs
continuing maintenance, forward-porting, and adaptation throughout
its lifetime. Transparency is therefore more than an esthetic
triumph; it is a victory that will be reflected in lower costs
throughout the software's life cycle.