Agile
practices such as unit testing, story-based requirements gathering, and pairing
are intuitively appealing ways to achieve higher quality and mitigate risk of
change. At first glance, they even seem
relatively easy to execute: how hard can it be for two people to collaborate,
write small business-oriented requirements, and code tests with each bit of
software? Executing Agile practices can
be quite difficult to perform. For one
thing, they make people uncomfortable because they challenge work habits long
established in IT. For another, they
give the appearance of reducing productivity.
This can lead teams to try to take shortcuts to becoming Agile. Selectively gaining experience with Agile
practices is of value when first taking them on, but denying them completely leaves
the benefits of Agile practices unrealized, and can cause more harm than good
to a development team.
Mythical Shortcut: We
write unit tests, but it doesn't matter if they pass or not
Writing unit tests and automating them into the build is an
obvious best development practice. While
many people are willing to write unit tests, they are not necessarily diligent
about maintaining them. That is, teams
may create a high degree of unit tests over a codebase and execute unit tests with
the build, but a failure of unit tests doesn't fail the build. Unit tests failures are therefore not a "call
to action" for developers. This can be
the case for several reasons, but most often:
There is pressure for
developers to show they are "development complete" of work being done;
Developers don't feel
ownership of unit tests which they didn't write; and/or
Unit tests aren't implemented
as a gatekeeper, only as information.
There is a false sense of quality created when unit test
status is a passively consumed indicator during the build. When not an active part of the development
cycle, tests tend not to be maintained, and degrade in value over time. If developers don't commit to maintaining success
of all tests by all members of a team, each test is relegated to being little
more than a spot inspection at the time it is created. As a result, tests can be little more than
"noise" instead of being true "signals" of code quality. As signals of quality, unit tests ensure that
quality is sustained as code evolves.
Advertisement
This undermines risk mitigation characteristics inherent in
an Agile team. First and foremost, the ability
of an entire team -- not named individuals -- to modify code is impaired. A test framework provides accurate feedback
on the integrity of change relative to the rest of the system. In the absence of a test framework, changes
to code are made with less confidence. This
encourages developers to work in silos: only those who know the code have the
confidence to change it, which, in turn, creates bottlenecks in throughput, and
vulnerability to staff turnover in a team.
Furthermore, the absence of unit tests make completion more of a matter
of developer opinion that the work is done, and less of a matter of fact as demonstrated
by a test harness that reflects the compliance of code to historical and
current requirements. Ultimately, this makes
Agile project management burn-up charts showing progress to completion less reliable,
as work declared "complete" lacks basis in fact.
There are several ways to make unit testing a fully
practiced activity within a team. Making
unit test coverage mandatory when code is checked-in (by mandating a minimum
level of code coverage as a build gatekeeper) means that developers will write
tests. Making 100 percent test passage a
gatekeeper on the build means that code and tests will be properly maintained
with collective understanding. Measuring test coverage as part of a governance
structure means that coverage is visible; things that are out of compliance
tend not to remain so when highly visible.
When supplemented with visual inspection and peer review of tests to
ensure quality of the tests themselves, these steps provide assurance of
disciplined unit testing.
Mythical Shortcut: We
pair, but only when we have trouble
Pairing is often considered a luxury activity. Many teams
consider it a "nice to do," but believe they lack the time or resources. Among the many reasons for this, two stand
out. First, there are social
considerations. People might lack social
skills, be hiding skill deficiency, or be protecting knowledge they have and
thus a job. Whatever the case, it means
that individuals on a team might vociferously resist working in such a
collaborative, interactive manner with other people. Second, because "development complete" passes
as a surrogate for "the code works," management tends to be focused on the cost
of development capacity. That is, if there
are x-thousand person hours of
development work to do, then y number
of developers can do the work in x/y time. Qualitative attributes that affect the time to
complete a task, such as environmental familiarity and solution quality, are
invisible in this logic. Management will thus misinterpret pairing as a request
for 2y developers to complete work.
The combination of individual pushback plus management focus
exclusively on developer hours means pairing is often disregarded, and indeed
seen as an inhibitor to productivity. For
many quasi-Agile teams, the ready excuse is, "we pair when we have difficult
problems to solve." While probably true,
this doesn't provide the same benefits as "pair programming."
True pair programming reduces risks on Agile project teams
in several ways. For one thing, it
maintains a consistent level of throughput of Agile teams: an entire team
familiar with code is far better able to perform work at a sustainable
pace. By comparison, a team of people
working in specialized "swim lanes" - where one person knows code or technology
that nobody else knows - delivers only as fast as the pace of the slowest
lane. This means teams work at different
rates of speed, which impairs a team's throughput. Pairing also supports the resilience of Agile
teams to staff changes. All members of a
team can be exposed to the entire code base by rotating pairs. Should somebody leave the team, the team can
absorb the loss with a minimal impact of productivity since there is shared
familiarity. It also trains new members on
code, infrastructure, and environmental issues through a collaborative, applied
process. Finally, pairing creates a high
degree of code review. Having two people
review code at the time it is created allows multiple perspectives of a problem
space to be built into code. It also
means that poor code constructions are less likely to be created by a team as
100 percent of code is audited at time of creation.
Implementing pair programming is difficult. Inside a team, it can be a disruptive
activity: it takes time for people to get used to doing it, and it takes the
right people to do it. Bringing this about
requires developers who are naturally oriented to work in a collaborative
manner. Outside a team, it requires communicating
differently with management. Iterative
delivery progress, reported in business terms, shifts management focus away
from the cost of capacity and toward the total cost of results achieved. Risks such as staff turnover can also be made
visible and quantified to management; when risks are visible, there will be
greater acceptance of practices such as pair programming that reduce those risks.
Mythical Shortcut: The
work we do doesn't lend itself to Agile "stories" so we track to technical
tasks
It isn't uncommon for teams to define work not as an end-to-end
business story, but as a technical task.
When this happens, requirements are structured as statements of
technical activity understood by developers, rather than as granular statements
of work understood by a business partner..
This happens because many times, IT professionals struggle to think from
the business perspective. Developers
tend to decompose requirements into technical phases (e.g., user interface,
server-side code, database code). As a result, it is easier for teams to
produce collections of technical tasks and try to pass them off as Agile
stories.
Working to any granular unit of work has merit. Exposing and tracking technical tasks allows
a team to provide visibility into what it is doing. However, technical actions performed are
meaningless to business partners: even if a collection of defined technical
tasks will fulfill a business requirement, it is difficult for the business to
assess the value of each technical task.
In this instance, providing a burn-up chart over a collection of technical
statements of work shows progress against the developer's understanding of
business need, but it doesn't provide visibility into progress against the businesses' definition of business need.
Tracking against technical stories, then,
creates a false sense of progress: it runs a great risk of showing progress to
a statement of scope that doesn't match the actual business problem.
Looking at this from another perspective, a collection of
purely technical stories obliterates the business partner's ability to
incrementally certify a teams' progress toward achieving business goals. Working to technical stories tends to result
in a single delivery event of business functionality occurring at the end of a
development cycle. This increases the
probability that software delivered will be a functional misfit. While there may be the appearance of
incremental progress through a backlog of technical stories, all of that
progress might be obliterated when the business partner receives a business
delivery only at the very end. To be
effective, an Agile team requires continuous participation from its business
partner, who is constantly engaged to express and granularly refine how the underlying
business need is met. Small statements
of business need are therefore of lower risk than delivery of very large
packages of functionality.
To bring this about in a team, the business representative
must make clear at daily stand-ups or retrospectives whether he understands the
requirements the team is working on.
Separately, IT governance policy can require that teams categorize
requirements as business or technical.
This allows a team to declare scope and progress in business terms, disallowing
progress reporting from being gamed through purely technical execution.
A shortcut is the
longest distance between two points
There is a synergistic benefit to the consistent execution
of these Agile practices. Disciplined
execution of them collectively yields greater technical quality, functional
fitness, and resilience to risk. Less
disciplined execution of any one of these practices risks destroying that
synergy, meaning technical defects will mount, functionality delivered will drift
from need, and change of any kind will be disruptive and not absorbed. In choosing how to develop software, and especially
if choosing not to perform specific practices, weigh carefully the effort being
saved in day-to-day execution versus the effort lost remediating preventable
problems.
About the Author
Ross
Pettit has 15 years' experience as a developer, project manager, and program
manager working on enterprise applications. A former COO, Managing Director,
and CTO, he also brings extensive experience managing distributed development
operations and global consulting companies. His industry background includes
investment and retail banking, insurance, manufacturing, distribution, media,
utilities, market research and government. He has most recently consulted to
global financial services and media companies on Agile transformation programs,
with an emphasis on metrics and measurement.
He is a frequent speaker and active blogger on topics of Agile
management, governance and innovation.
He is currently a Client Principal with ThoughtWorks.
Comments (3)
tim d.: ...
Like any tool, if you use it differently than it is designed to be used, there will be trouble.
But reality is, sometimes there is no choice but to take a shortcut...
1
January 29, 2008
Michael S.: ...
Valeri, Wow, it sounds like you must be facing a terribly frustrating environment! Most often the teams I’ve worked with are self-managing enough to specify their own rules for unit testing, without directives from outside management. With regard to quality and effectiveness of unit testing, there are effective tactics for ensuring a good return on investment – such as coverage metrics and peer review of test plans/implementations. Results from pair programming are also highly dependent on how it is done and how results are measured. Given the results you have seen, it sounds like pairs do not have complementary skills and that knowledge-transfer is not an aspect that is valued or measured. Regrettable and no doubt frustrating when unsatisfactory implementation prevents the realization of the potential benefits.
2
January 22, 2008
Valeri S.: ...
When unit test are formally required from developers by management (and enforced by build process), it quickly turns into formal exercise of producing a lot of useless unit test code which does nothing, checks nothing, tests nothing, and never fails. That would make managers very happy. And it is a waste of time and effort.
Pair programming in practice: the stronger developer writes code and makes design decisions, the weaker one just watches over the shoulder.