Scott Ambler explains that there are no universal rules; excerpt from in the latest newsletter from Software Development Magazine, 19-01-2005.
The IT community operates on a fundamental assumption of
software development "best practices," demanding that we use
them on all projects. For example, model reviews, detailed
requirements documents, change control boards (CCBs) and
pair programming are typically referred to as best practices.
But reality reveals that one size does not fit all: I believe that
these are actually contextual practices that work in some
situations, but not others -- there's really no such thing as "best
practices."
To be truly effective developers, we must know a wide
range of development techniques, and, equally important,
understand the context in which to apply them.
Consider code inspections: A group of your peers, perhaps
in a facilitated meeting, reviews your code and provides feedback.
According to Capers Jones (Software Assessments, Benchmarks
and Practices, Addison-Wesley, 2000), Tom Gilb (Software
Inspection, Addison-Wesley, 1994) and other experts, code
inspections are effective in identifying potential source code
problems that span deviations from accepted coding practices
to incorrectly implemented requirements.
Now consider pair programming: working with another
programmer at a single keyboard. Its proponents insist that
this approach results in higher-quality code, greater understanding
of the system's design, and enhanced skill transfer among team
members. Pair programming works particularly well when you
swap pairs on a regular basis, use a common and agreed-upon
set of coding conventions, and have a shared code base
throughout the team.
To Each Its Own
Code inspections and pair programming are widely considered
best practices that should be globally adopted. Unfortunately,
reality isn't this simple. Code inspections are effective in
environments where collaboration between programmers is
minimal and people "own" their own sections of the code.
When collaboration is low, programmers have little opportunity
to share improvement ideas and techniques, allowing deviations
in their work over time. Worse yet, when people work alone on
code for long periods of time, they can unwittingly introduce
defects that go undetected. In these situations, holding code
inspections is clearly a good idea because it forces other
"pairs of eyes" to examine your code. But what if you have the
benefit of a highly collaborative, flexible work environment?
In that situation, code inspections may not be just superfluous;
they can actually impair the development process.
Because of the high degree of collaboration it engenders,
pair programming works best in trusting and respectful
environments. When you pair program, you must stay focused
on actually writing code because you know your partner is
sitting beside you. If you deviate from the coding conventions,
forget to write a unit test first or get stuck on syntax, your
partner can take the helm. But if your environment isn't
supportive of highly collaborative work, pair programming
may prove an abysmal failure.
Two Great Tastes
Should we use these two "best practices" together? Perhaps --
but in my experience, in an effective pair-programming
environment, the value of code inspections plummets. Why
don't these two practices fit together? First, the contexts in
which each is effective are worlds apart. Second, as you
can see in "Best Practices Face-Off " (see next section),
the two techniques overlap significantly, each thereby
reducing the other's unique value.
But is one practice a replacement for the other? Not really.
Although the two techniques share several benefits, each
approach is best suited for different situations. Although
pair programming delivers more benefits than code inspection,
it does nothing to convince people external to your team that
you're doing a good job. Similarly, code inspections are
no replacement for pair programming because they don't
produce working software.
Compare Baskets, Not Fruit
Ultimately, however, weighing details of the two techniques
makes as much sense as comparing apples and oranges.
What does make sense, but is clearly much harder to
achieve, is to compare collections of practices -- baskets
of fruit, if you will. For example, you could weigh a set of agile
practices against a set of traditional practices. The agile
basket might hold pair programming, collective ownership,
test-driven development (TDD) and refactoring. The
traditional basket might contain code inspections, model
reviews, up-front detailed design and unit testing. Each
basket holds a group of synergistic practices that
covers a comparable set of issues, enabling a fair
comparison. Better yet, because each collection of
practices is commonly bundled together within its respective
development community, the relative effectiveness of agile
and traditional software development can potentially be
determined.
The process and organizational patterns community had
it right all along: You must first understand a problem's
forces (its context) to apply a solution that adequately
addresses them. Having done so, a new situation arises
that requires a different pattern. To succeed, you need a
collection of patterns, called a pattern language. Jim
Coplien's work in this area, specifically his architecture
process patterns, is the best-known example of process
pattern languages. Replace the terms pattern with practice,
force with issue and pattern language with collection of
practices, and we're talking about the same basic
concepts. (For more information, go to here.)
Farewell, Fantasyland
Just as you use the right tool for the job, you must apply
the right development practice for your situation. This
requires the skills to identify the situation you currently
face, proficiency in a wide range of practices, and an
understanding of the context in which each practice works.
In software development, "best practices" inhabit a sort
of fantasyland, where waving a magic process will
solve all your problems. Reality, however, demands
specific attention to specific issues. Customizing your
practices to fit the problem will get you much farther
on the road to success than flailing about with an
all-purpose -- and ineffective -- magic wand.
--Scott Ambler, 2005