Agile goals, fragile practices
Matt is a team leader and agile process mentor in London, and Doug is the founder of ICONIX Software Engineering. They are the authors of Extreme Programming Refactored: The Case Against XP (Apress, 2003). Doug can be contacted at [email protected], and Matt can be contacted at http://www.softwarereality.com/.
Any one practice doesn't stand well on its own (with the possible exception of testing). They require the other practices to keep them in balance.
Kent Beck, Extreme Programming Explained: Embrace Change
Well, from my experience, most teams that say they're doing XP don't actually do the practices.
Alistair Cockburn, http://www.c2.com/cgi/wiki?XpAndTheCmm
Houston, we have a problem.
Jim Lovell, Apollo 13
Software development processes are regarded by many programmers with a level of caution sometimes bordering on suspicion. The number of failed projects in the software industry is proof enough that some form of best practice guidance is needed to reduce the number of "death march" projects; see Death March: The Complete Software Developer's Guide to Surviving "Mission Impossible" Projects, by Edward Yourdon (Prentice Hall, 1999). Ironically, extreme programming (XP)a recent addition to the growing list of software processes and the industry's latest "silver bullet"causes more problems than it solves. It's a shame, because extreme programming contains some very good ideas. Unfortunately, it also contains some pretty awful ones.
We knew there were problems with XP when we started writing Extreme Programming Refactored (Apress, 2003). However, something surprising happened when word got out that we were writing about some of XP's pitfalls. People started e-mailing us true stories of problems they were experiencing on XP projects. In fact, we received so many of these contributions that we worked them into the book as a series of sidebars, which we called "Voice of eXPerience" (VoXP).
XP consists of 12 highly interdependent practices. However, each individual practice does not stand up well on its own: Each relies on at least one other practice to support it. So, tailoring XP is problematic, at best, and requires an in-depth understanding of the dynamics that exist between each of the 12 practices.
Just like too much coupling in a software design, too much coupling in a software process can cause problems as well. One factor that can't be ignored is that many programmers are attracted to XP because they believe they can avoid documentation and up-front design and still be successful. These folks are almost certainly not going to be prepared for the level of discipline required to stick to all of the XP processes. So, let's take a look at some of the ways XP practices depend on each other (and the problems that these dependencies can cause).
No Detailed Written Requirements
XP's requirements documentation consists of handwritten story cards. Each card consists of a sentence or two describing a feature, aspect, or behavior of the systema "user story." Stories are a mixture of behavioral requirements (similar to very lightweight use cases), data rules, and business logic. The data rules (for instance, "Value X cannot exceed limit Y") translate well to unit tests, because the test can be written simply to validate that the stated rule is never broken. However, user stories as an overall requirements capture system are problematic because they don't contain enough detail. They are also a bit too "free-form" and, in larger projects, need to be tailored into something more structured.
Also, user stories are considered to be transient. As the project progresses, customers are expected to write executable tests in place of stories. Requirements are generally not documented in any detail; instead, the details are left in the customer's brainthe theory being that the programmers can ask the customer for the details while they're programming the one-sentence story. As you can imagine, this places a huge burden on on-site customers, who are expected to carry around all 1000 requirements in their head and be able to recall each one at a moment's notice.
The lack of detailed requirements elicitation during the exploration phase also means that the design cannot be "pinned down" early in the project. This is compensated for with the practice of emergent design.
XP follows the YAGNI principle"You Ain't Gonna Need It." That is, only enough code (and design) to get the current feature working is ever written. In Extreme Programming Installed (Addison-Wesley, 2003), Ron Jeffries sums up the XP approach to design rather well:
Get a few people together and start sketching out the design. Ten minutes is idealhalf an hour is the most time you spend to do this. After that, the best thing to do is to let the code participate in the design sessionmove to the machine and start typing in code.
This "ten minutes of up-front design is enough" approach is central to XP's design philosophy. However, it is also blatantly ignoring the benefits that we get from doing an up-front design. The choice here is between getting initial results quickly (the XP way), but extending the overall length of the project (because of all the rewriting needed), versus delaying the initial delivery of working software slightly but getting the overall project done more quickly (because each part of the system only had to be written once).
Typical benefits of doing an up-front design are:
- Design clarity.
- Providing breathing space to let ideas gestate and develop before you risk getting bogged down in code.
- Defining interfaces early on, which helps teams to work in parallel.
- Making changes in a class model is easier than making the same changes in code.
- Making subsequent changes easier, more agile, because design diagrams give the team a high-level view of the design (for example, a logical view that is separate from specific implementation details).
Emergent design is (ironically) a heavyweight approach to software development. It is also high risk because there is the added danger that the code will disintegrate into a spaghetti mess of hacked-about code, rewritten as the design evolves. In XP, this danger is compensated for with the practice of constant refactoring.
Constant Refactoring After Programming
Refactoring is the practice of improving the design of existing code. By paying little attention to up-front design and focusing on getting something up and running as soon as possible, XP guarantees there will be lots of existing code that needs to have its design improved. To us, this seems to be a giant step backwards.
So, in the XP world, a heavy burden is placed upon refactoring because there just isn't enough up-front design. The burden is so heavy that this practice becomes constant refactoring: That is, a permanent eye needs to be kept on possible refactoring opportunities as the design evolves. If the team doesn't do this collectively, the project swiftly degenerates, and instead of emergent design, you get emergent entropy.
For instance, David Van Der Klauw, one of our VoXP correspondents, reported this:
Our unit tests were made up of two functions per test. The first function called the second function and outputted the name, description, and pass/fail result. The second function simply returned true or false. The task for our pair was to add unit testing for a new menu condition that would affect eight menu items.
My partner, a junior, claimed he knew the code well and jumped straight to some testing code with eight blocks of code. I didn't like it and said that all eight checks should be done in the one function, but I was told that this was the simplest thing possible.
Now our task was to do the simplest thing possible, so my partner duplicated the 8 tests, edited all 16 to cover the new condition, green-screened it, and checked it in. Our highlight at the next stand-up meeting was that "we have added eight new tests." Everyone clapped, but I was not impressed.
Later that week someone discovered that the function tested by our 16 tests was not actually called by the UI in determining menu item visibility. Therefore, the highlight at that stand-up meeting was that they "were able to YAGNI 16 tests." Everyone clapped.
Somehow, two XP highlights were a lowlight to me.
Refactoring also runs the risk of introducing bugs into existing code. If you're extracting methods, introducing parameter classes, and generally moving things around, some pretty insidious bugs can quickly move in and make themselves at home. In XP, this danger is compensated for with the (heavyweight) practice of constant unit testing.
Unit Testing: Design After First Testing
In XP, refactoring must take place in short baby steps: Make one small change, run the unit tests to get some assurance that you haven't broken anything, make another small change, and so on. In fact, because you're supposed to write the tests before you write the code in XP, the tests are sometimes considered to be the design.
This infinite loop of writing tests, writing code, running tests, and then refactoring is one of the reasons we describe the whole emergent design process as heavyweight: We've found it easier to spend time producing an up-front design, then produce the code to that design. This leaves little need for refactoring of existing code, and you don't have to write tests for code that you're going to throw away.
Having said that, unit testing is useful in everyday coding (not just in XP)and we're definitely in favor of unit testing. However, as a safety net for test-first design and constant refactoring, unit tests leave a critical area uncovereddesign correctness.
The problem is that unit tests catch certain types of code-level bugs, but they don't catch "wrongness" of a design. Design correctness is a highly subjective thing, and arguments rage on Internet forums over the validity of various design patterns (particularly when it comes to designing enterprise systems). To catch a design error, you really need a human to be involved.
The problem is made worse when the vitally important up-front design stage is skipped over (as in XP). In XP, the design is being evolved throughout the project. If one person evolves a design on his own, he quickly becomes stale and may start introducing some serious design errors (even though all the tests still pass 100 percent).
In XP, this danger is compensated for with the human equivalent of a design unit testerpair programmers.
By now, you've probably heard stories about how great pair programming is and how the poor lonely programmer doesn't have to be lonely any more. (Recent XP hype even implies that programming alone is an indication of a genetic defect; see "The New X-Men," by Martha Baer, Wired, September 2003). But here's e-mail that one of our VoXP correspondents sent to us:
I've just joined a project using XP. I really wished I had some critical information before jumping in. The pair programming is mind numbing. With this XP stuff, software development is no longer a professional occupation, it's just another type of assembly-line work. We're herded into a small room like telemarketers. Actually, I bet telemarketers have a better work environment.
So, if your project buys into the XP hype but your programmers don't like to be forced to "pair up" for the entire day, every day, every week of your project, you might just have a problem.
One of the issues addressed by pair programming is that of specialization. In any project (XP or otherwise), it's easy for programmers to become responsible for individual parts of the system. As time goes on, each programmer becomes the only person that knows anything about that part of the system. This is especially a danger in XP because there's no detailed design documentation (at a level of abstraction higher than unit tests) to bind everything together and provide details on how each part of the system works.
XP addresses this problem with pair rotationthat is, requiring that each programmer pair up with a different person several times a day. The theory is that programmers then get exposed to different areas of the system. Though this may seem like a good idea, it's idealistic. There is the problem of accountability. If some code is badly written or has a serious bug, who's responsible? How do you root out the "bad apple"in short, who gets fired?
XP appears to fix this problem by blithely ignoring itby making nobody responsible. In other words, everybody on the team "owns" the code as a sort of autonomous collective.
Collective ownership is a double-edged sword. On one hand, if everyone is responsible for the entire codebase then crufty code does not stay crufty for longsomeone will find it and refactor it. On the other hand, collective ownership also means that no one is really responsible for anything.
Encouraging pairs to jump in and change any piece of code could also cause problems. If a design is evolving in one direction, another pair may not be party to this. So they may refactor code in a different direction, undoing the work that has been made in the previous direction. This would be a sign that the level of communication on the project is slippinganother case where XPers must pay constant attention to the practices to avoid problems slipping in.
In fact, communication is one of the issues that collective ownership is intended to addressif the project has a high level of communication, then (the theory goes) less information needs to be written down in the form of specifications. Of course, the problem then is that the team may start to code something that is far from what the customer (or end user) either wants or needs. In XP, this danger is compensated for with a walking, talking, mind-changing spec, empowered to make snap decisions that can change the course of the whole projectthe on-site customer representative.
XP offloads responsibility for many aspects of software projects onto on-site customers. As a result, customers are one of the biggest single risk factors in an XP project. How much responsibility gets offloaded to the customer in XP? Here's a list that Arie van Deursen compiled in "Customer Involvement in Extreme Programming. XP 2001 Workshop Report" (http://portal.acm.org/ citation.cfm?id=505550&jmp=cit&dl=GUIDE&dl=ACM):
Understanding customer wishes, maintaining regular contact with end users, and balancing their potentially conflicting interests.
Talking to developers, clarifying feature requests when needed, and understanding some of the developer's technical concerns.
Specifying functional tests for user stories, and verifying that these tests run correctly.
Participating in the planning of iterations and releases.
Maintaining good contact with management, explaining progress, and justifying time spent with the development team.
Being a customer requires a number of skills that are independent of the application domain. These include balancing potentially conflicting end-user needs, experience in requirements gathering, reporting to upper management, controlling the budget, and checking for forgotten requirements.
Originally, all this was supposed to be done by a single individual. Not surprisingly, even XP's creator, Kent Beck, now admits that this was "an error of early XP thinking." Now, XP says that projects should have "customer teams." But, if the customer team doesn't "speak with a single voice," massive problems arise because so much in XP relies on face-to-face communication.
One of the reasons for including on-site customers in XP is to increase the project's "agility." That is, customers see the product as early as possiblewhile it's still being writtenand get to give immediate feedback. This may result in changing requirements, as customers change their minds having seen the way the product is shaping up. Also, decisions are deliberately left until as late as possible, so that customers can change their minds as late as possible.
This approach could lead to problems with requirements and design specifications quickly becoming out of date. In XP, this danger is compensated for by declaring requirements documentation (the user stories) to be transient, and for the detail to be contained either in the customer's head ("promises for future conversations") or as scripted tests that the customer must write. In other words, XP has no detailed written requirementswhich brings us neatly back to where we started...
The irony of XP is that the problems that it attempts to address are also the same problems that it seems to cause. The circular irony of XP is almost poetic in its simplistic beauty.
XP is often sold on the basis that it's a "lightweight, nonprescriptive" process. It's "lightweight" because it does not involve many practices (just 12). However, as we've seen, XP requires unfailing discipline from every member of the team throughout the project. This makes it anything but lightweight. Additionally, the 12 practices are so tightly dependent on each other that tailoring XP (or skipping a few of the practices) can be tricky. This makes XP anything but nonprescriptive.