XPlorations
Reactions: Code Ownership, Integration, Workspace,
Release Schedule, and Coding Standards |
February, 2000 |
We explore several practices in XP, exploring
alternative models and their consequences, and review the reasons for XP's
choices.
- Code Ownership: Who can change an object that needs to change?
- Integration: How and when does a team ensure everybody's code
works together?
- Workspace: How should a team be physically arranged?
- Release Schedule: How often should a team release their
product?
- Coding Standard: How should the code be written?
|
Code Ownership
Nobody ("Orphan")
For some systems, nobody owns the code. For closed-source systems, maintained
by a third party, "nobody" just means "nobody here". There are other programs
that are untouchables: there's no source code (it was lost years ago), or the
system is too brittle or too complicated to safely change.
When code isn't owned, developers will either design around it or treat it as
a black box. That latter approach can be especially painful: the programmer has
to format data going in and out; they may have to mediate between two paradigms
(e.g., using screen-scraping technology); they may be unable to do things you
would normally expect to be possible; there may be data denormalization and
coordination problems because information has to be stored both inside and
outside the system.
Avoid the situation of "nobody owns it (and nobody wants to)".
Last One Who Touched It ("Tag"); and
Whoever's Newest ("Trial by Fire")
You may have systems that are reasonably stable, but still a pain to
maintain. In these situations, there's typically a local cultural rule that
kicks in: whoever touched it last owns the next problem (which can make it
frustratingly hard to escape), or perhaps the person is given to the least
powerful person (often with the instructions, "just make it work").
This model seems very common in maintenance organizations.
One Owner Per Class (or Package) ("Monogamy")
This approach is very common in new development: the author owns the code
they write, until somebody explicitly takes it over.
The key is that there's a well-defined person in charge of a section of code.
If you want it changed, you negotiate with them. They may even let you change it
yourself, but they'll retain approval rights on what you do. (Sometimes the
ownership will go stale: the person who did one piece is gone, and it's not
actively changing, so there won't be a real owner until someone needs something
done, so the team will assign an owner at that time.)
The benefit of this approach is that it provides a well-defined method for
deciding who does what work, and it lets a person develop expertise in a
particular area.
There are downsides, though. If the owner isn't available to make a change
when needed, the team is slowed down. (Some teams mitigate this by having
emergency backups.) Sometimes the owner won't agree with a proposed change,
perhaps completely vetoing it. Then clients may design around it or wrapper it
in a way that is worse for the system overall. Another problem is that a single
owner can be in trouble and hide the fact. (The code may be deeply in trouble by
the time their lack of expertise is noticed.)
The single-owner approach can require that interfaces be frozen too early,
before they're really understood, because of the need to let clients "make
progress". Refactoring can be more difficult; when interfaces are public and
require a lot of cooperation to change, there's pressure not to change them for
political reasons.
Musical Chairs ("Rental Property")
Some groups will have a single owner for a package at any given time, but
that owner will be decided on a task-by-task or iteration-by-iteration basis.
This can be good in that it gives people variety, but they may not get a
chance to build deep enough expertise to be particularly effective. Since
there's an owner, everybody knows who to talk to.
The biggest problem is that the code is like rental property: the current
"owner" is really a "tenant"; they know the situation is temporary, so they have
less incentive to worry about the long-term value of the place (provided they
can get out of their lease before it gets too bad).
Ownership by Layer ("Tribalism")
Some groups organize their software into distinct layers, or even distinct
applications, and have ownership at that level. Anybody in the tribe can make
any change they need to - but they keep the tribe informed about what they're
doing. However, nobody from another layer would dare to jump in. (You see this
with user interface vs. business logic vs. database, or app1 vs. app2 vs.
database.)
This method overcomes some flaws of "monogamy": the "bus number" is higher,
there's no chance bad code will be hidden from the sub-team, etc. The subteams
can develop a very strong esprit de corps, which further boosts their
productivity.
However, interfaces between layers are elevated to near "golden"
status, making them even harder to change. This interferes with refactoring
intended to improve the overall system design.
Communication within the subteam is usually good, but it's harder to talk
across layers. A change that requires convincing on person in the "one owner"
model now requires "How about our subteams meet and discuss this - are you all
open next week?" This slows down the team as whole.
Collective Code Ownership ("Everybody")
In collective ownership, the whole team owns all code. Anybody can change any
part they need to.
The key benefit of this approach is that it is the least obstructive to
getting things done quickly. The ability to refactor is improved, as there are
fewer published interfaces. For the right team, this can be an effective mode.
(See the next section, which describes how XP tries to retain its benefits
without falling victim to its risks.)
There are downsides as well:
- Some people take personal pride in their code, and don't want others to
touch it.
- You risk the tragedy of the commons: "everybody is responsible" can come
to mean "nobody is responsible".
- This resembles "musical chairs" carried even further, perhaps aggravating
the risk that nobody will be expert enough, and that nobody will care for the
long-term value.
- It can be hard to read and work with someone else's code. You may get a
mish-mash of styles and approaches.
- People may step on each others' toes more, as they need access to the same
objects.
XP Uses Collective Code Ownership
Extreme Programming recognizes the risks in collective code ownership, but
uses it anyway. XP's practices attempt to mitigate these risks:
- Personal pride: XP doesn't really address this, other than perhaps
encouraging a shift to pride at the team level.
- "Tragedy of the Commons": Pair programming helps ensure that no person can
"pollute" in secrecy. The shuffling in pairs helps make all code even more
visible to the team. Refactoring can clean up any trouble that does occur.
- Not enough expertise: Pair programming spreads knowledge through the team.
The Open Workspace gives others a chance to speak up when one pair seems stuck
or worried. Simple design can require less "deep" expertise. Finally, tests
help ensure that functionality won't diverge from the requirements.
- Reading others' code: A coding standard helps reduce this problem, as does
the shared culture that pair programming engenders.
- Stepping on toes: Continuous integration ensures that people won't go far
without rejoining the main line. The tests ensure that there is no regression.
Conclusion - Code Ownership Models
We've described several code ownership models:
- Nobody
- Last One Who Touched It
- Whoever's Newest
- One Owner Per Class/Package
- Musical Chairs
- Ownership by Layer
- Collective Code Ownership
Finally, we talked briefly about how some of the practices in XP can overcome
the problems that might otherwise be caused by collective code ownership.
Integration
Just before delivery
The groups I've worked with have typically had developers working in private
areas, picking up what they need from others as they need it. Before delivery,
there's an attempt to do a "code freeze" (usually called "code slush" at this
point): everybody makes sure everything is checked in, and they resolve any
conflicts due to changing interfaces (especially those that obviously break the
compile). (This is similar to annealing in metallurgy: at first there's a lot of
activity, and as the temperature is lowered, everything settles into a low
energy state.)
The big problem with this approach is that it lets people go off in
drastically wrong directions, with nothing forcing them to test (or even
integrate) for days or weeks. The integration process becomes a lot of work for
whoever must resolve all the problems.
Daily Builds
A way forward is to go to daily builds. Every night, the system is compiled,
and a small test ("smoke test") is run.
The developer's motto becomes "Don't break the build". Deverlopers are
supposed to do their own integration testing as they check in, so there should
be no surprises. (The groups I've been in with this process had a project
manager who actively checked that people were checking in as they finished
tasks.)
Groups evolve different mechanisms to deal with this volume. I've heard of
groups that say "Whoever breaks the build must be in by 8 each day to check the
latest build (until somebody new breaks it)." A group I was in relied on peer
pressure by publicizing who broke it. Eventually they got a configuration
management person who had a set start time each day, and whose first
responsibility of the day was to identify any compilation or integration
problems, and get the relevant programmer(s) to fix it.
Continuous Integration
Continuous integration, as in XP, is not literally continuous, but it does
occur several times per day. Each time a developer (i.e., pair) finishes a work
session, they integrate what they have done. Typically, there's a single machine
for the team's integration efforts, so it's serialized "first-come,
first-served".
The other aspect of integration in XP is that it is supported by tests.
Developers must keep the unit tests integrated at 100%. To integrate, they take
their code to a machine also running at 100%. After they've integrated: if the
tests are still at 100%, they're done. If not, only one thing has changed: the
code they introduced. They're then obligated to fix the code (perhaps with help
from others), or back out the changes and throw it away. They're not
permitted to leave the integration system in a deteriorated state.
Continous integration is possible in XP because of the "togetherness" of the
group, because it's supported by tests, and because XP provides for simpler
design via refactoring.
Workspaces
Geographically Separate (Including Telecommuting)
Geographically separate groups are based in different locations, and face the
communication difficulties that implies. For example, there may be differences
in language (in the worst case) and differences in time zone. Even groups in the
same time zone can evolve different hours: I worked with a group where one site
tended to get in between 8:30 and 9:00, and the other group around 10-10:30.
With varying lunch and departure schedules, the core hours were 10:30-11:30 and
1:30-4:30.
Communication problems can make this approach more costly, even though it
appears cheaper on the surface. ("We can hire the best people from both
locations.", "We'll put another site where it's cheaper to hire.") There are
travel costs as well as communication costs (including resentment from those who
travel). Most groups must co-locate once in a while. (I know of an international
group that felt that things fell apart if they didn't meet at least quarterly.)
(Telecommuting takes the case of separate workspaces to the extreme, breeding
more communication difficulty, more isolation, and a perception of less
opportunity for advancement. If tasks can be split in a way to minimize the need
for communication, telecommuting may be a welcome approach. I haven't known any
developers to stick with it for more than a year or so, though.)
Offices (1- or 2-Person)
Offices offer the greatest level of privacy and quiet to the developer. In
Peopleware, deMarco and Lister reported that those with offices did the best
in their "coding wars", which they attributed to the need for programmers to
reach a state of "flow".
Offices are apparently the most expensive choice, because few companies seem
willing to provide them for developers. (I'll admit that I've felt most
productive in a 2-person office, though I haven't used an "open workspace" as a
member of an XP team.)
Cubicles
"Cubes" seem to be the form of office least liked by developers and most
liked by the managers who put them there.
Companies I've worked with seem to be making them smaller: 10 years ago, the
standard size was 100 square feet (including for the president of the company);
today (at a different company), the standard is 54 square feet. (And I'm bigger
than I was then!) My current office doesn't allow for two people at the desk,
and even if it did, the computer doesn't fit anywhere but the corner. (Cubes
also seem to be getting smaller and never bigger. A friend at a different
company would have "moving weekend", where you'd pack up your stuff, and end up
in the same office only 6" smaller. By gaining 6" per cube across a
football-field-sized room, they could add more offices.)
Cubes don't allow much privacy or quiet, but they still interfere with with
communication. (I've seen wall heights anywhere from 4 to 8 feet, but they
always seem to be open on top and never have a door.)
Open Workspace
XP specifies an open workspace, perhaps with small private spaces around the
central area. The fast machines are in the center, for pairing. It strives for
the mental state where you can focus on your problem, but still hear enough to
jump in if someone needs your help.
The same physical structure without an XP focus can degenerate into a
"bullpen": you're all stuffed into the same space (with no private space). You
aren't on the same project or phase, so the rhythms of your communication clash
with those of others. (This has been the worst office type I've been in (the
pure bullpen, not the XP open workspace.)
I've seen groups starting toward XP also take smaller steps toward open
workspace, by arranging for pairing machines in a spare niche, or treating a
wing of cubes as a public area.
Small Releases
Failing to meet the goal of having small releases is the biggest mistake I've
made in developing systems. When I focus on this goal, I find that "small" can
be even smaller than I would have thought.
I've resolved to start every project with this question: "Will this interface
work?" (Mimic pushing the button with your nose or forehead.)
The answer is often "yes, if you knew these parameters". In that case we
start without a GUI. Where it's not enough, it can get us focused on
understanding what is the minimal useful system. (I've also found that it
can be the developers who resist starting small; I think they have the vision of
what it could be and hate to back off from there.)
Someone in the first XP immersion class (and I apologize because I forget
who) described their practice of producing a ZFR ("ziffer") - Zero Feature
Release. It was an end-to-end release that did nothing, but it established the
architecture and the deployment strategy. It's hard to get a system into
production the first time; updating it is usually a lot easier.
Coding Standard
A coding standard is a tool that improves people's ability to read each
other's code. In XP, it supports refactoring as well: consistently "shaped" code
can be refactored more confidently.
There are several approaches to a team's coding standard:
- None. Ugh.
- Each chooses their own and uses it everywhere. ("Then I can tell
where I added code.") Ugh again.
- Each chooses their own for their code, but uses existing style on
existing code. This is the minimum I can live with. Many times I've worked
with a team that intended to have a standard, but evolved toward this as there
was no "enforcement" pressure. At least with this, you can read an individual
module. This approach does interfere with refactoring: when you move code
between modules, now you have to reformat it as well.
- Team has a style and sticks to it. This is the ideal for XP. Since
XP practices collective code ownership, it makes sense as well.
I've seen two group styles in determining this. The first type group has a
huge battle at the beginning of the project with heated arguments over spaces
and braces, but converges on a group style. The second group has no fight, but
builds no group ethic either; they end up with "whatever's right for the code
you're in". I'm not sure how to lead the second type along.
What coding style should be used? In the most recent project where I
participated in defining this (for Java) we had a 6-page summary of
Sun's Java coding
conventions extended with the
JavaBeans naming
conventions. I believe we could probably get it down to a page of annotated
code just as effectively. Perhaps even the page wouldn't be needed with the peer
pressure of constant pairing and refactoring.
Conclusion
We've discussed several practices of XP, and some of the alternative choices
possible.
- Code Ownership: Who can change an object that needs to change? XP
says "collective code ownership". If a team is not XP, this may well be
problematic.
- Integration: How and when does a team ensure everybody's code works
together? XP says "continuous integration". If a team is not XP, I believe
they should still strive toward as frequent an integration as possible.
- Workspace: How should a team be physically arranged? XP says "open
workspace." If a team is not XP, I favor offices, but with attention to the
team's communication paths.
- Release Schedule: How often should a team release their product? XP
says "small releases". If a team is not XP, I think this is still a useful
target, but probably harder for them to hit.
- Coding Standard: How should the code be written? XP says "team must
share a standard". If a team is not XP, I think a team standard is still
appropriate.
Resources
[Written 2-15-2000.]
|