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.]
|