team almost never has a full grasp on
the totality of the problem. This is at
the root of the failure of the waterfall
model of software development, which
posits that all requirements can be finalized before design begins, which
in turn can be completed before the
system is implemented, and so forth.
The argument seems good: the cost to
make a change goes up exponentially
as the system is developed, so the best
path is to get the early stages done right
before moving on. The reality is that requirements always change (“
requirements churn”). It is often better to have
a working prototype (even though it is
not complete or perfect) so that you and
the customers can start gaining experience with the system. This is the philosophy behind Agile programming,
which accepts some technical debt as
inevitable but also mandates a remediation process (“plan for change”).
As necessary as technical debt may
be, however, it is important that the
strategic parts of it be repaid promptly.
As time goes on, programmers move to
other companies, and the people who
agreed to various compromises have
moved on to other projects, replaced
by others who do not see it the same
way. Failure to write the documentation (both internal and external) for
the initial prototype may be a good
trade-off, but the longer it goes the
more difficult it is to write—if only
because human memory is transient,
and if you show most people code
they wrote a year ago they will have to
study it to remember why they did it
that way. Code that is intended to have
a limited life span may be immune to
these concerns, but many short-term
“prototypes” end up getting shipped
to customers. Unfortunately, Fred
Brooks’ statement in The Mythical
Man-Month, “Plan to throw one away;
you will, anyhow,”
1 seems all too often
to be corrupted to, “Make your prototype shippable; it will, anyhow.” These
two statements are not contradictory.
Equally as important is that some
forms of technical debt are so expensive that they should be avoided entirely whenever possible. Security is an
area where taking shortcuts can lead to
disaster. You never want to say, “We’re
using passwords in the clear today, but
we will come back someday and change
it to challenge-response,” in anything
understanding,
communicating,
and managing
technical debt
can make a huge
difference in both
the short- and
long-term success
of a system.
other than very early prototypes that no
one but you will ever see. This is a recipe for disaster if it ever gets accidentally deployed. You also want to avoid enshrining “bet your company” shortcuts
in code. If for some reason you have no
choice (for example, because during
development other engineers have to
write code that will interface with yours
and you can’t afford to keep them waiting), keep a journal of “debts that must
be repaid before release.” It’s amazing
how easy it can be to forget these things
if they aren’t written down.
Release cycles can make a considerable difference in the rate of acquisition and disposal of technical debt.
The modern trend to “release early
and often,” especially in the context
of Web-based services, has made it
much easier to take on technical debt
but has also made it easier to resolve
that debt. When well-managed, this
can be a blessing—taking on debt earlier allows you to release more functionality earlier, allowing immediate
feedback from customers, resulting
in a product that is more responsive to
user needs. If that debt is not paid off
promptly, however, it also compounds
more quickly, and the system can bog
down at a truly frightening rate. Another side of Web-based services in
particular is that a correct but inefficient solution can actually cost your
company more money—for example,
in the form of server-farm rental fees.
Fortunately, this makes the debt easy
to translate into dollar terms, which
nontechnical stakeholders usually
find easier to understand than assertions about maintainability.
Not all technical debt is the result
of programmer laziness. Some is imposed by management or other departments, especially when they do not understand how pernicious this debt can
be. Customers usually buy features,
not long-term maintainability, so marketing departments often encourage
engineering to move on to the next
great thing rather than spending the
time necessary to consolidate, clean
up, and document the existing system.
To them, taking these steps is an unnecessary cost—after all, the system
works today, so why does engineering
need to spend time gilding the lily?
There is another aspect to technical debt to consider: it occurs in many